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