GUI traffic visualization work on server-side.
Change-Id: I2e903ec028ea40fd325f69c4d7e1f0b2b6db2f42
diff --git a/web/gui/src/main/java/org/onlab/onos/gui/TopologyMessages.java b/web/gui/src/main/java/org/onlab/onos/gui/TopologyMessages.java
index c87a7f6..aef9e95 100644
--- a/web/gui/src/main/java/org/onlab/onos/gui/TopologyMessages.java
+++ b/web/gui/src/main/java/org/onlab/onos/gui/TopologyMessages.java
@@ -44,6 +44,7 @@
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.net.intent.LinkCollectionIntent;
+import org.onlab.onos.net.intent.OpticalConnectivityIntent;
import org.onlab.onos.net.intent.PathIntent;
import org.onlab.onos.net.link.LinkEvent;
import org.onlab.onos.net.link.LinkService;
@@ -88,6 +89,7 @@
protected final HostService hostService;
protected final MastershipService mastershipService;
protected final IntentService intentService;
+// protected final StatisticService statService;
protected final ObjectMapper mapper = new ObjectMapper();
@@ -107,6 +109,7 @@
hostService = directory.get(HostService.class);
mastershipService = directory.get(MastershipService.class);
intentService = directory.get(IntentService.class);
+// statService = directory.get(StatisticService.class);
}
// Retrieves the payload from the specified event.
@@ -376,10 +379,14 @@
for (TrafficClass trafficClass : trafficClasses) {
for (Intent intent : trafficClass.intents) {
+ boolean isOptical = intent instanceof OpticalConnectivityIntent;
List<Intent> installables = intentService.getInstallableIntents(intent.id());
- for (Intent installable : installables) {
- if (installable instanceof ConnectivityIntent) {
- addPathTraffic(paths, trafficClass.type, (ConnectivityIntent) installable);
+ if (installables != null) {
+ for (Intent installable : installables) {
+ String cls = isOptical ? trafficClass.type + " optical" : trafficClass.type;
+ if (installable instanceof ConnectivityIntent) {
+ addPathTraffic(paths, cls, (ConnectivityIntent) installable);
+ }
}
}
}
@@ -395,20 +402,34 @@
ObjectNode pathNode = mapper.createObjectNode();
ArrayNode linksNode = mapper.createArrayNode();
- Iterable<Link> links;
- if (installable instanceof PathIntent) {
- links = ((PathIntent) installable).path().links();
- } else if (installable instanceof LinkCollectionIntent) {
- links = ((LinkCollectionIntent) installable).links();
- } else {
- return;
+ Iterable<Link> links = pathLinks(installable);
+ if (links != null) {
+ ArrayNode labels = mapper.createArrayNode();
+ boolean hasTraffic = true; // FIXME
+ for (Link link : links) {
+ linksNode.add(compactLinkString(link));
+// Load load = statService.load(link);
+ String label = "";
+// if (load.rate() > 0) {
+// label = load.toString();
+// }
+ labels.add(label);
+ }
+ pathNode.put("class", hasTraffic ? type + " animated" : type);
+ pathNode.put("traffic", hasTraffic);
+ pathNode.set("links", linksNode);
+ pathNode.set("labels", labels);
+ paths.add(pathNode);
}
+ }
- for (Link link : links) {
- linksNode.add(compactLinkString(link));
+ private Iterable<Link> pathLinks(ConnectivityIntent intent) {
+ if (intent instanceof PathIntent) {
+ return ((PathIntent) intent).path().links();
+ } else if (intent instanceof LinkCollectionIntent) {
+ return ((LinkCollectionIntent) intent).links();
}
- pathNode.put("type", type).set("links", linksNode);
- paths.add(pathNode);
+ return null;
}
// Produces compact string representation of a link.
diff --git a/web/gui/src/main/java/org/onlab/onos/gui/TopologyWebSocket.java b/web/gui/src/main/java/org/onlab/onos/gui/TopologyWebSocket.java
index cf8144b..10b5785 100644
--- a/web/gui/src/main/java/org/onlab/onos/gui/TopologyWebSocket.java
+++ b/web/gui/src/main/java/org/onlab/onos/gui/TopologyWebSocket.java
@@ -24,8 +24,6 @@
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.core.ApplicationId;
import org.onlab.onos.core.CoreService;
-import org.onlab.onos.mastership.MastershipEvent;
-import org.onlab.onos.mastership.MastershipListener;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Device;
import org.onlab.onos.net.Host;
@@ -43,6 +41,7 @@
import org.onlab.onos.net.intent.IntentEvent;
import org.onlab.onos.net.intent.IntentListener;
import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
+import org.onlab.onos.net.intent.OpticalConnectivityIntent;
import org.onlab.onos.net.intent.PathIntent;
import org.onlab.onos.net.intent.PointToPointIntent;
import org.onlab.onos.net.link.LinkEvent;
@@ -52,9 +51,9 @@
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.Timer;
+import java.util.TimerTask;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onlab.onos.cluster.ClusterEvent.Type.INSTANCE_ADDED;
@@ -62,6 +61,7 @@
import static org.onlab.onos.net.HostId.hostId;
import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_ADDED;
import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED;
+import static org.onlab.onos.net.intent.IntentState.INSTALLED;
import static org.onlab.onos.net.link.LinkEvent.Type.LINK_ADDED;
/**
@@ -79,6 +79,8 @@
private static final String APP_ID = "org.onlab.onos.gui";
+ private static final long TRAFFIC_FREQUENCY_SEC = 5000;
+
private final ApplicationId appId;
private Connection connection;
@@ -88,11 +90,12 @@
private final DeviceListener deviceListener = new InternalDeviceListener();
private final LinkListener linkListener = new InternalLinkListener();
private final HostListener hostListener = new InternalHostListener();
- private final MastershipListener mastershipListener = new InternalMastershipListener();
private final IntentListener intentListener = new InternalIntentListener();
// Intents that are being monitored for the GUI
- private Map<Intent, Long> intentsToMonitor = new ConcurrentHashMap<>();
+ private ObjectNode monitorRequest;
+ private final Timer timer = new Timer("intent-traffic-monitor");
+ private final TimerTask timerTask = new IntentTrafficMonitor();
private long lastActive = System.currentTimeMillis();
private boolean listenersRemoved = false;
@@ -141,6 +144,7 @@
this.connection = connection;
this.control = (FrameConnection) connection;
addListeners();
+ timer.schedule(timerTask, TRAFFIC_FREQUENCY_SEC, TRAFFIC_FREQUENCY_SEC);
sendAllInstances();
sendAllDevices();
@@ -151,6 +155,7 @@
@Override
public synchronized void onClose(int closeCode, String message) {
removeListeners();
+ timer.cancel();
log.info("GUI client disconnected");
}
@@ -245,14 +250,15 @@
HostToHostIntent hostIntent = new HostToHostIntent(appId, one, two,
DefaultTrafficSelector.builder().build(),
DefaultTrafficTreatment.builder().build());
- intentsToMonitor.put(hostIntent, number(event, "sid"));
+ monitorRequest = event;
intentService.submit(hostIntent);
}
// Sends traffic message.
- private void requestTraffic(ObjectNode event) {
+ private synchronized void requestTraffic(ObjectNode event) {
ObjectNode payload = payload(event);
long sid = number(event, "sid");
+ monitorRequest = event;
// Get the set of selected hosts and their intents.
Set<Host> hosts = getHosts((ArrayNode) payload.path("ids"));
@@ -274,18 +280,13 @@
} else {
// Send an initial message to highlight all links of all monitored intents.
sendMessage(trafficMessage(sid, new TrafficClass("primary", intents)));
-
- // Add all those intents to the list of monitored intents & flows.
- intentsToMonitor.clear();
- for (Intent intent : intents) {
- intentsToMonitor.put(intent, sid);
- }
}
}
// Cancels sending traffic messages.
private void cancelTraffic(ObjectNode event) {
sendMessage(trafficMessage(number(event, "sid")));
+ monitorRequest = null;
}
// Finds all path (host-to-host or point-to-point) intents that pertains
@@ -306,18 +307,30 @@
return intents;
}
- for (Intent intent : intentService.getIntents()) {
- boolean isRelevant = false;
- if (intent instanceof HostToHostIntent) {
- isRelevant = isIntentRelevant((HostToHostIntent) intent, hosts);
- } else if (intent instanceof PointToPointIntent) {
- isRelevant = isIntentRelevant((PointToPointIntent) intent, edgePoints);
- } else if (intent instanceof MultiPointToSinglePointIntent) {
- isRelevant = isIntentRelevant((MultiPointToSinglePointIntent) intent, edgePoints);
- }
- // TODO: add other intents, e.g. SinglePointToMultiPointIntent
+ Set<OpticalConnectivityIntent> opticalIntents = new HashSet<>();
- if (isRelevant) {
+ for (Intent intent : intentService.getIntents()) {
+ if (intentService.getIntentState(intent.id()) == INSTALLED) {
+ boolean isRelevant = false;
+ if (intent instanceof HostToHostIntent) {
+ isRelevant = isIntentRelevant((HostToHostIntent) intent, hosts);
+ } else if (intent instanceof PointToPointIntent) {
+ isRelevant = isIntentRelevant((PointToPointIntent) intent, edgePoints);
+ } else if (intent instanceof MultiPointToSinglePointIntent) {
+ isRelevant = isIntentRelevant((MultiPointToSinglePointIntent) intent, edgePoints);
+ } else if (intent instanceof OpticalConnectivityIntent) {
+ opticalIntents.add((OpticalConnectivityIntent) intent);
+ }
+ // TODO: add other intents, e.g. SinglePointToMultiPointIntent
+
+ if (isRelevant) {
+ intents.add(intent);
+ }
+ }
+ }
+
+ for (OpticalConnectivityIntent intent : opticalIntents) {
+ if (isIntentRelevant(intent, intents)) {
intents.add(intent);
}
}
@@ -362,6 +375,23 @@
return true;
}
+ // Indicates whether the specified intent involves all of the given edge points.
+ private boolean isIntentRelevant(OpticalConnectivityIntent opticalIntent,
+ Set<Intent> intents) {
+ for (Intent intent : intents) {
+ List<Intent> installables = intentService.getInstallableIntents(intent.id());
+ for (Intent installable : installables) {
+ if (installable instanceof PathIntent) {
+ Path path = ((PathIntent) installable).path();
+ if (opticalIntent.getSrcConnectPoint().equals(path.src()) &&
+ opticalIntent.getDst().equals(path.dst())) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
// Produces a set of all host ids listed in the specified JSON array.
private Set<Host> getHosts(ArrayNode array) {
@@ -401,7 +431,6 @@
deviceService.addListener(deviceListener);
linkService.addListener(linkListener);
hostService.addListener(hostListener);
- mastershipService.addListener(mastershipListener);
intentService.addListener(intentListener);
}
@@ -413,7 +442,6 @@
deviceService.removeListener(deviceListener);
linkService.removeListener(linkListener);
hostService.removeListener(hostListener);
- mastershipService.removeListener(mastershipListener);
intentService.removeListener(intentListener);
}
}
@@ -450,35 +478,23 @@
}
}
- // Mastership event listener.
- private class InternalMastershipListener implements MastershipListener {
- @Override
- public void event(MastershipEvent event) {
- // TODO: Is DeviceEvent.Type.DEVICE_MASTERSHIP_CHANGED the same?
-
- }
- }
-
// Intent event listener.
private class InternalIntentListener implements IntentListener {
@Override
public void event(IntentEvent event) {
- Intent intent = event.subject();
- Long sid = intentsToMonitor.get(intent);
- if (sid != null) {
- List<Intent> installable = intentService.getInstallableIntents(intent.id());
- if (installable != null && !installable.isEmpty()) {
- PathIntent pathIntent = (PathIntent) installable.iterator().next();
- Path path = pathIntent.path();
- ObjectNode payload = pathMessage(path, "host")
- .put("intentId", intent.id().toString());
- sendMessage(envelope("showPath", sid, payload));
- TrafficClass tc = new TrafficClass("animated", intentsToMonitor.keySet());
- sendMessage(trafficMessage(sid, tc));
- }
+ if (monitorRequest != null) {
+ requestTraffic(monitorRequest);
}
}
}
+ private class IntentTrafficMonitor extends TimerTask {
+ @Override
+ public void run() {
+ if (monitorRequest != null) {
+ requestTraffic(monitorRequest);
+ }
+ }
+ }
}