GUI traffic visualization work on server-side.
Change-Id: I2e903ec028ea40fd325f69c4d7e1f0b2b6db2f42
Showing
2 changed files
with
98 additions
and
61 deletions
... | @@ -44,6 +44,7 @@ import org.onlab.onos.net.intent.ConnectivityIntent; | ... | @@ -44,6 +44,7 @@ import org.onlab.onos.net.intent.ConnectivityIntent; |
44 | import org.onlab.onos.net.intent.Intent; | 44 | import org.onlab.onos.net.intent.Intent; |
45 | import org.onlab.onos.net.intent.IntentService; | 45 | import org.onlab.onos.net.intent.IntentService; |
46 | import org.onlab.onos.net.intent.LinkCollectionIntent; | 46 | import org.onlab.onos.net.intent.LinkCollectionIntent; |
47 | +import org.onlab.onos.net.intent.OpticalConnectivityIntent; | ||
47 | import org.onlab.onos.net.intent.PathIntent; | 48 | import org.onlab.onos.net.intent.PathIntent; |
48 | import org.onlab.onos.net.link.LinkEvent; | 49 | import org.onlab.onos.net.link.LinkEvent; |
49 | import org.onlab.onos.net.link.LinkService; | 50 | import org.onlab.onos.net.link.LinkService; |
... | @@ -88,6 +89,7 @@ public abstract class TopologyMessages { | ... | @@ -88,6 +89,7 @@ public abstract class TopologyMessages { |
88 | protected final HostService hostService; | 89 | protected final HostService hostService; |
89 | protected final MastershipService mastershipService; | 90 | protected final MastershipService mastershipService; |
90 | protected final IntentService intentService; | 91 | protected final IntentService intentService; |
92 | +// protected final StatisticService statService; | ||
91 | 93 | ||
92 | protected final ObjectMapper mapper = new ObjectMapper(); | 94 | protected final ObjectMapper mapper = new ObjectMapper(); |
93 | 95 | ||
... | @@ -107,6 +109,7 @@ public abstract class TopologyMessages { | ... | @@ -107,6 +109,7 @@ public abstract class TopologyMessages { |
107 | hostService = directory.get(HostService.class); | 109 | hostService = directory.get(HostService.class); |
108 | mastershipService = directory.get(MastershipService.class); | 110 | mastershipService = directory.get(MastershipService.class); |
109 | intentService = directory.get(IntentService.class); | 111 | intentService = directory.get(IntentService.class); |
112 | +// statService = directory.get(StatisticService.class); | ||
110 | } | 113 | } |
111 | 114 | ||
112 | // Retrieves the payload from the specified event. | 115 | // Retrieves the payload from the specified event. |
... | @@ -376,10 +379,14 @@ public abstract class TopologyMessages { | ... | @@ -376,10 +379,14 @@ public abstract class TopologyMessages { |
376 | 379 | ||
377 | for (TrafficClass trafficClass : trafficClasses) { | 380 | for (TrafficClass trafficClass : trafficClasses) { |
378 | for (Intent intent : trafficClass.intents) { | 381 | for (Intent intent : trafficClass.intents) { |
382 | + boolean isOptical = intent instanceof OpticalConnectivityIntent; | ||
379 | List<Intent> installables = intentService.getInstallableIntents(intent.id()); | 383 | List<Intent> installables = intentService.getInstallableIntents(intent.id()); |
380 | - for (Intent installable : installables) { | 384 | + if (installables != null) { |
381 | - if (installable instanceof ConnectivityIntent) { | 385 | + for (Intent installable : installables) { |
382 | - addPathTraffic(paths, trafficClass.type, (ConnectivityIntent) installable); | 386 | + String cls = isOptical ? trafficClass.type + " optical" : trafficClass.type; |
387 | + if (installable instanceof ConnectivityIntent) { | ||
388 | + addPathTraffic(paths, cls, (ConnectivityIntent) installable); | ||
389 | + } | ||
383 | } | 390 | } |
384 | } | 391 | } |
385 | } | 392 | } |
... | @@ -395,20 +402,34 @@ public abstract class TopologyMessages { | ... | @@ -395,20 +402,34 @@ public abstract class TopologyMessages { |
395 | ObjectNode pathNode = mapper.createObjectNode(); | 402 | ObjectNode pathNode = mapper.createObjectNode(); |
396 | ArrayNode linksNode = mapper.createArrayNode(); | 403 | ArrayNode linksNode = mapper.createArrayNode(); |
397 | 404 | ||
398 | - Iterable<Link> links; | 405 | + Iterable<Link> links = pathLinks(installable); |
399 | - if (installable instanceof PathIntent) { | 406 | + if (links != null) { |
400 | - links = ((PathIntent) installable).path().links(); | 407 | + ArrayNode labels = mapper.createArrayNode(); |
401 | - } else if (installable instanceof LinkCollectionIntent) { | 408 | + boolean hasTraffic = true; // FIXME |
402 | - links = ((LinkCollectionIntent) installable).links(); | 409 | + for (Link link : links) { |
403 | - } else { | 410 | + linksNode.add(compactLinkString(link)); |
404 | - return; | 411 | +// Load load = statService.load(link); |
412 | + String label = ""; | ||
413 | +// if (load.rate() > 0) { | ||
414 | +// label = load.toString(); | ||
415 | +// } | ||
416 | + labels.add(label); | ||
417 | + } | ||
418 | + pathNode.put("class", hasTraffic ? type + " animated" : type); | ||
419 | + pathNode.put("traffic", hasTraffic); | ||
420 | + pathNode.set("links", linksNode); | ||
421 | + pathNode.set("labels", labels); | ||
422 | + paths.add(pathNode); | ||
405 | } | 423 | } |
424 | + } | ||
406 | 425 | ||
407 | - for (Link link : links) { | 426 | + private Iterable<Link> pathLinks(ConnectivityIntent intent) { |
408 | - linksNode.add(compactLinkString(link)); | 427 | + if (intent instanceof PathIntent) { |
428 | + return ((PathIntent) intent).path().links(); | ||
429 | + } else if (intent instanceof LinkCollectionIntent) { | ||
430 | + return ((LinkCollectionIntent) intent).links(); | ||
409 | } | 431 | } |
410 | - pathNode.put("type", type).set("links", linksNode); | 432 | + return null; |
411 | - paths.add(pathNode); | ||
412 | } | 433 | } |
413 | 434 | ||
414 | // Produces compact string representation of a link. | 435 | // Produces compact string representation of a link. | ... | ... |
... | @@ -24,8 +24,6 @@ import org.onlab.onos.cluster.ClusterEventListener; | ... | @@ -24,8 +24,6 @@ import org.onlab.onos.cluster.ClusterEventListener; |
24 | import org.onlab.onos.cluster.ControllerNode; | 24 | import org.onlab.onos.cluster.ControllerNode; |
25 | import org.onlab.onos.core.ApplicationId; | 25 | import org.onlab.onos.core.ApplicationId; |
26 | import org.onlab.onos.core.CoreService; | 26 | import org.onlab.onos.core.CoreService; |
27 | -import org.onlab.onos.mastership.MastershipEvent; | ||
28 | -import org.onlab.onos.mastership.MastershipListener; | ||
29 | import org.onlab.onos.net.ConnectPoint; | 27 | import org.onlab.onos.net.ConnectPoint; |
30 | import org.onlab.onos.net.Device; | 28 | import org.onlab.onos.net.Device; |
31 | import org.onlab.onos.net.Host; | 29 | import org.onlab.onos.net.Host; |
... | @@ -43,6 +41,7 @@ import org.onlab.onos.net.intent.Intent; | ... | @@ -43,6 +41,7 @@ import org.onlab.onos.net.intent.Intent; |
43 | import org.onlab.onos.net.intent.IntentEvent; | 41 | import org.onlab.onos.net.intent.IntentEvent; |
44 | import org.onlab.onos.net.intent.IntentListener; | 42 | import org.onlab.onos.net.intent.IntentListener; |
45 | import org.onlab.onos.net.intent.MultiPointToSinglePointIntent; | 43 | import org.onlab.onos.net.intent.MultiPointToSinglePointIntent; |
44 | +import org.onlab.onos.net.intent.OpticalConnectivityIntent; | ||
46 | import org.onlab.onos.net.intent.PathIntent; | 45 | import org.onlab.onos.net.intent.PathIntent; |
47 | import org.onlab.onos.net.intent.PointToPointIntent; | 46 | import org.onlab.onos.net.intent.PointToPointIntent; |
48 | import org.onlab.onos.net.link.LinkEvent; | 47 | import org.onlab.onos.net.link.LinkEvent; |
... | @@ -52,9 +51,9 @@ import org.onlab.osgi.ServiceDirectory; | ... | @@ -52,9 +51,9 @@ import org.onlab.osgi.ServiceDirectory; |
52 | import java.io.IOException; | 51 | import java.io.IOException; |
53 | import java.util.HashSet; | 52 | import java.util.HashSet; |
54 | import java.util.List; | 53 | import java.util.List; |
55 | -import java.util.Map; | ||
56 | import java.util.Set; | 54 | import java.util.Set; |
57 | -import java.util.concurrent.ConcurrentHashMap; | 55 | +import java.util.Timer; |
56 | +import java.util.TimerTask; | ||
58 | 57 | ||
59 | import static com.google.common.base.Strings.isNullOrEmpty; | 58 | import static com.google.common.base.Strings.isNullOrEmpty; |
60 | import static org.onlab.onos.cluster.ClusterEvent.Type.INSTANCE_ADDED; | 59 | import static org.onlab.onos.cluster.ClusterEvent.Type.INSTANCE_ADDED; |
... | @@ -62,6 +61,7 @@ import static org.onlab.onos.net.DeviceId.deviceId; | ... | @@ -62,6 +61,7 @@ import static org.onlab.onos.net.DeviceId.deviceId; |
62 | import static org.onlab.onos.net.HostId.hostId; | 61 | import static org.onlab.onos.net.HostId.hostId; |
63 | import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_ADDED; | 62 | import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_ADDED; |
64 | import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED; | 63 | import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED; |
64 | +import static org.onlab.onos.net.intent.IntentState.INSTALLED; | ||
65 | import static org.onlab.onos.net.link.LinkEvent.Type.LINK_ADDED; | 65 | import static org.onlab.onos.net.link.LinkEvent.Type.LINK_ADDED; |
66 | 66 | ||
67 | /** | 67 | /** |
... | @@ -79,6 +79,8 @@ public class TopologyWebSocket | ... | @@ -79,6 +79,8 @@ public class TopologyWebSocket |
79 | 79 | ||
80 | private static final String APP_ID = "org.onlab.onos.gui"; | 80 | private static final String APP_ID = "org.onlab.onos.gui"; |
81 | 81 | ||
82 | + private static final long TRAFFIC_FREQUENCY_SEC = 5000; | ||
83 | + | ||
82 | private final ApplicationId appId; | 84 | private final ApplicationId appId; |
83 | 85 | ||
84 | private Connection connection; | 86 | private Connection connection; |
... | @@ -88,11 +90,12 @@ public class TopologyWebSocket | ... | @@ -88,11 +90,12 @@ public class TopologyWebSocket |
88 | private final DeviceListener deviceListener = new InternalDeviceListener(); | 90 | private final DeviceListener deviceListener = new InternalDeviceListener(); |
89 | private final LinkListener linkListener = new InternalLinkListener(); | 91 | private final LinkListener linkListener = new InternalLinkListener(); |
90 | private final HostListener hostListener = new InternalHostListener(); | 92 | private final HostListener hostListener = new InternalHostListener(); |
91 | - private final MastershipListener mastershipListener = new InternalMastershipListener(); | ||
92 | private final IntentListener intentListener = new InternalIntentListener(); | 93 | private final IntentListener intentListener = new InternalIntentListener(); |
93 | 94 | ||
94 | // Intents that are being monitored for the GUI | 95 | // Intents that are being monitored for the GUI |
95 | - private Map<Intent, Long> intentsToMonitor = new ConcurrentHashMap<>(); | 96 | + private ObjectNode monitorRequest; |
97 | + private final Timer timer = new Timer("intent-traffic-monitor"); | ||
98 | + private final TimerTask timerTask = new IntentTrafficMonitor(); | ||
96 | 99 | ||
97 | private long lastActive = System.currentTimeMillis(); | 100 | private long lastActive = System.currentTimeMillis(); |
98 | private boolean listenersRemoved = false; | 101 | private boolean listenersRemoved = false; |
... | @@ -141,6 +144,7 @@ public class TopologyWebSocket | ... | @@ -141,6 +144,7 @@ public class TopologyWebSocket |
141 | this.connection = connection; | 144 | this.connection = connection; |
142 | this.control = (FrameConnection) connection; | 145 | this.control = (FrameConnection) connection; |
143 | addListeners(); | 146 | addListeners(); |
147 | + timer.schedule(timerTask, TRAFFIC_FREQUENCY_SEC, TRAFFIC_FREQUENCY_SEC); | ||
144 | 148 | ||
145 | sendAllInstances(); | 149 | sendAllInstances(); |
146 | sendAllDevices(); | 150 | sendAllDevices(); |
... | @@ -151,6 +155,7 @@ public class TopologyWebSocket | ... | @@ -151,6 +155,7 @@ public class TopologyWebSocket |
151 | @Override | 155 | @Override |
152 | public synchronized void onClose(int closeCode, String message) { | 156 | public synchronized void onClose(int closeCode, String message) { |
153 | removeListeners(); | 157 | removeListeners(); |
158 | + timer.cancel(); | ||
154 | log.info("GUI client disconnected"); | 159 | log.info("GUI client disconnected"); |
155 | } | 160 | } |
156 | 161 | ||
... | @@ -245,14 +250,15 @@ public class TopologyWebSocket | ... | @@ -245,14 +250,15 @@ public class TopologyWebSocket |
245 | HostToHostIntent hostIntent = new HostToHostIntent(appId, one, two, | 250 | HostToHostIntent hostIntent = new HostToHostIntent(appId, one, two, |
246 | DefaultTrafficSelector.builder().build(), | 251 | DefaultTrafficSelector.builder().build(), |
247 | DefaultTrafficTreatment.builder().build()); | 252 | DefaultTrafficTreatment.builder().build()); |
248 | - intentsToMonitor.put(hostIntent, number(event, "sid")); | 253 | + monitorRequest = event; |
249 | intentService.submit(hostIntent); | 254 | intentService.submit(hostIntent); |
250 | } | 255 | } |
251 | 256 | ||
252 | // Sends traffic message. | 257 | // Sends traffic message. |
253 | - private void requestTraffic(ObjectNode event) { | 258 | + private synchronized void requestTraffic(ObjectNode event) { |
254 | ObjectNode payload = payload(event); | 259 | ObjectNode payload = payload(event); |
255 | long sid = number(event, "sid"); | 260 | long sid = number(event, "sid"); |
261 | + monitorRequest = event; | ||
256 | 262 | ||
257 | // Get the set of selected hosts and their intents. | 263 | // Get the set of selected hosts and their intents. |
258 | Set<Host> hosts = getHosts((ArrayNode) payload.path("ids")); | 264 | Set<Host> hosts = getHosts((ArrayNode) payload.path("ids")); |
... | @@ -274,18 +280,13 @@ public class TopologyWebSocket | ... | @@ -274,18 +280,13 @@ public class TopologyWebSocket |
274 | } else { | 280 | } else { |
275 | // Send an initial message to highlight all links of all monitored intents. | 281 | // Send an initial message to highlight all links of all monitored intents. |
276 | sendMessage(trafficMessage(sid, new TrafficClass("primary", intents))); | 282 | sendMessage(trafficMessage(sid, new TrafficClass("primary", intents))); |
277 | - | ||
278 | - // Add all those intents to the list of monitored intents & flows. | ||
279 | - intentsToMonitor.clear(); | ||
280 | - for (Intent intent : intents) { | ||
281 | - intentsToMonitor.put(intent, sid); | ||
282 | - } | ||
283 | } | 283 | } |
284 | } | 284 | } |
285 | 285 | ||
286 | // Cancels sending traffic messages. | 286 | // Cancels sending traffic messages. |
287 | private void cancelTraffic(ObjectNode event) { | 287 | private void cancelTraffic(ObjectNode event) { |
288 | sendMessage(trafficMessage(number(event, "sid"))); | 288 | sendMessage(trafficMessage(number(event, "sid"))); |
289 | + monitorRequest = null; | ||
289 | } | 290 | } |
290 | 291 | ||
291 | // Finds all path (host-to-host or point-to-point) intents that pertains | 292 | // Finds all path (host-to-host or point-to-point) intents that pertains |
... | @@ -306,18 +307,30 @@ public class TopologyWebSocket | ... | @@ -306,18 +307,30 @@ public class TopologyWebSocket |
306 | return intents; | 307 | return intents; |
307 | } | 308 | } |
308 | 309 | ||
310 | + Set<OpticalConnectivityIntent> opticalIntents = new HashSet<>(); | ||
311 | + | ||
309 | for (Intent intent : intentService.getIntents()) { | 312 | for (Intent intent : intentService.getIntents()) { |
310 | - boolean isRelevant = false; | 313 | + if (intentService.getIntentState(intent.id()) == INSTALLED) { |
311 | - if (intent instanceof HostToHostIntent) { | 314 | + boolean isRelevant = false; |
312 | - isRelevant = isIntentRelevant((HostToHostIntent) intent, hosts); | 315 | + if (intent instanceof HostToHostIntent) { |
313 | - } else if (intent instanceof PointToPointIntent) { | 316 | + isRelevant = isIntentRelevant((HostToHostIntent) intent, hosts); |
314 | - isRelevant = isIntentRelevant((PointToPointIntent) intent, edgePoints); | 317 | + } else if (intent instanceof PointToPointIntent) { |
315 | - } else if (intent instanceof MultiPointToSinglePointIntent) { | 318 | + isRelevant = isIntentRelevant((PointToPointIntent) intent, edgePoints); |
316 | - isRelevant = isIntentRelevant((MultiPointToSinglePointIntent) intent, edgePoints); | 319 | + } else if (intent instanceof MultiPointToSinglePointIntent) { |
320 | + isRelevant = isIntentRelevant((MultiPointToSinglePointIntent) intent, edgePoints); | ||
321 | + } else if (intent instanceof OpticalConnectivityIntent) { | ||
322 | + opticalIntents.add((OpticalConnectivityIntent) intent); | ||
323 | + } | ||
324 | + // TODO: add other intents, e.g. SinglePointToMultiPointIntent | ||
325 | + | ||
326 | + if (isRelevant) { | ||
327 | + intents.add(intent); | ||
328 | + } | ||
317 | } | 329 | } |
318 | - // TODO: add other intents, e.g. SinglePointToMultiPointIntent | 330 | + } |
319 | 331 | ||
320 | - if (isRelevant) { | 332 | + for (OpticalConnectivityIntent intent : opticalIntents) { |
333 | + if (isIntentRelevant(intent, intents)) { | ||
321 | intents.add(intent); | 334 | intents.add(intent); |
322 | } | 335 | } |
323 | } | 336 | } |
... | @@ -362,6 +375,23 @@ public class TopologyWebSocket | ... | @@ -362,6 +375,23 @@ public class TopologyWebSocket |
362 | return true; | 375 | return true; |
363 | } | 376 | } |
364 | 377 | ||
378 | + // Indicates whether the specified intent involves all of the given edge points. | ||
379 | + private boolean isIntentRelevant(OpticalConnectivityIntent opticalIntent, | ||
380 | + Set<Intent> intents) { | ||
381 | + for (Intent intent : intents) { | ||
382 | + List<Intent> installables = intentService.getInstallableIntents(intent.id()); | ||
383 | + for (Intent installable : installables) { | ||
384 | + if (installable instanceof PathIntent) { | ||
385 | + Path path = ((PathIntent) installable).path(); | ||
386 | + if (opticalIntent.getSrcConnectPoint().equals(path.src()) && | ||
387 | + opticalIntent.getDst().equals(path.dst())) { | ||
388 | + return true; | ||
389 | + } | ||
390 | + } | ||
391 | + } | ||
392 | + } | ||
393 | + return false; | ||
394 | + } | ||
365 | 395 | ||
366 | // Produces a set of all host ids listed in the specified JSON array. | 396 | // Produces a set of all host ids listed in the specified JSON array. |
367 | private Set<Host> getHosts(ArrayNode array) { | 397 | private Set<Host> getHosts(ArrayNode array) { |
... | @@ -401,7 +431,6 @@ public class TopologyWebSocket | ... | @@ -401,7 +431,6 @@ public class TopologyWebSocket |
401 | deviceService.addListener(deviceListener); | 431 | deviceService.addListener(deviceListener); |
402 | linkService.addListener(linkListener); | 432 | linkService.addListener(linkListener); |
403 | hostService.addListener(hostListener); | 433 | hostService.addListener(hostListener); |
404 | - mastershipService.addListener(mastershipListener); | ||
405 | intentService.addListener(intentListener); | 434 | intentService.addListener(intentListener); |
406 | } | 435 | } |
407 | 436 | ||
... | @@ -413,7 +442,6 @@ public class TopologyWebSocket | ... | @@ -413,7 +442,6 @@ public class TopologyWebSocket |
413 | deviceService.removeListener(deviceListener); | 442 | deviceService.removeListener(deviceListener); |
414 | linkService.removeListener(linkListener); | 443 | linkService.removeListener(linkListener); |
415 | hostService.removeListener(hostListener); | 444 | hostService.removeListener(hostListener); |
416 | - mastershipService.removeListener(mastershipListener); | ||
417 | intentService.removeListener(intentListener); | 445 | intentService.removeListener(intentListener); |
418 | } | 446 | } |
419 | } | 447 | } |
... | @@ -450,35 +478,23 @@ public class TopologyWebSocket | ... | @@ -450,35 +478,23 @@ public class TopologyWebSocket |
450 | } | 478 | } |
451 | } | 479 | } |
452 | 480 | ||
453 | - // Mastership event listener. | ||
454 | - private class InternalMastershipListener implements MastershipListener { | ||
455 | - @Override | ||
456 | - public void event(MastershipEvent event) { | ||
457 | - // TODO: Is DeviceEvent.Type.DEVICE_MASTERSHIP_CHANGED the same? | ||
458 | - | ||
459 | - } | ||
460 | - } | ||
461 | - | ||
462 | // Intent event listener. | 481 | // Intent event listener. |
463 | private class InternalIntentListener implements IntentListener { | 482 | private class InternalIntentListener implements IntentListener { |
464 | @Override | 483 | @Override |
465 | public void event(IntentEvent event) { | 484 | public void event(IntentEvent event) { |
466 | - Intent intent = event.subject(); | 485 | + if (monitorRequest != null) { |
467 | - Long sid = intentsToMonitor.get(intent); | 486 | + requestTraffic(monitorRequest); |
468 | - if (sid != null) { | ||
469 | - List<Intent> installable = intentService.getInstallableIntents(intent.id()); | ||
470 | - if (installable != null && !installable.isEmpty()) { | ||
471 | - PathIntent pathIntent = (PathIntent) installable.iterator().next(); | ||
472 | - Path path = pathIntent.path(); | ||
473 | - ObjectNode payload = pathMessage(path, "host") | ||
474 | - .put("intentId", intent.id().toString()); | ||
475 | - sendMessage(envelope("showPath", sid, payload)); | ||
476 | - TrafficClass tc = new TrafficClass("animated", intentsToMonitor.keySet()); | ||
477 | - sendMessage(trafficMessage(sid, tc)); | ||
478 | - } | ||
479 | } | 487 | } |
480 | } | 488 | } |
481 | } | 489 | } |
482 | 490 | ||
491 | + private class IntentTrafficMonitor extends TimerTask { | ||
492 | + @Override | ||
493 | + public void run() { | ||
494 | + if (monitorRequest != null) { | ||
495 | + requestTraffic(monitorRequest); | ||
496 | + } | ||
497 | + } | ||
498 | + } | ||
483 | } | 499 | } |
484 | 500 | ... | ... |
-
Please register or login to post a comment