GUI fixes/breaks.
Change-Id: Ic5c8b087cc32506162153b2756a677c7d9e3bdd7
diff --git a/core/net/src/main/java/org/onlab/onos/net/topology/impl/DefaultTopologyProvider.java b/core/net/src/main/java/org/onlab/onos/net/topology/impl/DefaultTopologyProvider.java
index 44aa9f7..3b1a4a3 100644
--- a/core/net/src/main/java/org/onlab/onos/net/topology/impl/DefaultTopologyProvider.java
+++ b/core/net/src/main/java/org/onlab/onos/net/topology/impl/DefaultTopologyProvider.java
@@ -66,7 +66,7 @@
public class DefaultTopologyProvider extends AbstractProvider
implements TopologyProvider {
- private static final int MAX_THREADS = 8;
+ private static final int MAX_THREADS = 32;
private static final int DEFAULT_MAX_EVENTS = 1000;
private static final int DEFAULT_MAX_IDLE_MS = 10;
private static final int DEFAULT_MAX_BATCH_MS = 50;
diff --git a/tools/test/topos/topo-200sw-linkalarm.py b/tools/test/topos/topo-200sw-linkalarm.py
new file mode 100644
index 0000000..bb964e2
--- /dev/null
+++ b/tools/test/topos/topo-200sw-linkalarm.py
@@ -0,0 +1,20 @@
+
+from mininet.topo import Topo
+
+class MyTopo( Topo ):
+ "10 'floating' switch topology"
+
+ def __init__( self ):
+ # Initialize topology
+ Topo.__init__( self )
+
+ sw_list = []
+ swC = self.addSwitch('sc', dpid = 'ffffffff00000001')
+
+ for i in range(1, 201):
+ switch=self.addSwitch('s'+str(i), dpid = str(i).zfill(16))
+ self.addLink(switch,swC)
+
+ sw_list.append(switch)
+
+topos = { 'mytopo': ( lambda: MyTopo() ) }
diff --git a/web/gui/src/main/java/org/onlab/onos/gui/TopologyViewIntentFilter.java b/web/gui/src/main/java/org/onlab/onos/gui/TopologyViewIntentFilter.java
index 2585b84..e5c9249 100644
--- a/web/gui/src/main/java/org/onlab/onos/gui/TopologyViewIntentFilter.java
+++ b/web/gui/src/main/java/org/onlab/onos/gui/TopologyViewIntentFilter.java
@@ -33,6 +33,7 @@
import org.onlab.onos.net.intent.PointToPointIntent;
import org.onlab.onos.net.link.LinkService;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -71,17 +72,19 @@
* Finds all path (host-to-host or point-to-point) intents that pertains
* to the given hosts.
*
- * @param hosts set of hosts to query by
- * @param devices set of devices to query by
+ * @param hosts set of hosts to query by
+ * @param devices set of devices to query by
+ * @param sourceIntents collection of intents to search
* @return set of intents that 'match' all hosts and devices given
*/
- Set<Intent> findPathIntents(Set<Host> hosts, Set<Device> devices) {
+ List<Intent> findPathIntents(Set<Host> hosts, Set<Device> devices,
+ Iterable<Intent> sourceIntents) {
// Derive from this the set of edge connect points.
Set<ConnectPoint> edgePoints = getEdgePoints(hosts);
// Iterate over all intents and produce a set that contains only those
// intents that target all selected hosts or derived edge connect points.
- return getIntents(hosts, devices, edgePoints);
+ return getIntents(hosts, devices, edgePoints, sourceIntents);
}
@@ -94,10 +97,11 @@
return edgePoints;
}
- // Produces a set of intents that target all selected hosts, devices or connect points.
- private Set<Intent> getIntents(Set<Host> hosts, Set<Device> devices,
- Set<ConnectPoint> edgePoints) {
- Set<Intent> intents = new HashSet<>();
+ // Produces a list of intents that target all selected hosts, devices or connect points.
+ private List<Intent> getIntents(Set<Host> hosts, Set<Device> devices,
+ Set<ConnectPoint> edgePoints,
+ Iterable<Intent> sourceIntents) {
+ List<Intent> intents = new ArrayList<>();
if (hosts.isEmpty() && devices.isEmpty()) {
return intents;
}
@@ -105,7 +109,7 @@
Set<OpticalConnectivityIntent> opticalIntents = new HashSet<>();
// Search through all intents and see if they are relevant to our search.
- for (Intent intent : intentService.getIntents()) {
+ for (Intent intent : sourceIntents) {
if (intentService.getIntentState(intent.id()) == INSTALLED) {
boolean isRelevant = false;
if (intent instanceof HostToHostIntent) {
@@ -140,7 +144,7 @@
}
// Indicates whether the specified intent involves all of the given hosts.
- private boolean isIntentRelevantToHosts(HostToHostIntent intent, Set<Host> hosts) {
+ private boolean isIntentRelevantToHosts(HostToHostIntent intent, Iterable<Host> hosts) {
for (Host host : hosts) {
HostId id = host.id();
// Bail if intent does not involve this host.
@@ -152,7 +156,7 @@
}
// Indicates whether the specified intent involves all of the given devices.
- private boolean isIntentRelevantToDevices(Intent intent, Set<Device> devices) {
+ private boolean isIntentRelevantToDevices(Intent intent, Iterable<Device> devices) {
List<Intent> installables = intentService.getInstallableIntents(intent.id());
for (Device device : devices) {
if (!isIntentRelevantToDevice(installables, device)) {
@@ -192,7 +196,8 @@
return false;
}
- private boolean isIntentRelevant(PointToPointIntent intent, Set<ConnectPoint> edgePoints) {
+ private boolean isIntentRelevant(PointToPointIntent intent,
+ Iterable<ConnectPoint> edgePoints) {
for (ConnectPoint point : edgePoints) {
// Bail if intent does not involve this edge point.
if (!point.equals(intent.egressPoint()) &&
@@ -205,7 +210,7 @@
// Indicates whether the specified intent involves all of the given edge points.
private boolean isIntentRelevant(MultiPointToSinglePointIntent intent,
- Set<ConnectPoint> edgePoints) {
+ Iterable<ConnectPoint> edgePoints) {
for (ConnectPoint point : edgePoints) {
// Bail if intent does not involve this edge point.
if (!point.equals(intent.egressPoint()) &&
@@ -218,7 +223,7 @@
// Indicates whether the specified intent involves all of the given edge points.
private boolean isIntentRelevant(OpticalConnectivityIntent opticalIntent,
- Set<Intent> intents) {
+ Iterable<Intent> intents) {
Link ccSrc = getFirstLink(opticalIntent.getSrc(), false);
Link ccDst = getFirstLink(opticalIntent.getDst(), true);
diff --git a/web/gui/src/main/java/org/onlab/onos/gui/TopologyViewMessages.java b/web/gui/src/main/java/org/onlab/onos/gui/TopologyViewMessages.java
index c49fbee..486e375 100644
--- a/web/gui/src/main/java/org/onlab/onos/gui/TopologyViewMessages.java
+++ b/web/gui/src/main/java/org/onlab/onos/gui/TopologyViewMessages.java
@@ -676,13 +676,16 @@
List<Intent> installables = intentService.getInstallableIntents(intent.id());
if (installables != null) {
for (Intent installable : installables) {
- String cls = isOptical ? trafficClass.type + " optical" : trafficClass.type;
+ String type = isOptical ? trafficClass.type + " optical" : trafficClass.type;
if (installable instanceof PathIntent) {
- classifyLinks(cls, biLinks, ((PathIntent) installable).path().links());
+ classifyLinks(type, biLinks, trafficClass.showTraffic,
+ ((PathIntent) installable).path().links());
} else if (installable instanceof LinkCollectionIntent) {
- classifyLinks(cls, biLinks, ((LinkCollectionIntent) installable).links());
+ classifyLinks(type, biLinks, trafficClass.showTraffic,
+ ((LinkCollectionIntent) installable).links());
} else if (installable instanceof OpticalPathIntent) {
- classifyLinks(cls, biLinks, ((OpticalPathIntent) installable).path().links());
+ classifyLinks(type, biLinks, trafficClass.showTraffic,
+ ((OpticalPathIntent) installable).path().links());
}
}
}
@@ -695,12 +698,14 @@
// Adds the link segments (path or tree) associated with the specified
// connectivity intent
private void classifyLinks(String type, Map<LinkKey, BiLink> biLinks,
- Iterable<Link> links) {
+ boolean showTraffic, Iterable<Link> links) {
if (links != null) {
for (Link link : links) {
BiLink biLink = addLink(biLinks, link);
if (isInfrastructureEgress(link)) {
- biLink.addLoad(statService.load(link));
+ if (showTraffic) {
+ biLink.addLoad(statService.load(link));
+ }
biLink.addClass(type);
}
}
@@ -862,12 +867,18 @@
// Auxiliary carrier of data for requesting traffic message.
protected class TrafficClass {
+ public final boolean showTraffic;
public final String type;
- public final Set<Intent> intents;
+ public final Iterable<Intent> intents;
- TrafficClass(String type, Set<Intent> intents) {
+ TrafficClass(String type, Iterable<Intent> intents) {
+ this(type, intents, false);
+ }
+
+ TrafficClass(String type, Iterable<Intent> intents, boolean showTraffic) {
this.type = type;
this.intents = intents;
+ this.showTraffic = showTraffic;
}
}
diff --git a/web/gui/src/main/java/org/onlab/onos/gui/TopologyViewWebSocket.java b/web/gui/src/main/java/org/onlab/onos/gui/TopologyViewWebSocket.java
index 9e46da3..bd02065 100644
--- a/web/gui/src/main/java/org/onlab/onos/gui/TopologyViewWebSocket.java
+++ b/web/gui/src/main/java/org/onlab/onos/gui/TopologyViewWebSocket.java
@@ -90,7 +90,8 @@
private static final String APP_ID = "org.onlab.onos.gui";
- private static final long TRAFFIC_FREQUENCY_SEC = 2000;
+ private static final long TRAFFIC_FREQUENCY = 2000;
+ private static final long SUMMARY_FREQUENCY = 30000;
private static final Comparator<? super ControllerNode> NODE_COMPARATOR =
new Comparator<ControllerNode>() {
@@ -103,9 +104,9 @@
private final Timer timer = new Timer("topology-view");
- private static final int MAX_EVENTS = 500;
- private static final int MAX_BATCH_MS = 1000;
- private static final int MAX_IDLE_MS = 500;
+ private static final int MAX_EVENTS = 1000;
+ private static final int MAX_BATCH_MS = 5000;
+ private static final int MAX_IDLE_MS = 1000;
private final ApplicationId appId;
@@ -122,15 +123,23 @@
private final EventAccumulator eventAccummulator = new InternalEventAccummulator();
- private boolean summaryEnabled = true;
private TimerTask trafficTask;
private ObjectNode trafficEvent;
+ private TimerTask summaryTask;
+ private ObjectNode summaryEvent;
+
private long lastActive = System.currentTimeMillis();
private boolean listenersRemoved = false;
private TopologyViewIntentFilter intentFilter;
+ // Current selection context
+ private Set<Host> selectedHosts;
+ private Set<Device> selectedDevices;
+ private List<Intent> selectedIntents;
+ private int currentIntentIndex = -1;
+
/**
* Creates a new web-socket for serving data to GUI topology view.
*
@@ -204,7 +213,6 @@
processMessage((ObjectNode) mapper.reader().readTree(data));
} catch (Exception e) {
log.warn("Unable to parse GUI request {} due to {}", data, e);
- log.warn("Boom!!!!", e);
}
}
@@ -221,19 +229,29 @@
} else if (type.equals("addMultiSourceIntent")) {
createMultiSourceIntent(event);
- } else if (type.equals("requestTraffic")) {
- requestTraffic(event);
+ } else if (type.equals("requestRelatedIntents")) {
+ requestRelatedIntents(event);
+ } else if (type.equals("requestNextRelatedIntent")) {
+ requestNextRelatedIntent(event);
+ } else if (type.equals("requestSelectedIntentTraffic")) {
+ requestSelectedIntentTraffic(event);
+
} else if (type.equals("requestAllTraffic")) {
requestAllTraffic(event);
+ startTrafficMonitoring(event);
+
} else if (type.equals("requestDeviceLinkFlows")) {
requestDeviceLinkFlows(event);
+ startTrafficMonitoring(event);
+
} else if (type.equals("cancelTraffic")) {
cancelTraffic(event);
} else if (type.equals("requestSummary")) {
requestSummary(event);
+ startSummaryMonitoring(event);
} else if (type.equals("cancelSummary")) {
- cancelSummary(event);
+ stopSummaryMonitoring();
} else if (type.equals("equalizeMasters")) {
equalizeMasters(event);
@@ -324,8 +342,9 @@
new HostToHostIntent(appId, one, two,
DefaultTrafficSelector.builder().build(),
DefaultTrafficTreatment.builder().build());
- startMonitoring(event);
+
intentService.submit(intent);
+ startMonitoringIntent(event, intent);
}
// Creates multi-source-to-single-dest intent.
@@ -348,10 +367,24 @@
MultiPointToSinglePointIntent intent =
new MultiPointToSinglePointIntent(appId, selector, treatment,
ingressPoints, dstHost.location());
- startMonitoring(event);
+
intentService.submit(intent);
+ startMonitoringIntent(event, intent);
}
+
+ private synchronized void startMonitoringIntent(ObjectNode event, Intent intent) {
+ selectedHosts = new HashSet<>();
+ selectedDevices = new HashSet<>();
+ selectedIntents = new ArrayList<>();
+ selectedIntents.add(intent);
+ currentIntentIndex = -1;
+ requestNextRelatedIntent(event);
+ requestSelectedIntentTraffic(event);
+ }
+
+
+
private Set<ConnectPoint> getHostLocations(Set<HostId> hostIds) {
Set<ConnectPoint> points = new HashSet<>();
for (HostId hostId : hostIds) {
@@ -374,17 +407,15 @@
}
- private synchronized long startMonitoring(ObjectNode event) {
- if (trafficTask != null) {
- stopMonitoring();
- }
+ private synchronized long startTrafficMonitoring(ObjectNode event) {
+ stopTrafficMonitoring();
trafficEvent = event;
trafficTask = new TrafficMonitor();
- timer.schedule(trafficTask, TRAFFIC_FREQUENCY_SEC, TRAFFIC_FREQUENCY_SEC);
+ timer.schedule(trafficTask, TRAFFIC_FREQUENCY, TRAFFIC_FREQUENCY);
return number(event, "sid");
}
- private synchronized void stopMonitoring() {
+ private synchronized void stopTrafficMonitoring() {
if (trafficTask != null) {
trafficTask.cancel();
trafficTask = null;
@@ -394,13 +425,13 @@
// Subscribes for host traffic messages.
private synchronized void requestAllTraffic(ObjectNode event) {
- long sid = startMonitoring(event);
+ long sid = startTrafficMonitoring(event);
sendMessage(trafficSummaryMessage(sid));
}
private void requestDeviceLinkFlows(ObjectNode event) {
ObjectNode payload = payload(event);
- long sid = startMonitoring(event);
+ long sid = startTrafficMonitoring(event);
// Get the set of selected hosts and their intents.
ArrayNode ids = (ArrayNode) payload.path("ids");
@@ -416,58 +447,122 @@
}
- // Subscribes for host traffic messages.
- private synchronized void requestTraffic(ObjectNode event) {
+ // Requests related intents message.
+ private synchronized void requestRelatedIntents(ObjectNode event) {
ObjectNode payload = payload(event);
if (!payload.has("ids")) {
return;
}
- long sid = startMonitoring(event);
+ long sid = number(event, "sid");
- // Get the set of selected hosts and their intents.
- ArrayNode ids = (ArrayNode) payload.path("ids");
- Set<Host> hosts = getHosts(ids);
- Set<Device> devices = getDevices(ids);
- Set<Intent> intents = intentFilter.findPathIntents(hosts, devices);
+ // Cancel any other traffic monitoring mode.
+ stopTrafficMonitoring();
- // If there is a hover node, include it in the hosts and find intents.
String hover = string(payload, "hover");
- Set<Intent> hoverIntents;
+ if (haveSelectedIntents()) {
+ // Get the set of selected hosts and their intents.
+ ArrayNode ids = (ArrayNode) payload.path("ids");
+ selectedHosts = getHosts(ids);
+ selectedDevices = getDevices(ids);
+ selectedIntents = intentFilter.findPathIntents(selectedHosts, selectedDevices,
+ intentService.getIntents());
+ currentIntentIndex = -1;
+
+ // Send a message to highlight all links of all monitored intents.
+ sendMessage(trafficMessage(sid, new TrafficClass("primary", selectedIntents)));
+ }
+
if (!isNullOrEmpty(hover)) {
- addHover(hosts, devices, hover);
- hoverIntents = intentFilter.findPathIntents(hosts, devices);
- intents.removeAll(hoverIntents);
+ // If there is a hover node, include it in the selection and find intents.
+ processExtendedSelection(sid, hover);
+ }
+ }
- // Send an initial message to highlight all links of all monitored intents.
- sendMessage(trafficMessage(sid,
- new TrafficClass("primary", hoverIntents),
- new TrafficClass("secondary", intents)));
+ private boolean haveSelectedIntents() {
+ return selectedIntents != null && !selectedIntents.isEmpty();
+ }
- } else {
- // Send an initial message to highlight all links of all monitored intents.
- sendMessage(trafficMessage(sid, new TrafficClass("primary", intents)));
+ private void processExtendedSelection(long sid, String hover) {
+ Set<Host> hoverSelHosts = new HashSet<>(selectedHosts);
+ Set<Device> hoverSelDevices = new HashSet<>(selectedDevices);
+ addHover(hoverSelHosts, hoverSelDevices, hover);
+
+ List<Intent> primary =
+ intentFilter.findPathIntents(hoverSelHosts, hoverSelDevices,
+ selectedIntents);
+ Set<Intent> secondary = new HashSet<>(selectedIntents);
+ secondary.removeAll(primary);
+
+ // Send a message to highlight all links of all monitored intents.
+ sendMessage(trafficMessage(sid, new TrafficClass("primary", primary),
+ new TrafficClass("secondary", secondary)));
+ }
+
+ // Requests next of the related intents.
+ private void requestNextRelatedIntent(ObjectNode event) {
+ if (haveSelectedIntents()) {
+ currentIntentIndex = (currentIntentIndex + 1) % selectedIntents.size();
+ Intent selectedIntent = selectedIntents.get(currentIntentIndex);
+ log.info("Requested next intent {}", selectedIntent.id());
+
+ Set<Intent> primary = new HashSet<>();
+ primary.add(selectedIntent);
+
+ Set<Intent> secondary = new HashSet<>(selectedIntents);
+ secondary.remove(selectedIntent);
+
+ // Send a message to highlight all links of the selected intent.
+ sendMessage(trafficMessage(number(event, "sid"),
+ new TrafficClass("primary", primary),
+ new TrafficClass("secondary", secondary)));
+ }
+ }
+
+ // Requests monitoring of traffic for the selected intent.
+ private void requestSelectedIntentTraffic(ObjectNode event) {
+ if (haveSelectedIntents()) {
+ Intent selectedIntent = selectedIntents.get(currentIntentIndex);
+ log.info("Requested traffic for selected {}", selectedIntent.id());
+
+ Set<Intent> primary = new HashSet<>();
+ primary.add(selectedIntent);
+
+ // Send a message to highlight all links of the selected intent.
+ sendMessage(trafficMessage(number(event, "sid"),
+ new TrafficClass("primary", primary, true)));
}
}
// Cancels sending traffic messages.
private void cancelTraffic(ObjectNode event) {
+ selectedIntents = null;
sendMessage(trafficMessage(number(event, "sid")));
- stopMonitoring();
+ stopTrafficMonitoring();
}
+ private synchronized long startSummaryMonitoring(ObjectNode event) {
+ stopSummaryMonitoring();
+ summaryEvent = event;
+ summaryTask = new SummaryMonitor();
+ timer.schedule(summaryTask, SUMMARY_FREQUENCY, SUMMARY_FREQUENCY);
+ return number(event, "sid");
+ }
+
+ private synchronized void stopSummaryMonitoring() {
+ if (summaryEvent != null) {
+ summaryTask.cancel();
+ summaryTask = null;
+ summaryEvent = null;
+ }
+ }
+
// Subscribes for summary messages.
private synchronized void requestSummary(ObjectNode event) {
- summaryEnabled = true;
sendMessage(summmaryMessage(number(event, "sid")));
}
- // Cancels sending summary messages.
- private synchronized void cancelSummary(ObjectNode event) {
- summaryEnabled = false;
- }
-
// Forces mastership role rebalancing.
private void equalizeMasters(ObjectNode event) {
@@ -550,7 +645,7 @@
@Override
public void event(IntentEvent event) {
if (trafficEvent != null) {
- requestTraffic(trafficEvent);
+ requestSelectedIntentTraffic(trafficEvent);
}
eventAccummulator.add(event);
}
@@ -564,6 +659,7 @@
}
}
+ // Periodic update of the traffic information
private class TrafficMonitor extends TimerTask {
@Override
public void run() {
@@ -574,8 +670,8 @@
requestAllTraffic(trafficEvent);
} else if (type.equals("requestDeviceLinkFlows")) {
requestDeviceLinkFlows(trafficEvent);
- } else {
- requestTraffic(trafficEvent);
+ } else if (type.equals("requestSelectedIntentTraffic")) {
+ requestSelectedIntentTraffic(trafficEvent);
}
}
} catch (Exception e) {
@@ -585,6 +681,20 @@
}
}
+ // Periodic update of the summary information
+ private class SummaryMonitor extends TimerTask {
+ @Override
+ public void run() {
+ try {
+ if (summaryEvent != null) {
+ requestSummary(summaryEvent);
+ }
+ } catch (Exception e) {
+ log.warn("Unable to handle summary request due to {}", e.getMessage());
+ }
+ }
+ }
+
// Accumulates events to drive methodic update of the summary pane.
private class InternalEventAccummulator extends AbstractEventAccumulator {
protected InternalEventAccummulator() {
@@ -594,7 +704,7 @@
@Override
public void processEvents(List<Event> events) {
try {
- if (summaryEnabled) {
+ if (summaryEvent != null) {
sendMessage(summmaryMessage(0));
}
} catch (Exception e) {
diff --git a/web/gui/src/main/webapp/topo.js b/web/gui/src/main/webapp/topo.js
index f52b0c9..ea0d731 100644
--- a/web/gui/src/main/webapp/topo.js
+++ b/web/gui/src/main/webapp/topo.js
@@ -145,8 +145,10 @@
P: togglePorts,
U: [unpin, 'Unpin node (hover mouse over)'],
R: [resetPanZoom, 'Reset pan / zoom'],
- V: [showTrafficAction, 'Show related traffic'],
- A: [showAllTrafficAction, 'Show all traffic'],
+ V: [showRelatedIntentsAction, 'Show all related intents'],
+ N: [showNextIntentAction, 'Show next related intent'],
+ W: [showSelectedIntentTrafficAction, 'Monitor traffic of selected intent'],
+ A: [showAllTrafficAction, 'Monitor all traffic'],
F: [showDeviceLinkFlowsAction, 'Show device link flows'],
X: [toggleNodeLock, 'Lock / unlock node positions'],
Z: [toggleOblique, 'Toggle oblique view (Experimental)'],
@@ -209,10 +211,11 @@
oblique = false;
// constants
- var hoverModeAll = 1,
+ var hoverModeNone = 0,
+ hoverModeAll = 1,
hoverModeFlows = 2,
hoverModeIntents = 3,
- hoverMode = hoverModeFlows;
+ hoverMode = hoverModeNone;
// D3 selections
var svg,
@@ -394,7 +397,7 @@
cancelSummary();
stopAntTimer();
} else {
- hoverMode = hoverModeFlows;
+ hoverMode = hoverModeNone;
}
}
@@ -1219,22 +1222,20 @@
}
function requestTrafficForMode() {
- if (hoverMode === hoverModeAll) {
- requestAllTraffic();
- } else if (hoverMode === hoverModeFlows) {
+ if (hoverMode === hoverModeFlows) {
requestDeviceLinkFlows();
} else if (hoverMode === hoverModeIntents) {
- requestSelectTraffic();
+ requestRelatedIntents();
}
}
- function showTrafficAction() {
+ function showRelatedIntentsAction() {
hoverMode = hoverModeIntents;
- requestSelectTraffic();
- flash('Related Traffic');
+ requestRelatedIntents();
+ flash('Related intents');
}
- function requestSelectTraffic() {
+ function requestRelatedIntents() {
function hoverValid() {
return hoverMode === hoverModeIntents &&
hovered &&
@@ -1242,13 +1243,24 @@
}
if (validateSelectionContext()) {
- sendMessage('requestTraffic', {
+ sendMessage('requestRelatedIntents', {
ids: selectOrder,
hover: hoverValid() ? hovered.id : ''
});
}
}
+ function showNextIntentAction() {
+ hoverMode = hoverModeNone;
+ sendMessage('requestNextRelatedIntent', {});
+ flash('Next related intent');
+ }
+
+ function showSelectedIntentTrafficAction() {
+ hoverMode = hoverModeNone;
+ sendMessage('requestSelectedIntentTraffic', {});
+ flash('Monitoring selected intent');
+ }
function showDeviceLinkFlowsAction() {
hoverMode = hoverModeFlows;
@@ -2010,13 +2022,17 @@
}
function nodeMouseOver(d) {
- hovered = d;
- requestTrafficForMode();
+ if (hovered != d) {
+ hovered = d;
+ requestTrafficForMode();
+ }
}
function nodeMouseOut(d) {
- hovered = null;
- requestTrafficForMode();
+ if (hovered != null) {
+ hovered = null;
+ requestTrafficForMode();
+ }
}
function addHostIcon(node, radius, iid) {
@@ -2498,7 +2514,7 @@
wsTrace('rx', msg);
}
function wsTrace(rxtx, msg) {
- console.log('[' + rxtx + '] ' + msg);
+ // console.log('[' + rxtx + '] ' + msg);
}
// NOTE: Temporary hardcoded example for showing detail pane
@@ -2620,7 +2636,6 @@
emptySelect();
} else if (nSel === 1) {
singleSelect();
- requestTrafficForMode();
} else {
multiSelect();
}
@@ -2635,12 +2650,14 @@
function singleSelect() {
// NOTE: detail is shown from showDetails event callback
requestDetails();
+ cancelTraffic();
requestTrafficForMode();
}
function multiSelect() {
haveDetails = true;
populateMultiSelect();
+ cancelTraffic();
requestTrafficForMode();
}
@@ -2738,7 +2755,7 @@
function addSingleSelectActions(data) {
detailPane.append('hr');
// always want to allow 'show traffic'
- addAction(detailPane, 'Show Related Traffic', showTrafficAction);
+ addAction(detailPane, 'Show Related Traffic', showRelatedIntentsAction);
if (data.type === 'switch') {
addAction(detailPane, 'Show Device Flows', showDeviceLinkFlowsAction);
@@ -2748,7 +2765,7 @@
function addMultiSelectActions() {
detailPane.append('hr');
// always want to allow 'show traffic'
- addAction(detailPane, 'Show Related Traffic', showTrafficAction);
+ addAction(detailPane, 'Show Related Traffic', showRelatedIntentsAction);
// if exactly two hosts are selected, also want 'add host intent'
if (nSel() === 2 && allSelectionsClass('host')) {
addAction(detailPane, 'Create Host-to-Host Flow', addHostIntentAction);