Committed by
Gerrit Code Review
GUI fixes/breaks.
Change-Id: Ic5c8b087cc32506162153b2756a677c7d9e3bdd7
Showing
6 changed files
with
250 additions
and
87 deletions
| ... | @@ -66,7 +66,7 @@ import static org.slf4j.LoggerFactory.getLogger; | ... | @@ -66,7 +66,7 @@ import static org.slf4j.LoggerFactory.getLogger; |
| 66 | public class DefaultTopologyProvider extends AbstractProvider | 66 | public class DefaultTopologyProvider extends AbstractProvider |
| 67 | implements TopologyProvider { | 67 | implements TopologyProvider { |
| 68 | 68 | ||
| 69 | - private static final int MAX_THREADS = 8; | 69 | + private static final int MAX_THREADS = 32; |
| 70 | private static final int DEFAULT_MAX_EVENTS = 1000; | 70 | private static final int DEFAULT_MAX_EVENTS = 1000; |
| 71 | private static final int DEFAULT_MAX_IDLE_MS = 10; | 71 | private static final int DEFAULT_MAX_IDLE_MS = 10; |
| 72 | private static final int DEFAULT_MAX_BATCH_MS = 50; | 72 | private static final int DEFAULT_MAX_BATCH_MS = 50; | ... | ... |
tools/test/topos/topo-200sw-linkalarm.py
0 → 100644
| 1 | + | ||
| 2 | +from mininet.topo import Topo | ||
| 3 | + | ||
| 4 | +class MyTopo( Topo ): | ||
| 5 | + "10 'floating' switch topology" | ||
| 6 | + | ||
| 7 | + def __init__( self ): | ||
| 8 | + # Initialize topology | ||
| 9 | + Topo.__init__( self ) | ||
| 10 | + | ||
| 11 | + sw_list = [] | ||
| 12 | + swC = self.addSwitch('sc', dpid = 'ffffffff00000001') | ||
| 13 | + | ||
| 14 | + for i in range(1, 201): | ||
| 15 | + switch=self.addSwitch('s'+str(i), dpid = str(i).zfill(16)) | ||
| 16 | + self.addLink(switch,swC) | ||
| 17 | + | ||
| 18 | + sw_list.append(switch) | ||
| 19 | + | ||
| 20 | +topos = { 'mytopo': ( lambda: MyTopo() ) } |
| ... | @@ -33,6 +33,7 @@ import org.onlab.onos.net.intent.PathIntent; | ... | @@ -33,6 +33,7 @@ import org.onlab.onos.net.intent.PathIntent; |
| 33 | import org.onlab.onos.net.intent.PointToPointIntent; | 33 | import org.onlab.onos.net.intent.PointToPointIntent; |
| 34 | import org.onlab.onos.net.link.LinkService; | 34 | import org.onlab.onos.net.link.LinkService; |
| 35 | 35 | ||
| 36 | +import java.util.ArrayList; | ||
| 36 | import java.util.HashSet; | 37 | import java.util.HashSet; |
| 37 | import java.util.List; | 38 | import java.util.List; |
| 38 | import java.util.Set; | 39 | import java.util.Set; |
| ... | @@ -73,15 +74,17 @@ public class TopologyViewIntentFilter { | ... | @@ -73,15 +74,17 @@ public class TopologyViewIntentFilter { |
| 73 | * | 74 | * |
| 74 | * @param hosts set of hosts to query by | 75 | * @param hosts set of hosts to query by |
| 75 | * @param devices set of devices to query by | 76 | * @param devices set of devices to query by |
| 77 | + * @param sourceIntents collection of intents to search | ||
| 76 | * @return set of intents that 'match' all hosts and devices given | 78 | * @return set of intents that 'match' all hosts and devices given |
| 77 | */ | 79 | */ |
| 78 | - Set<Intent> findPathIntents(Set<Host> hosts, Set<Device> devices) { | 80 | + List<Intent> findPathIntents(Set<Host> hosts, Set<Device> devices, |
| 81 | + Iterable<Intent> sourceIntents) { | ||
| 79 | // Derive from this the set of edge connect points. | 82 | // Derive from this the set of edge connect points. |
| 80 | Set<ConnectPoint> edgePoints = getEdgePoints(hosts); | 83 | Set<ConnectPoint> edgePoints = getEdgePoints(hosts); |
| 81 | 84 | ||
| 82 | // Iterate over all intents and produce a set that contains only those | 85 | // Iterate over all intents and produce a set that contains only those |
| 83 | // intents that target all selected hosts or derived edge connect points. | 86 | // intents that target all selected hosts or derived edge connect points. |
| 84 | - return getIntents(hosts, devices, edgePoints); | 87 | + return getIntents(hosts, devices, edgePoints, sourceIntents); |
| 85 | } | 88 | } |
| 86 | 89 | ||
| 87 | 90 | ||
| ... | @@ -94,10 +97,11 @@ public class TopologyViewIntentFilter { | ... | @@ -94,10 +97,11 @@ public class TopologyViewIntentFilter { |
| 94 | return edgePoints; | 97 | return edgePoints; |
| 95 | } | 98 | } |
| 96 | 99 | ||
| 97 | - // Produces a set of intents that target all selected hosts, devices or connect points. | 100 | + // Produces a list of intents that target all selected hosts, devices or connect points. |
| 98 | - private Set<Intent> getIntents(Set<Host> hosts, Set<Device> devices, | 101 | + private List<Intent> getIntents(Set<Host> hosts, Set<Device> devices, |
| 99 | - Set<ConnectPoint> edgePoints) { | 102 | + Set<ConnectPoint> edgePoints, |
| 100 | - Set<Intent> intents = new HashSet<>(); | 103 | + Iterable<Intent> sourceIntents) { |
| 104 | + List<Intent> intents = new ArrayList<>(); | ||
| 101 | if (hosts.isEmpty() && devices.isEmpty()) { | 105 | if (hosts.isEmpty() && devices.isEmpty()) { |
| 102 | return intents; | 106 | return intents; |
| 103 | } | 107 | } |
| ... | @@ -105,7 +109,7 @@ public class TopologyViewIntentFilter { | ... | @@ -105,7 +109,7 @@ public class TopologyViewIntentFilter { |
| 105 | Set<OpticalConnectivityIntent> opticalIntents = new HashSet<>(); | 109 | Set<OpticalConnectivityIntent> opticalIntents = new HashSet<>(); |
| 106 | 110 | ||
| 107 | // Search through all intents and see if they are relevant to our search. | 111 | // Search through all intents and see if they are relevant to our search. |
| 108 | - for (Intent intent : intentService.getIntents()) { | 112 | + for (Intent intent : sourceIntents) { |
| 109 | if (intentService.getIntentState(intent.id()) == INSTALLED) { | 113 | if (intentService.getIntentState(intent.id()) == INSTALLED) { |
| 110 | boolean isRelevant = false; | 114 | boolean isRelevant = false; |
| 111 | if (intent instanceof HostToHostIntent) { | 115 | if (intent instanceof HostToHostIntent) { |
| ... | @@ -140,7 +144,7 @@ public class TopologyViewIntentFilter { | ... | @@ -140,7 +144,7 @@ public class TopologyViewIntentFilter { |
| 140 | } | 144 | } |
| 141 | 145 | ||
| 142 | // Indicates whether the specified intent involves all of the given hosts. | 146 | // Indicates whether the specified intent involves all of the given hosts. |
| 143 | - private boolean isIntentRelevantToHosts(HostToHostIntent intent, Set<Host> hosts) { | 147 | + private boolean isIntentRelevantToHosts(HostToHostIntent intent, Iterable<Host> hosts) { |
| 144 | for (Host host : hosts) { | 148 | for (Host host : hosts) { |
| 145 | HostId id = host.id(); | 149 | HostId id = host.id(); |
| 146 | // Bail if intent does not involve this host. | 150 | // Bail if intent does not involve this host. |
| ... | @@ -152,7 +156,7 @@ public class TopologyViewIntentFilter { | ... | @@ -152,7 +156,7 @@ public class TopologyViewIntentFilter { |
| 152 | } | 156 | } |
| 153 | 157 | ||
| 154 | // Indicates whether the specified intent involves all of the given devices. | 158 | // Indicates whether the specified intent involves all of the given devices. |
| 155 | - private boolean isIntentRelevantToDevices(Intent intent, Set<Device> devices) { | 159 | + private boolean isIntentRelevantToDevices(Intent intent, Iterable<Device> devices) { |
| 156 | List<Intent> installables = intentService.getInstallableIntents(intent.id()); | 160 | List<Intent> installables = intentService.getInstallableIntents(intent.id()); |
| 157 | for (Device device : devices) { | 161 | for (Device device : devices) { |
| 158 | if (!isIntentRelevantToDevice(installables, device)) { | 162 | if (!isIntentRelevantToDevice(installables, device)) { |
| ... | @@ -192,7 +196,8 @@ public class TopologyViewIntentFilter { | ... | @@ -192,7 +196,8 @@ public class TopologyViewIntentFilter { |
| 192 | return false; | 196 | return false; |
| 193 | } | 197 | } |
| 194 | 198 | ||
| 195 | - private boolean isIntentRelevant(PointToPointIntent intent, Set<ConnectPoint> edgePoints) { | 199 | + private boolean isIntentRelevant(PointToPointIntent intent, |
| 200 | + Iterable<ConnectPoint> edgePoints) { | ||
| 196 | for (ConnectPoint point : edgePoints) { | 201 | for (ConnectPoint point : edgePoints) { |
| 197 | // Bail if intent does not involve this edge point. | 202 | // Bail if intent does not involve this edge point. |
| 198 | if (!point.equals(intent.egressPoint()) && | 203 | if (!point.equals(intent.egressPoint()) && |
| ... | @@ -205,7 +210,7 @@ public class TopologyViewIntentFilter { | ... | @@ -205,7 +210,7 @@ public class TopologyViewIntentFilter { |
| 205 | 210 | ||
| 206 | // Indicates whether the specified intent involves all of the given edge points. | 211 | // Indicates whether the specified intent involves all of the given edge points. |
| 207 | private boolean isIntentRelevant(MultiPointToSinglePointIntent intent, | 212 | private boolean isIntentRelevant(MultiPointToSinglePointIntent intent, |
| 208 | - Set<ConnectPoint> edgePoints) { | 213 | + Iterable<ConnectPoint> edgePoints) { |
| 209 | for (ConnectPoint point : edgePoints) { | 214 | for (ConnectPoint point : edgePoints) { |
| 210 | // Bail if intent does not involve this edge point. | 215 | // Bail if intent does not involve this edge point. |
| 211 | if (!point.equals(intent.egressPoint()) && | 216 | if (!point.equals(intent.egressPoint()) && |
| ... | @@ -218,7 +223,7 @@ public class TopologyViewIntentFilter { | ... | @@ -218,7 +223,7 @@ public class TopologyViewIntentFilter { |
| 218 | 223 | ||
| 219 | // Indicates whether the specified intent involves all of the given edge points. | 224 | // Indicates whether the specified intent involves all of the given edge points. |
| 220 | private boolean isIntentRelevant(OpticalConnectivityIntent opticalIntent, | 225 | private boolean isIntentRelevant(OpticalConnectivityIntent opticalIntent, |
| 221 | - Set<Intent> intents) { | 226 | + Iterable<Intent> intents) { |
| 222 | Link ccSrc = getFirstLink(opticalIntent.getSrc(), false); | 227 | Link ccSrc = getFirstLink(opticalIntent.getSrc(), false); |
| 223 | Link ccDst = getFirstLink(opticalIntent.getDst(), true); | 228 | Link ccDst = getFirstLink(opticalIntent.getDst(), true); |
| 224 | 229 | ... | ... |
| ... | @@ -676,13 +676,16 @@ public abstract class TopologyViewMessages { | ... | @@ -676,13 +676,16 @@ public abstract class TopologyViewMessages { |
| 676 | List<Intent> installables = intentService.getInstallableIntents(intent.id()); | 676 | List<Intent> installables = intentService.getInstallableIntents(intent.id()); |
| 677 | if (installables != null) { | 677 | if (installables != null) { |
| 678 | for (Intent installable : installables) { | 678 | for (Intent installable : installables) { |
| 679 | - String cls = isOptical ? trafficClass.type + " optical" : trafficClass.type; | 679 | + String type = isOptical ? trafficClass.type + " optical" : trafficClass.type; |
| 680 | if (installable instanceof PathIntent) { | 680 | if (installable instanceof PathIntent) { |
| 681 | - classifyLinks(cls, biLinks, ((PathIntent) installable).path().links()); | 681 | + classifyLinks(type, biLinks, trafficClass.showTraffic, |
| 682 | + ((PathIntent) installable).path().links()); | ||
| 682 | } else if (installable instanceof LinkCollectionIntent) { | 683 | } else if (installable instanceof LinkCollectionIntent) { |
| 683 | - classifyLinks(cls, biLinks, ((LinkCollectionIntent) installable).links()); | 684 | + classifyLinks(type, biLinks, trafficClass.showTraffic, |
| 685 | + ((LinkCollectionIntent) installable).links()); | ||
| 684 | } else if (installable instanceof OpticalPathIntent) { | 686 | } else if (installable instanceof OpticalPathIntent) { |
| 685 | - classifyLinks(cls, biLinks, ((OpticalPathIntent) installable).path().links()); | 687 | + classifyLinks(type, biLinks, trafficClass.showTraffic, |
| 688 | + ((OpticalPathIntent) installable).path().links()); | ||
| 686 | } | 689 | } |
| 687 | } | 690 | } |
| 688 | } | 691 | } |
| ... | @@ -695,12 +698,14 @@ public abstract class TopologyViewMessages { | ... | @@ -695,12 +698,14 @@ public abstract class TopologyViewMessages { |
| 695 | // Adds the link segments (path or tree) associated with the specified | 698 | // Adds the link segments (path or tree) associated with the specified |
| 696 | // connectivity intent | 699 | // connectivity intent |
| 697 | private void classifyLinks(String type, Map<LinkKey, BiLink> biLinks, | 700 | private void classifyLinks(String type, Map<LinkKey, BiLink> biLinks, |
| 698 | - Iterable<Link> links) { | 701 | + boolean showTraffic, Iterable<Link> links) { |
| 699 | if (links != null) { | 702 | if (links != null) { |
| 700 | for (Link link : links) { | 703 | for (Link link : links) { |
| 701 | BiLink biLink = addLink(biLinks, link); | 704 | BiLink biLink = addLink(biLinks, link); |
| 702 | if (isInfrastructureEgress(link)) { | 705 | if (isInfrastructureEgress(link)) { |
| 706 | + if (showTraffic) { | ||
| 703 | biLink.addLoad(statService.load(link)); | 707 | biLink.addLoad(statService.load(link)); |
| 708 | + } | ||
| 704 | biLink.addClass(type); | 709 | biLink.addClass(type); |
| 705 | } | 710 | } |
| 706 | } | 711 | } |
| ... | @@ -862,12 +867,18 @@ public abstract class TopologyViewMessages { | ... | @@ -862,12 +867,18 @@ public abstract class TopologyViewMessages { |
| 862 | 867 | ||
| 863 | // Auxiliary carrier of data for requesting traffic message. | 868 | // Auxiliary carrier of data for requesting traffic message. |
| 864 | protected class TrafficClass { | 869 | protected class TrafficClass { |
| 870 | + public final boolean showTraffic; | ||
| 865 | public final String type; | 871 | public final String type; |
| 866 | - public final Set<Intent> intents; | 872 | + public final Iterable<Intent> intents; |
| 873 | + | ||
| 874 | + TrafficClass(String type, Iterable<Intent> intents) { | ||
| 875 | + this(type, intents, false); | ||
| 876 | + } | ||
| 867 | 877 | ||
| 868 | - TrafficClass(String type, Set<Intent> intents) { | 878 | + TrafficClass(String type, Iterable<Intent> intents, boolean showTraffic) { |
| 869 | this.type = type; | 879 | this.type = type; |
| 870 | this.intents = intents; | 880 | this.intents = intents; |
| 881 | + this.showTraffic = showTraffic; | ||
| 871 | } | 882 | } |
| 872 | } | 883 | } |
| 873 | 884 | ... | ... |
| ... | @@ -90,7 +90,8 @@ public class TopologyViewWebSocket | ... | @@ -90,7 +90,8 @@ public class TopologyViewWebSocket |
| 90 | 90 | ||
| 91 | private static final String APP_ID = "org.onlab.onos.gui"; | 91 | private static final String APP_ID = "org.onlab.onos.gui"; |
| 92 | 92 | ||
| 93 | - private static final long TRAFFIC_FREQUENCY_SEC = 2000; | 93 | + private static final long TRAFFIC_FREQUENCY = 2000; |
| 94 | + private static final long SUMMARY_FREQUENCY = 30000; | ||
| 94 | 95 | ||
| 95 | private static final Comparator<? super ControllerNode> NODE_COMPARATOR = | 96 | private static final Comparator<? super ControllerNode> NODE_COMPARATOR = |
| 96 | new Comparator<ControllerNode>() { | 97 | new Comparator<ControllerNode>() { |
| ... | @@ -103,9 +104,9 @@ public class TopologyViewWebSocket | ... | @@ -103,9 +104,9 @@ public class TopologyViewWebSocket |
| 103 | 104 | ||
| 104 | private final Timer timer = new Timer("topology-view"); | 105 | private final Timer timer = new Timer("topology-view"); |
| 105 | 106 | ||
| 106 | - private static final int MAX_EVENTS = 500; | 107 | + private static final int MAX_EVENTS = 1000; |
| 107 | - private static final int MAX_BATCH_MS = 1000; | 108 | + private static final int MAX_BATCH_MS = 5000; |
| 108 | - private static final int MAX_IDLE_MS = 500; | 109 | + private static final int MAX_IDLE_MS = 1000; |
| 109 | 110 | ||
| 110 | private final ApplicationId appId; | 111 | private final ApplicationId appId; |
| 111 | 112 | ||
| ... | @@ -122,15 +123,23 @@ public class TopologyViewWebSocket | ... | @@ -122,15 +123,23 @@ public class TopologyViewWebSocket |
| 122 | 123 | ||
| 123 | private final EventAccumulator eventAccummulator = new InternalEventAccummulator(); | 124 | private final EventAccumulator eventAccummulator = new InternalEventAccummulator(); |
| 124 | 125 | ||
| 125 | - private boolean summaryEnabled = true; | ||
| 126 | private TimerTask trafficTask; | 126 | private TimerTask trafficTask; |
| 127 | private ObjectNode trafficEvent; | 127 | private ObjectNode trafficEvent; |
| 128 | 128 | ||
| 129 | + private TimerTask summaryTask; | ||
| 130 | + private ObjectNode summaryEvent; | ||
| 131 | + | ||
| 129 | private long lastActive = System.currentTimeMillis(); | 132 | private long lastActive = System.currentTimeMillis(); |
| 130 | private boolean listenersRemoved = false; | 133 | private boolean listenersRemoved = false; |
| 131 | 134 | ||
| 132 | private TopologyViewIntentFilter intentFilter; | 135 | private TopologyViewIntentFilter intentFilter; |
| 133 | 136 | ||
| 137 | + // Current selection context | ||
| 138 | + private Set<Host> selectedHosts; | ||
| 139 | + private Set<Device> selectedDevices; | ||
| 140 | + private List<Intent> selectedIntents; | ||
| 141 | + private int currentIntentIndex = -1; | ||
| 142 | + | ||
| 134 | /** | 143 | /** |
| 135 | * Creates a new web-socket for serving data to GUI topology view. | 144 | * Creates a new web-socket for serving data to GUI topology view. |
| 136 | * | 145 | * |
| ... | @@ -204,7 +213,6 @@ public class TopologyViewWebSocket | ... | @@ -204,7 +213,6 @@ public class TopologyViewWebSocket |
| 204 | processMessage((ObjectNode) mapper.reader().readTree(data)); | 213 | processMessage((ObjectNode) mapper.reader().readTree(data)); |
| 205 | } catch (Exception e) { | 214 | } catch (Exception e) { |
| 206 | log.warn("Unable to parse GUI request {} due to {}", data, e); | 215 | log.warn("Unable to parse GUI request {} due to {}", data, e); |
| 207 | - log.warn("Boom!!!!", e); | ||
| 208 | } | 216 | } |
| 209 | } | 217 | } |
| 210 | 218 | ||
| ... | @@ -221,19 +229,29 @@ public class TopologyViewWebSocket | ... | @@ -221,19 +229,29 @@ public class TopologyViewWebSocket |
| 221 | } else if (type.equals("addMultiSourceIntent")) { | 229 | } else if (type.equals("addMultiSourceIntent")) { |
| 222 | createMultiSourceIntent(event); | 230 | createMultiSourceIntent(event); |
| 223 | 231 | ||
| 224 | - } else if (type.equals("requestTraffic")) { | 232 | + } else if (type.equals("requestRelatedIntents")) { |
| 225 | - requestTraffic(event); | 233 | + requestRelatedIntents(event); |
| 234 | + } else if (type.equals("requestNextRelatedIntent")) { | ||
| 235 | + requestNextRelatedIntent(event); | ||
| 236 | + } else if (type.equals("requestSelectedIntentTraffic")) { | ||
| 237 | + requestSelectedIntentTraffic(event); | ||
| 238 | + | ||
| 226 | } else if (type.equals("requestAllTraffic")) { | 239 | } else if (type.equals("requestAllTraffic")) { |
| 227 | requestAllTraffic(event); | 240 | requestAllTraffic(event); |
| 241 | + startTrafficMonitoring(event); | ||
| 242 | + | ||
| 228 | } else if (type.equals("requestDeviceLinkFlows")) { | 243 | } else if (type.equals("requestDeviceLinkFlows")) { |
| 229 | requestDeviceLinkFlows(event); | 244 | requestDeviceLinkFlows(event); |
| 245 | + startTrafficMonitoring(event); | ||
| 246 | + | ||
| 230 | } else if (type.equals("cancelTraffic")) { | 247 | } else if (type.equals("cancelTraffic")) { |
| 231 | cancelTraffic(event); | 248 | cancelTraffic(event); |
| 232 | 249 | ||
| 233 | } else if (type.equals("requestSummary")) { | 250 | } else if (type.equals("requestSummary")) { |
| 234 | requestSummary(event); | 251 | requestSummary(event); |
| 252 | + startSummaryMonitoring(event); | ||
| 235 | } else if (type.equals("cancelSummary")) { | 253 | } else if (type.equals("cancelSummary")) { |
| 236 | - cancelSummary(event); | 254 | + stopSummaryMonitoring(); |
| 237 | 255 | ||
| 238 | } else if (type.equals("equalizeMasters")) { | 256 | } else if (type.equals("equalizeMasters")) { |
| 239 | equalizeMasters(event); | 257 | equalizeMasters(event); |
| ... | @@ -324,8 +342,9 @@ public class TopologyViewWebSocket | ... | @@ -324,8 +342,9 @@ public class TopologyViewWebSocket |
| 324 | new HostToHostIntent(appId, one, two, | 342 | new HostToHostIntent(appId, one, two, |
| 325 | DefaultTrafficSelector.builder().build(), | 343 | DefaultTrafficSelector.builder().build(), |
| 326 | DefaultTrafficTreatment.builder().build()); | 344 | DefaultTrafficTreatment.builder().build()); |
| 327 | - startMonitoring(event); | 345 | + |
| 328 | intentService.submit(intent); | 346 | intentService.submit(intent); |
| 347 | + startMonitoringIntent(event, intent); | ||
| 329 | } | 348 | } |
| 330 | 349 | ||
| 331 | // Creates multi-source-to-single-dest intent. | 350 | // Creates multi-source-to-single-dest intent. |
| ... | @@ -348,10 +367,24 @@ public class TopologyViewWebSocket | ... | @@ -348,10 +367,24 @@ public class TopologyViewWebSocket |
| 348 | MultiPointToSinglePointIntent intent = | 367 | MultiPointToSinglePointIntent intent = |
| 349 | new MultiPointToSinglePointIntent(appId, selector, treatment, | 368 | new MultiPointToSinglePointIntent(appId, selector, treatment, |
| 350 | ingressPoints, dstHost.location()); | 369 | ingressPoints, dstHost.location()); |
| 351 | - startMonitoring(event); | 370 | + |
| 352 | intentService.submit(intent); | 371 | intentService.submit(intent); |
| 372 | + startMonitoringIntent(event, intent); | ||
| 353 | } | 373 | } |
| 354 | 374 | ||
| 375 | + | ||
| 376 | + private synchronized void startMonitoringIntent(ObjectNode event, Intent intent) { | ||
| 377 | + selectedHosts = new HashSet<>(); | ||
| 378 | + selectedDevices = new HashSet<>(); | ||
| 379 | + selectedIntents = new ArrayList<>(); | ||
| 380 | + selectedIntents.add(intent); | ||
| 381 | + currentIntentIndex = -1; | ||
| 382 | + requestNextRelatedIntent(event); | ||
| 383 | + requestSelectedIntentTraffic(event); | ||
| 384 | + } | ||
| 385 | + | ||
| 386 | + | ||
| 387 | + | ||
| 355 | private Set<ConnectPoint> getHostLocations(Set<HostId> hostIds) { | 388 | private Set<ConnectPoint> getHostLocations(Set<HostId> hostIds) { |
| 356 | Set<ConnectPoint> points = new HashSet<>(); | 389 | Set<ConnectPoint> points = new HashSet<>(); |
| 357 | for (HostId hostId : hostIds) { | 390 | for (HostId hostId : hostIds) { |
| ... | @@ -374,17 +407,15 @@ public class TopologyViewWebSocket | ... | @@ -374,17 +407,15 @@ public class TopologyViewWebSocket |
| 374 | } | 407 | } |
| 375 | 408 | ||
| 376 | 409 | ||
| 377 | - private synchronized long startMonitoring(ObjectNode event) { | 410 | + private synchronized long startTrafficMonitoring(ObjectNode event) { |
| 378 | - if (trafficTask != null) { | 411 | + stopTrafficMonitoring(); |
| 379 | - stopMonitoring(); | ||
| 380 | - } | ||
| 381 | trafficEvent = event; | 412 | trafficEvent = event; |
| 382 | trafficTask = new TrafficMonitor(); | 413 | trafficTask = new TrafficMonitor(); |
| 383 | - timer.schedule(trafficTask, TRAFFIC_FREQUENCY_SEC, TRAFFIC_FREQUENCY_SEC); | 414 | + timer.schedule(trafficTask, TRAFFIC_FREQUENCY, TRAFFIC_FREQUENCY); |
| 384 | return number(event, "sid"); | 415 | return number(event, "sid"); |
| 385 | } | 416 | } |
| 386 | 417 | ||
| 387 | - private synchronized void stopMonitoring() { | 418 | + private synchronized void stopTrafficMonitoring() { |
| 388 | if (trafficTask != null) { | 419 | if (trafficTask != null) { |
| 389 | trafficTask.cancel(); | 420 | trafficTask.cancel(); |
| 390 | trafficTask = null; | 421 | trafficTask = null; |
| ... | @@ -394,13 +425,13 @@ public class TopologyViewWebSocket | ... | @@ -394,13 +425,13 @@ public class TopologyViewWebSocket |
| 394 | 425 | ||
| 395 | // Subscribes for host traffic messages. | 426 | // Subscribes for host traffic messages. |
| 396 | private synchronized void requestAllTraffic(ObjectNode event) { | 427 | private synchronized void requestAllTraffic(ObjectNode event) { |
| 397 | - long sid = startMonitoring(event); | 428 | + long sid = startTrafficMonitoring(event); |
| 398 | sendMessage(trafficSummaryMessage(sid)); | 429 | sendMessage(trafficSummaryMessage(sid)); |
| 399 | } | 430 | } |
| 400 | 431 | ||
| 401 | private void requestDeviceLinkFlows(ObjectNode event) { | 432 | private void requestDeviceLinkFlows(ObjectNode event) { |
| 402 | ObjectNode payload = payload(event); | 433 | ObjectNode payload = payload(event); |
| 403 | - long sid = startMonitoring(event); | 434 | + long sid = startTrafficMonitoring(event); |
| 404 | 435 | ||
| 405 | // Get the set of selected hosts and their intents. | 436 | // Get the set of selected hosts and their intents. |
| 406 | ArrayNode ids = (ArrayNode) payload.path("ids"); | 437 | ArrayNode ids = (ArrayNode) payload.path("ids"); |
| ... | @@ -416,58 +447,122 @@ public class TopologyViewWebSocket | ... | @@ -416,58 +447,122 @@ public class TopologyViewWebSocket |
| 416 | } | 447 | } |
| 417 | 448 | ||
| 418 | 449 | ||
| 419 | - // Subscribes for host traffic messages. | 450 | + // Requests related intents message. |
| 420 | - private synchronized void requestTraffic(ObjectNode event) { | 451 | + private synchronized void requestRelatedIntents(ObjectNode event) { |
| 421 | ObjectNode payload = payload(event); | 452 | ObjectNode payload = payload(event); |
| 422 | if (!payload.has("ids")) { | 453 | if (!payload.has("ids")) { |
| 423 | return; | 454 | return; |
| 424 | } | 455 | } |
| 425 | 456 | ||
| 426 | - long sid = startMonitoring(event); | 457 | + long sid = number(event, "sid"); |
| 458 | + | ||
| 459 | + // Cancel any other traffic monitoring mode. | ||
| 460 | + stopTrafficMonitoring(); | ||
| 427 | 461 | ||
| 462 | + String hover = string(payload, "hover"); | ||
| 463 | + if (haveSelectedIntents()) { | ||
| 428 | // Get the set of selected hosts and their intents. | 464 | // Get the set of selected hosts and their intents. |
| 429 | ArrayNode ids = (ArrayNode) payload.path("ids"); | 465 | ArrayNode ids = (ArrayNode) payload.path("ids"); |
| 430 | - Set<Host> hosts = getHosts(ids); | 466 | + selectedHosts = getHosts(ids); |
| 431 | - Set<Device> devices = getDevices(ids); | 467 | + selectedDevices = getDevices(ids); |
| 432 | - Set<Intent> intents = intentFilter.findPathIntents(hosts, devices); | 468 | + selectedIntents = intentFilter.findPathIntents(selectedHosts, selectedDevices, |
| 469 | + intentService.getIntents()); | ||
| 470 | + currentIntentIndex = -1; | ||
| 471 | + | ||
| 472 | + // Send a message to highlight all links of all monitored intents. | ||
| 473 | + sendMessage(trafficMessage(sid, new TrafficClass("primary", selectedIntents))); | ||
| 474 | + } | ||
| 433 | 475 | ||
| 434 | - // If there is a hover node, include it in the hosts and find intents. | ||
| 435 | - String hover = string(payload, "hover"); | ||
| 436 | - Set<Intent> hoverIntents; | ||
| 437 | if (!isNullOrEmpty(hover)) { | 476 | if (!isNullOrEmpty(hover)) { |
| 438 | - addHover(hosts, devices, hover); | 477 | + // If there is a hover node, include it in the selection and find intents. |
| 439 | - hoverIntents = intentFilter.findPathIntents(hosts, devices); | 478 | + processExtendedSelection(sid, hover); |
| 440 | - intents.removeAll(hoverIntents); | 479 | + } |
| 480 | + } | ||
| 481 | + | ||
| 482 | + private boolean haveSelectedIntents() { | ||
| 483 | + return selectedIntents != null && !selectedIntents.isEmpty(); | ||
| 484 | + } | ||
| 485 | + | ||
| 486 | + private void processExtendedSelection(long sid, String hover) { | ||
| 487 | + Set<Host> hoverSelHosts = new HashSet<>(selectedHosts); | ||
| 488 | + Set<Device> hoverSelDevices = new HashSet<>(selectedDevices); | ||
| 489 | + addHover(hoverSelHosts, hoverSelDevices, hover); | ||
| 441 | 490 | ||
| 442 | - // Send an initial message to highlight all links of all monitored intents. | 491 | + List<Intent> primary = |
| 443 | - sendMessage(trafficMessage(sid, | 492 | + intentFilter.findPathIntents(hoverSelHosts, hoverSelDevices, |
| 444 | - new TrafficClass("primary", hoverIntents), | 493 | + selectedIntents); |
| 445 | - new TrafficClass("secondary", intents))); | 494 | + Set<Intent> secondary = new HashSet<>(selectedIntents); |
| 495 | + secondary.removeAll(primary); | ||
| 446 | 496 | ||
| 447 | - } else { | 497 | + // Send a message to highlight all links of all monitored intents. |
| 448 | - // Send an initial message to highlight all links of all monitored intents. | 498 | + sendMessage(trafficMessage(sid, new TrafficClass("primary", primary), |
| 449 | - sendMessage(trafficMessage(sid, new TrafficClass("primary", intents))); | 499 | + new TrafficClass("secondary", secondary))); |
| 500 | + } | ||
| 501 | + | ||
| 502 | + // Requests next of the related intents. | ||
| 503 | + private void requestNextRelatedIntent(ObjectNode event) { | ||
| 504 | + if (haveSelectedIntents()) { | ||
| 505 | + currentIntentIndex = (currentIntentIndex + 1) % selectedIntents.size(); | ||
| 506 | + Intent selectedIntent = selectedIntents.get(currentIntentIndex); | ||
| 507 | + log.info("Requested next intent {}", selectedIntent.id()); | ||
| 508 | + | ||
| 509 | + Set<Intent> primary = new HashSet<>(); | ||
| 510 | + primary.add(selectedIntent); | ||
| 511 | + | ||
| 512 | + Set<Intent> secondary = new HashSet<>(selectedIntents); | ||
| 513 | + secondary.remove(selectedIntent); | ||
| 514 | + | ||
| 515 | + // Send a message to highlight all links of the selected intent. | ||
| 516 | + sendMessage(trafficMessage(number(event, "sid"), | ||
| 517 | + new TrafficClass("primary", primary), | ||
| 518 | + new TrafficClass("secondary", secondary))); | ||
| 519 | + } | ||
| 520 | + } | ||
| 521 | + | ||
| 522 | + // Requests monitoring of traffic for the selected intent. | ||
| 523 | + private void requestSelectedIntentTraffic(ObjectNode event) { | ||
| 524 | + if (haveSelectedIntents()) { | ||
| 525 | + Intent selectedIntent = selectedIntents.get(currentIntentIndex); | ||
| 526 | + log.info("Requested traffic for selected {}", selectedIntent.id()); | ||
| 527 | + | ||
| 528 | + Set<Intent> primary = new HashSet<>(); | ||
| 529 | + primary.add(selectedIntent); | ||
| 530 | + | ||
| 531 | + // Send a message to highlight all links of the selected intent. | ||
| 532 | + sendMessage(trafficMessage(number(event, "sid"), | ||
| 533 | + new TrafficClass("primary", primary, true))); | ||
| 450 | } | 534 | } |
| 451 | } | 535 | } |
| 452 | 536 | ||
| 453 | // Cancels sending traffic messages. | 537 | // Cancels sending traffic messages. |
| 454 | private void cancelTraffic(ObjectNode event) { | 538 | private void cancelTraffic(ObjectNode event) { |
| 539 | + selectedIntents = null; | ||
| 455 | sendMessage(trafficMessage(number(event, "sid"))); | 540 | sendMessage(trafficMessage(number(event, "sid"))); |
| 456 | - stopMonitoring(); | 541 | + stopTrafficMonitoring(); |
| 542 | + } | ||
| 543 | + | ||
| 544 | + | ||
| 545 | + private synchronized long startSummaryMonitoring(ObjectNode event) { | ||
| 546 | + stopSummaryMonitoring(); | ||
| 547 | + summaryEvent = event; | ||
| 548 | + summaryTask = new SummaryMonitor(); | ||
| 549 | + timer.schedule(summaryTask, SUMMARY_FREQUENCY, SUMMARY_FREQUENCY); | ||
| 550 | + return number(event, "sid"); | ||
| 457 | } | 551 | } |
| 458 | 552 | ||
| 553 | + private synchronized void stopSummaryMonitoring() { | ||
| 554 | + if (summaryEvent != null) { | ||
| 555 | + summaryTask.cancel(); | ||
| 556 | + summaryTask = null; | ||
| 557 | + summaryEvent = null; | ||
| 558 | + } | ||
| 559 | + } | ||
| 459 | 560 | ||
| 460 | // Subscribes for summary messages. | 561 | // Subscribes for summary messages. |
| 461 | private synchronized void requestSummary(ObjectNode event) { | 562 | private synchronized void requestSummary(ObjectNode event) { |
| 462 | - summaryEnabled = true; | ||
| 463 | sendMessage(summmaryMessage(number(event, "sid"))); | 563 | sendMessage(summmaryMessage(number(event, "sid"))); |
| 464 | } | 564 | } |
| 465 | 565 | ||
| 466 | - // Cancels sending summary messages. | ||
| 467 | - private synchronized void cancelSummary(ObjectNode event) { | ||
| 468 | - summaryEnabled = false; | ||
| 469 | - } | ||
| 470 | - | ||
| 471 | 566 | ||
| 472 | // Forces mastership role rebalancing. | 567 | // Forces mastership role rebalancing. |
| 473 | private void equalizeMasters(ObjectNode event) { | 568 | private void equalizeMasters(ObjectNode event) { |
| ... | @@ -550,7 +645,7 @@ public class TopologyViewWebSocket | ... | @@ -550,7 +645,7 @@ public class TopologyViewWebSocket |
| 550 | @Override | 645 | @Override |
| 551 | public void event(IntentEvent event) { | 646 | public void event(IntentEvent event) { |
| 552 | if (trafficEvent != null) { | 647 | if (trafficEvent != null) { |
| 553 | - requestTraffic(trafficEvent); | 648 | + requestSelectedIntentTraffic(trafficEvent); |
| 554 | } | 649 | } |
| 555 | eventAccummulator.add(event); | 650 | eventAccummulator.add(event); |
| 556 | } | 651 | } |
| ... | @@ -564,6 +659,7 @@ public class TopologyViewWebSocket | ... | @@ -564,6 +659,7 @@ public class TopologyViewWebSocket |
| 564 | } | 659 | } |
| 565 | } | 660 | } |
| 566 | 661 | ||
| 662 | + // Periodic update of the traffic information | ||
| 567 | private class TrafficMonitor extends TimerTask { | 663 | private class TrafficMonitor extends TimerTask { |
| 568 | @Override | 664 | @Override |
| 569 | public void run() { | 665 | public void run() { |
| ... | @@ -574,8 +670,8 @@ public class TopologyViewWebSocket | ... | @@ -574,8 +670,8 @@ public class TopologyViewWebSocket |
| 574 | requestAllTraffic(trafficEvent); | 670 | requestAllTraffic(trafficEvent); |
| 575 | } else if (type.equals("requestDeviceLinkFlows")) { | 671 | } else if (type.equals("requestDeviceLinkFlows")) { |
| 576 | requestDeviceLinkFlows(trafficEvent); | 672 | requestDeviceLinkFlows(trafficEvent); |
| 577 | - } else { | 673 | + } else if (type.equals("requestSelectedIntentTraffic")) { |
| 578 | - requestTraffic(trafficEvent); | 674 | + requestSelectedIntentTraffic(trafficEvent); |
| 579 | } | 675 | } |
| 580 | } | 676 | } |
| 581 | } catch (Exception e) { | 677 | } catch (Exception e) { |
| ... | @@ -585,6 +681,20 @@ public class TopologyViewWebSocket | ... | @@ -585,6 +681,20 @@ public class TopologyViewWebSocket |
| 585 | } | 681 | } |
| 586 | } | 682 | } |
| 587 | 683 | ||
| 684 | + // Periodic update of the summary information | ||
| 685 | + private class SummaryMonitor extends TimerTask { | ||
| 686 | + @Override | ||
| 687 | + public void run() { | ||
| 688 | + try { | ||
| 689 | + if (summaryEvent != null) { | ||
| 690 | + requestSummary(summaryEvent); | ||
| 691 | + } | ||
| 692 | + } catch (Exception e) { | ||
| 693 | + log.warn("Unable to handle summary request due to {}", e.getMessage()); | ||
| 694 | + } | ||
| 695 | + } | ||
| 696 | + } | ||
| 697 | + | ||
| 588 | // Accumulates events to drive methodic update of the summary pane. | 698 | // Accumulates events to drive methodic update of the summary pane. |
| 589 | private class InternalEventAccummulator extends AbstractEventAccumulator { | 699 | private class InternalEventAccummulator extends AbstractEventAccumulator { |
| 590 | protected InternalEventAccummulator() { | 700 | protected InternalEventAccummulator() { |
| ... | @@ -594,7 +704,7 @@ public class TopologyViewWebSocket | ... | @@ -594,7 +704,7 @@ public class TopologyViewWebSocket |
| 594 | @Override | 704 | @Override |
| 595 | public void processEvents(List<Event> events) { | 705 | public void processEvents(List<Event> events) { |
| 596 | try { | 706 | try { |
| 597 | - if (summaryEnabled) { | 707 | + if (summaryEvent != null) { |
| 598 | sendMessage(summmaryMessage(0)); | 708 | sendMessage(summmaryMessage(0)); |
| 599 | } | 709 | } |
| 600 | } catch (Exception e) { | 710 | } catch (Exception e) { | ... | ... |
| ... | @@ -145,8 +145,10 @@ | ... | @@ -145,8 +145,10 @@ |
| 145 | P: togglePorts, | 145 | P: togglePorts, |
| 146 | U: [unpin, 'Unpin node (hover mouse over)'], | 146 | U: [unpin, 'Unpin node (hover mouse over)'], |
| 147 | R: [resetPanZoom, 'Reset pan / zoom'], | 147 | R: [resetPanZoom, 'Reset pan / zoom'], |
| 148 | - V: [showTrafficAction, 'Show related traffic'], | 148 | + V: [showRelatedIntentsAction, 'Show all related intents'], |
| 149 | - A: [showAllTrafficAction, 'Show all traffic'], | 149 | + N: [showNextIntentAction, 'Show next related intent'], |
| 150 | + W: [showSelectedIntentTrafficAction, 'Monitor traffic of selected intent'], | ||
| 151 | + A: [showAllTrafficAction, 'Monitor all traffic'], | ||
| 150 | F: [showDeviceLinkFlowsAction, 'Show device link flows'], | 152 | F: [showDeviceLinkFlowsAction, 'Show device link flows'], |
| 151 | X: [toggleNodeLock, 'Lock / unlock node positions'], | 153 | X: [toggleNodeLock, 'Lock / unlock node positions'], |
| 152 | Z: [toggleOblique, 'Toggle oblique view (Experimental)'], | 154 | Z: [toggleOblique, 'Toggle oblique view (Experimental)'], |
| ... | @@ -209,10 +211,11 @@ | ... | @@ -209,10 +211,11 @@ |
| 209 | oblique = false; | 211 | oblique = false; |
| 210 | 212 | ||
| 211 | // constants | 213 | // constants |
| 212 | - var hoverModeAll = 1, | 214 | + var hoverModeNone = 0, |
| 215 | + hoverModeAll = 1, | ||
| 213 | hoverModeFlows = 2, | 216 | hoverModeFlows = 2, |
| 214 | hoverModeIntents = 3, | 217 | hoverModeIntents = 3, |
| 215 | - hoverMode = hoverModeFlows; | 218 | + hoverMode = hoverModeNone; |
| 216 | 219 | ||
| 217 | // D3 selections | 220 | // D3 selections |
| 218 | var svg, | 221 | var svg, |
| ... | @@ -394,7 +397,7 @@ | ... | @@ -394,7 +397,7 @@ |
| 394 | cancelSummary(); | 397 | cancelSummary(); |
| 395 | stopAntTimer(); | 398 | stopAntTimer(); |
| 396 | } else { | 399 | } else { |
| 397 | - hoverMode = hoverModeFlows; | 400 | + hoverMode = hoverModeNone; |
| 398 | } | 401 | } |
| 399 | } | 402 | } |
| 400 | 403 | ||
| ... | @@ -1219,22 +1222,20 @@ | ... | @@ -1219,22 +1222,20 @@ |
| 1219 | } | 1222 | } |
| 1220 | 1223 | ||
| 1221 | function requestTrafficForMode() { | 1224 | function requestTrafficForMode() { |
| 1222 | - if (hoverMode === hoverModeAll) { | 1225 | + if (hoverMode === hoverModeFlows) { |
| 1223 | - requestAllTraffic(); | ||
| 1224 | - } else if (hoverMode === hoverModeFlows) { | ||
| 1225 | requestDeviceLinkFlows(); | 1226 | requestDeviceLinkFlows(); |
| 1226 | } else if (hoverMode === hoverModeIntents) { | 1227 | } else if (hoverMode === hoverModeIntents) { |
| 1227 | - requestSelectTraffic(); | 1228 | + requestRelatedIntents(); |
| 1228 | } | 1229 | } |
| 1229 | } | 1230 | } |
| 1230 | 1231 | ||
| 1231 | - function showTrafficAction() { | 1232 | + function showRelatedIntentsAction() { |
| 1232 | hoverMode = hoverModeIntents; | 1233 | hoverMode = hoverModeIntents; |
| 1233 | - requestSelectTraffic(); | 1234 | + requestRelatedIntents(); |
| 1234 | - flash('Related Traffic'); | 1235 | + flash('Related intents'); |
| 1235 | } | 1236 | } |
| 1236 | 1237 | ||
| 1237 | - function requestSelectTraffic() { | 1238 | + function requestRelatedIntents() { |
| 1238 | function hoverValid() { | 1239 | function hoverValid() { |
| 1239 | return hoverMode === hoverModeIntents && | 1240 | return hoverMode === hoverModeIntents && |
| 1240 | hovered && | 1241 | hovered && |
| ... | @@ -1242,13 +1243,24 @@ | ... | @@ -1242,13 +1243,24 @@ |
| 1242 | } | 1243 | } |
| 1243 | 1244 | ||
| 1244 | if (validateSelectionContext()) { | 1245 | if (validateSelectionContext()) { |
| 1245 | - sendMessage('requestTraffic', { | 1246 | + sendMessage('requestRelatedIntents', { |
| 1246 | ids: selectOrder, | 1247 | ids: selectOrder, |
| 1247 | hover: hoverValid() ? hovered.id : '' | 1248 | hover: hoverValid() ? hovered.id : '' |
| 1248 | }); | 1249 | }); |
| 1249 | } | 1250 | } |
| 1250 | } | 1251 | } |
| 1251 | 1252 | ||
| 1253 | + function showNextIntentAction() { | ||
| 1254 | + hoverMode = hoverModeNone; | ||
| 1255 | + sendMessage('requestNextRelatedIntent', {}); | ||
| 1256 | + flash('Next related intent'); | ||
| 1257 | + } | ||
| 1258 | + | ||
| 1259 | + function showSelectedIntentTrafficAction() { | ||
| 1260 | + hoverMode = hoverModeNone; | ||
| 1261 | + sendMessage('requestSelectedIntentTraffic', {}); | ||
| 1262 | + flash('Monitoring selected intent'); | ||
| 1263 | + } | ||
| 1252 | 1264 | ||
| 1253 | function showDeviceLinkFlowsAction() { | 1265 | function showDeviceLinkFlowsAction() { |
| 1254 | hoverMode = hoverModeFlows; | 1266 | hoverMode = hoverModeFlows; |
| ... | @@ -2010,14 +2022,18 @@ | ... | @@ -2010,14 +2022,18 @@ |
| 2010 | } | 2022 | } |
| 2011 | 2023 | ||
| 2012 | function nodeMouseOver(d) { | 2024 | function nodeMouseOver(d) { |
| 2025 | + if (hovered != d) { | ||
| 2013 | hovered = d; | 2026 | hovered = d; |
| 2014 | requestTrafficForMode(); | 2027 | requestTrafficForMode(); |
| 2015 | } | 2028 | } |
| 2029 | + } | ||
| 2016 | 2030 | ||
| 2017 | function nodeMouseOut(d) { | 2031 | function nodeMouseOut(d) { |
| 2032 | + if (hovered != null) { | ||
| 2018 | hovered = null; | 2033 | hovered = null; |
| 2019 | requestTrafficForMode(); | 2034 | requestTrafficForMode(); |
| 2020 | } | 2035 | } |
| 2036 | + } | ||
| 2021 | 2037 | ||
| 2022 | function addHostIcon(node, radius, iid) { | 2038 | function addHostIcon(node, radius, iid) { |
| 2023 | var dim = radius * 1.5, | 2039 | var dim = radius * 1.5, |
| ... | @@ -2498,7 +2514,7 @@ | ... | @@ -2498,7 +2514,7 @@ |
| 2498 | wsTrace('rx', msg); | 2514 | wsTrace('rx', msg); |
| 2499 | } | 2515 | } |
| 2500 | function wsTrace(rxtx, msg) { | 2516 | function wsTrace(rxtx, msg) { |
| 2501 | - console.log('[' + rxtx + '] ' + msg); | 2517 | + // console.log('[' + rxtx + '] ' + msg); |
| 2502 | } | 2518 | } |
| 2503 | 2519 | ||
| 2504 | // NOTE: Temporary hardcoded example for showing detail pane | 2520 | // NOTE: Temporary hardcoded example for showing detail pane |
| ... | @@ -2620,7 +2636,6 @@ | ... | @@ -2620,7 +2636,6 @@ |
| 2620 | emptySelect(); | 2636 | emptySelect(); |
| 2621 | } else if (nSel === 1) { | 2637 | } else if (nSel === 1) { |
| 2622 | singleSelect(); | 2638 | singleSelect(); |
| 2623 | - requestTrafficForMode(); | ||
| 2624 | } else { | 2639 | } else { |
| 2625 | multiSelect(); | 2640 | multiSelect(); |
| 2626 | } | 2641 | } |
| ... | @@ -2635,12 +2650,14 @@ | ... | @@ -2635,12 +2650,14 @@ |
| 2635 | function singleSelect() { | 2650 | function singleSelect() { |
| 2636 | // NOTE: detail is shown from showDetails event callback | 2651 | // NOTE: detail is shown from showDetails event callback |
| 2637 | requestDetails(); | 2652 | requestDetails(); |
| 2653 | + cancelTraffic(); | ||
| 2638 | requestTrafficForMode(); | 2654 | requestTrafficForMode(); |
| 2639 | } | 2655 | } |
| 2640 | 2656 | ||
| 2641 | function multiSelect() { | 2657 | function multiSelect() { |
| 2642 | haveDetails = true; | 2658 | haveDetails = true; |
| 2643 | populateMultiSelect(); | 2659 | populateMultiSelect(); |
| 2660 | + cancelTraffic(); | ||
| 2644 | requestTrafficForMode(); | 2661 | requestTrafficForMode(); |
| 2645 | } | 2662 | } |
| 2646 | 2663 | ||
| ... | @@ -2738,7 +2755,7 @@ | ... | @@ -2738,7 +2755,7 @@ |
| 2738 | function addSingleSelectActions(data) { | 2755 | function addSingleSelectActions(data) { |
| 2739 | detailPane.append('hr'); | 2756 | detailPane.append('hr'); |
| 2740 | // always want to allow 'show traffic' | 2757 | // always want to allow 'show traffic' |
| 2741 | - addAction(detailPane, 'Show Related Traffic', showTrafficAction); | 2758 | + addAction(detailPane, 'Show Related Traffic', showRelatedIntentsAction); |
| 2742 | 2759 | ||
| 2743 | if (data.type === 'switch') { | 2760 | if (data.type === 'switch') { |
| 2744 | addAction(detailPane, 'Show Device Flows', showDeviceLinkFlowsAction); | 2761 | addAction(detailPane, 'Show Device Flows', showDeviceLinkFlowsAction); |
| ... | @@ -2748,7 +2765,7 @@ | ... | @@ -2748,7 +2765,7 @@ |
| 2748 | function addMultiSelectActions() { | 2765 | function addMultiSelectActions() { |
| 2749 | detailPane.append('hr'); | 2766 | detailPane.append('hr'); |
| 2750 | // always want to allow 'show traffic' | 2767 | // always want to allow 'show traffic' |
| 2751 | - addAction(detailPane, 'Show Related Traffic', showTrafficAction); | 2768 | + addAction(detailPane, 'Show Related Traffic', showRelatedIntentsAction); |
| 2752 | // if exactly two hosts are selected, also want 'add host intent' | 2769 | // if exactly two hosts are selected, also want 'add host intent' |
| 2753 | if (nSel() === 2 && allSelectionsClass('host')) { | 2770 | if (nSel() === 2 && allSelectionsClass('host')) { |
| 2754 | addAction(detailPane, 'Create Host-to-Host Flow', addHostIntentAction); | 2771 | addAction(detailPane, 'Create Host-to-Host Flow', addHostIntentAction); | ... | ... |
-
Please register or login to post a comment