Thomas Vachuska
Committed by Gerrit Code Review

GUI -- Added port-statistics traffic visualization to the topo view.

Change-Id: I52b3c1739cc50a026c0796819d61ec1898937ced
...@@ -26,13 +26,14 @@ public class DefaultLoad implements Load { ...@@ -26,13 +26,14 @@ public class DefaultLoad implements Load {
26 private final long current; 26 private final long current;
27 private final long previous; 27 private final long previous;
28 private final long time; 28 private final long time;
29 + private final int interval;
29 30
30 /** 31 /**
31 * Indicates the flow statistics poll interval in seconds. 32 * Indicates the flow statistics poll interval in seconds.
32 */ 33 */
33 private static int pollInterval = 10; 34 private static int pollInterval = 10;
34 35
35 - /** 36 + /**
36 * Creates an invalid load. 37 * Creates an invalid load.
37 */ 38 */
38 public DefaultLoad() { 39 public DefaultLoad() {
...@@ -40,18 +41,32 @@ public class DefaultLoad implements Load { ...@@ -40,18 +41,32 @@ public class DefaultLoad implements Load {
40 this.time = System.currentTimeMillis(); 41 this.time = System.currentTimeMillis();
41 this.current = -1; 42 this.current = -1;
42 this.previous = -1; 43 this.previous = -1;
44 + this.interval = pollInterval;
43 } 45 }
44 46
45 /** 47 /**
46 * Creates a load value from the parameters. 48 * Creates a load value from the parameters.
47 - * @param current the current value 49 + *
50 + * @param current the current value
48 * @param previous the previous value 51 * @param previous the previous value
49 */ 52 */
50 public DefaultLoad(long current, long previous) { 53 public DefaultLoad(long current, long previous) {
54 + this(current, previous, pollInterval);
55 + }
56 +
57 + /**
58 + * Creates a load value from the parameters.
59 + *
60 + * @param current the current value
61 + * @param previous the previous value
62 + * @param interval poll interval for this load
63 + */
64 + public DefaultLoad(long current, long previous, int interval) {
51 this.current = current; 65 this.current = current;
52 this.previous = previous; 66 this.previous = previous;
53 this.time = System.currentTimeMillis(); 67 this.time = System.currentTimeMillis();
54 this.isValid = true; 68 this.isValid = true;
69 + this.interval = interval;
55 } 70 }
56 71
57 /** 72 /**
...@@ -66,7 +81,7 @@ public class DefaultLoad implements Load { ...@@ -66,7 +81,7 @@ public class DefaultLoad implements Load {
66 81
67 @Override 82 @Override
68 public long rate() { 83 public long rate() {
69 - return (current - previous) / pollInterval; 84 + return (current - previous) / interval;
70 } 85 }
71 86
72 @Override 87 @Override
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.incubator.net;
17 +
18 +import org.onosproject.net.ConnectPoint;
19 +import org.onosproject.net.statistic.Load;
20 +
21 +/**
22 + * Service for obtaining statistic information about device ports.
23 + */
24 +public interface PortStatisticsService {
25 +
26 + /**
27 + * Obtain the egress load for the given port.
28 + *
29 + * @param connectPoint the port to query
30 + * @return egress traffic load
31 + */
32 + Load load(ConnectPoint connectPoint);
33 +
34 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.incubator.net.impl;
17 +
18 +import com.google.common.collect.Maps;
19 +import org.apache.felix.scr.annotations.Activate;
20 +import org.apache.felix.scr.annotations.Component;
21 +import org.apache.felix.scr.annotations.Deactivate;
22 +import org.apache.felix.scr.annotations.Reference;
23 +import org.apache.felix.scr.annotations.ReferenceCardinality;
24 +import org.apache.felix.scr.annotations.Service;
25 +import org.onosproject.incubator.net.PortStatisticsService;
26 +import org.onosproject.net.ConnectPoint;
27 +import org.onosproject.net.DeviceId;
28 +import org.onosproject.net.device.DeviceEvent;
29 +import org.onosproject.net.device.DeviceListener;
30 +import org.onosproject.net.device.DeviceService;
31 +import org.onosproject.net.device.PortStatistics;
32 +import org.onosproject.net.statistic.DefaultLoad;
33 +import org.onosproject.net.statistic.Load;
34 +import org.slf4j.Logger;
35 +
36 +import java.util.Map;
37 +import java.util.stream.Collectors;
38 +
39 +import static org.onosproject.net.PortNumber.portNumber;
40 +import static org.onosproject.net.device.DeviceEvent.Type.*;
41 +import static org.slf4j.LoggerFactory.getLogger;
42 +
43 +/**
44 + * Implementation of the port statistics service.
45 + */
46 +@Component(immediate = true)
47 +@Service
48 +public class PortStatisticsManager implements PortStatisticsService {
49 + private final Logger log = getLogger(getClass());
50 +
51 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
52 + protected DeviceService deviceService;
53 +
54 + private final DeviceListener deviceListener = new InternalDeviceListener();
55 +
56 + private Map<ConnectPoint, DataPoint> current = Maps.newConcurrentMap();
57 + private Map<ConnectPoint, DataPoint> previous = Maps.newConcurrentMap();
58 +
59 + @Activate
60 + public void activate() {
61 + deviceService.addListener(deviceListener);
62 + log.info("Started");
63 +
64 + }
65 +
66 + @Deactivate
67 + public void deactivate() {
68 + deviceService.removeListener(deviceListener);
69 + log.info("Stopped");
70 + }
71 +
72 + @Override
73 + public Load load(ConnectPoint connectPoint) {
74 + DataPoint c = current.get(connectPoint);
75 + DataPoint p = previous.get(connectPoint);
76 + if (c != null && p != null) {
77 + return new DefaultLoad(c.stats.bytesSent(), p.stats.bytesSent(),
78 + (int) (c.time - p.time) / 1000);
79 + }
80 + return null;
81 + }
82 +
83 + // Monitors port stats update messages.
84 + private class InternalDeviceListener implements DeviceListener {
85 + @Override
86 + public void event(DeviceEvent event) {
87 + DeviceEvent.Type type = event.type();
88 + DeviceId deviceId = event.subject().id();
89 + if (type == PORT_STATS_UPDATED) {
90 + // Update port load
91 + updateDeviceData(deviceId);
92 +
93 + } else if (type == DEVICE_REMOVED ||
94 + (type == DEVICE_AVAILABILITY_CHANGED &&
95 + !deviceService.isAvailable(deviceId))) {
96 + // Clean-up all port loads
97 + pruneDeviceData(deviceId);
98 + }
99 + }
100 + }
101 +
102 + // Updates the port stats for the specified device
103 + private void updateDeviceData(DeviceId deviceId) {
104 + deviceService.getPortStatistics(deviceId)
105 + .forEach(stats -> updatePortData(deviceId, stats));
106 + }
107 +
108 + // Updates the port stats for the specified port
109 + private void updatePortData(DeviceId deviceId, PortStatistics stats) {
110 + ConnectPoint cp = new ConnectPoint(deviceId, portNumber(stats.port()));
111 +
112 + // If we have a current data point, demote it to previous
113 + DataPoint c = current.get(cp);
114 + if (c != null) {
115 + previous.put(cp, c);
116 + }
117 +
118 + // Create a new data point and make it the current one
119 + current.put(cp, new DataPoint(stats));
120 + }
121 +
122 + // Cleans all port loads for the specified device
123 + private void pruneDeviceData(DeviceId deviceId) {
124 + pruneMap(current, deviceId);
125 + pruneMap(previous, deviceId);
126 + }
127 +
128 + private void pruneMap(Map<ConnectPoint, DataPoint> map, DeviceId deviceId) {
129 + map.keySet().stream().filter(cp -> deviceId.equals(cp.deviceId()))
130 + .collect(Collectors.toSet()).forEach(map::remove);
131 + }
132 +
133 + // Auxiliary data point to track when we receive different samples.
134 + private class DataPoint {
135 + long time;
136 + PortStatistics stats;
137 +
138 + DataPoint(PortStatistics stats) {
139 + time = System.currentTimeMillis();
140 + this.stats = stats;
141 + }
142 + }
143 +
144 +}
...@@ -15,14 +15,15 @@ ...@@ -15,14 +15,15 @@
15 */ 15 */
16 package org.onosproject.provider.of.device.impl; 16 package org.onosproject.provider.of.device.impl;
17 17
18 +import com.google.common.base.Strings;
18 import com.google.common.collect.Maps; 19 import com.google.common.collect.Maps;
19 import com.google.common.collect.Sets; 20 import com.google.common.collect.Sets;
20 -
21 import org.apache.felix.scr.annotations.Activate; 21 import org.apache.felix.scr.annotations.Activate;
22 import org.apache.felix.scr.annotations.Component; 22 import org.apache.felix.scr.annotations.Component;
23 import org.apache.felix.scr.annotations.Deactivate; 23 import org.apache.felix.scr.annotations.Deactivate;
24 import org.apache.felix.scr.annotations.Reference; 24 import org.apache.felix.scr.annotations.Reference;
25 import org.apache.felix.scr.annotations.ReferenceCardinality; 25 import org.apache.felix.scr.annotations.ReferenceCardinality;
26 +import org.onlab.packet.ChassisId;
26 import org.onosproject.net.AnnotationKeys; 27 import org.onosproject.net.AnnotationKeys;
27 import org.onosproject.net.DefaultAnnotations; 28 import org.onosproject.net.DefaultAnnotations;
28 import org.onosproject.net.Device; 29 import org.onosproject.net.Device;
...@@ -50,7 +51,6 @@ import org.onosproject.openflow.controller.OpenFlowSwitch; ...@@ -50,7 +51,6 @@ import org.onosproject.openflow.controller.OpenFlowSwitch;
50 import org.onosproject.openflow.controller.OpenFlowSwitchListener; 51 import org.onosproject.openflow.controller.OpenFlowSwitchListener;
51 import org.onosproject.openflow.controller.PortDescPropertyType; 52 import org.onosproject.openflow.controller.PortDescPropertyType;
52 import org.onosproject.openflow.controller.RoleState; 53 import org.onosproject.openflow.controller.RoleState;
53 -import org.onlab.packet.ChassisId;
54 import org.projectfloodlight.openflow.protocol.OFFactory; 54 import org.projectfloodlight.openflow.protocol.OFFactory;
55 import org.projectfloodlight.openflow.protocol.OFMessage; 55 import org.projectfloodlight.openflow.protocol.OFMessage;
56 import org.projectfloodlight.openflow.protocol.OFPortConfig; 56 import org.projectfloodlight.openflow.protocol.OFPortConfig;
...@@ -75,8 +75,6 @@ import java.util.HashMap; ...@@ -75,8 +75,6 @@ import java.util.HashMap;
75 import java.util.HashSet; 75 import java.util.HashSet;
76 import java.util.List; 76 import java.util.List;
77 77
78 -import com.google.common.base.Strings;
79 -
80 import static org.onosproject.net.DeviceId.deviceId; 78 import static org.onosproject.net.DeviceId.deviceId;
81 import static org.onosproject.net.Port.Type.COPPER; 79 import static org.onosproject.net.Port.Type.COPPER;
82 import static org.onosproject.net.Port.Type.FIBER; 80 import static org.onosproject.net.Port.Type.FIBER;
...@@ -204,36 +202,37 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr ...@@ -204,36 +202,37 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
204 202
205 private void pushPortMetrics(Dpid dpid, OFPortStatsReply msg) { 203 private void pushPortMetrics(Dpid dpid, OFPortStatsReply msg) {
206 DeviceId deviceId = DeviceId.deviceId(dpid.uri(dpid)); 204 DeviceId deviceId = DeviceId.deviceId(dpid.uri(dpid));
207 -
208 Collection<PortStatistics> stats = buildPortStatistics(deviceId, msg); 205 Collection<PortStatistics> stats = buildPortStatistics(deviceId, msg);
209 -
210 providerService.updatePortStatistics(deviceId, stats); 206 providerService.updatePortStatistics(deviceId, stats);
211 } 207 }
212 208
213 private Collection<PortStatistics> buildPortStatistics(DeviceId deviceId, OFPortStatsReply msg) { 209 private Collection<PortStatistics> buildPortStatistics(DeviceId deviceId, OFPortStatsReply msg) {
214 -
215 HashSet<PortStatistics> stats = Sets.newHashSet(); 210 HashSet<PortStatistics> stats = Sets.newHashSet();
216 211
217 for (OFPortStatsEntry entry: msg.getEntries()) { 212 for (OFPortStatsEntry entry: msg.getEntries()) {
218 - if (entry.getPortNo().getPortNumber() < 0) { 213 + try {
219 - continue; 214 + if (entry.getPortNo().getPortNumber() < 0) {
215 + continue;
216 + }
217 + DefaultPortStatistics.Builder builder = DefaultPortStatistics.builder();
218 + DefaultPortStatistics stat = builder.setDeviceId(deviceId)
219 + .setPort(entry.getPortNo().getPortNumber())
220 + .setPacketsReceived(entry.getRxPackets().getValue())
221 + .setPacketsSent(entry.getTxPackets().getValue())
222 + .setBytesReceived(entry.getRxBytes().getValue())
223 + .setBytesSent(entry.getTxBytes().getValue())
224 + .setPacketsRxDropped(entry.getRxDropped().getValue())
225 + .setPacketsTxDropped(entry.getTxDropped().getValue())
226 + .setPacketsRxErrors(entry.getRxErrors().getValue())
227 + .setPacketsTxErrors(entry.getTxErrors().getValue())
228 + .setDurationSec(entry.getVersion() == OFVersion.OF_10 ? 0 : entry.getDurationSec())
229 + .setDurationNano(entry.getVersion() == OFVersion.OF_10 ? 0 : entry.getDurationNsec())
230 + .build();
231 +
232 + stats.add(stat);
233 + } catch (Exception e) {
234 + LOG.warn("Unable to process port stats", e);
220 } 235 }
221 - DefaultPortStatistics.Builder builder = DefaultPortStatistics.builder();
222 - DefaultPortStatistics stat = builder.setDeviceId(deviceId)
223 - .setPort(entry.getPortNo().getPortNumber())
224 - .setPacketsReceived(entry.getRxPackets().getValue())
225 - .setPacketsSent(entry.getTxPackets().getValue())
226 - .setBytesReceived(entry.getRxBytes().getValue())
227 - .setBytesSent(entry.getTxBytes().getValue())
228 - .setPacketsRxDropped(entry.getRxDropped().getValue())
229 - .setPacketsTxDropped(entry.getTxDropped().getValue())
230 - .setPacketsRxErrors(entry.getRxErrors().getValue())
231 - .setPacketsTxErrors(entry.getTxErrors().getValue())
232 - .setDurationSec(entry.getDurationSec())
233 - .setDurationNano(entry.getDurationNsec())
234 - .build();
235 -
236 - stats.add(stat);
237 } 236 }
238 237
239 return Collections.unmodifiableSet(stats); 238 return Collections.unmodifiableSet(stats);
......
...@@ -92,7 +92,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -92,7 +92,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
92 private static final String REQ_NEXT_INTENT = "requestNextRelatedIntent"; 92 private static final String REQ_NEXT_INTENT = "requestNextRelatedIntent";
93 private static final String REQ_PREV_INTENT = "requestPrevRelatedIntent"; 93 private static final String REQ_PREV_INTENT = "requestPrevRelatedIntent";
94 private static final String REQ_SEL_INTENT_TRAFFIC = "requestSelectedIntentTraffic"; 94 private static final String REQ_SEL_INTENT_TRAFFIC = "requestSelectedIntentTraffic";
95 - private static final String REQ_ALL_TRAFFIC = "requestAllTraffic"; 95 + private static final String REQ_ALL_FLOW_TRAFFIC = "requestAllFlowTraffic";
96 + private static final String REQ_ALL_PORT_TRAFFIC = "requestAllPortTraffic";
96 private static final String REQ_DEV_LINK_FLOWS = "requestDeviceLinkFlows"; 97 private static final String REQ_DEV_LINK_FLOWS = "requestDeviceLinkFlows";
97 private static final String CANCEL_TRAFFIC = "cancelTraffic"; 98 private static final String CANCEL_TRAFFIC = "cancelTraffic";
98 private static final String REQ_SUMMARY = "requestSummary"; 99 private static final String REQ_SUMMARY = "requestSummary";
...@@ -187,7 +188,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -187,7 +188,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
187 new ReqNextIntent(), 188 new ReqNextIntent(),
188 new ReqPrevIntent(), 189 new ReqPrevIntent(),
189 new ReqSelectedIntentTraffic(), 190 new ReqSelectedIntentTraffic(),
190 - new ReqAllTraffic(), 191 + new ReqAllFlowTraffic(),
192 + new ReqAllPortTraffic(),
191 new ReqDevLinkFlows(), 193 new ReqDevLinkFlows(),
192 new CancelTraffic() 194 new CancelTraffic()
193 ); 195 );
...@@ -453,23 +455,33 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -453,23 +455,33 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
453 455
454 @Override 456 @Override
455 public void process(long sid, ObjectNode payload) { 457 public void process(long sid, ObjectNode payload) {
456 - trafficEvent = 458 + trafficEvent = new TrafficEvent(TrafficEvent.Type.SEL_INTENT, payload);
457 - new TrafficEvent(TrafficEvent.Type.SEL_INTENT, payload);
458 requestSelectedIntentTraffic(); 459 requestSelectedIntentTraffic();
459 startTrafficMonitoring(); 460 startTrafficMonitoring();
460 } 461 }
461 } 462 }
462 463
463 - private final class ReqAllTraffic extends RequestHandler { 464 + private final class ReqAllFlowTraffic extends RequestHandler {
464 - private ReqAllTraffic() { 465 + private ReqAllFlowTraffic() {
465 - super(REQ_ALL_TRAFFIC); 466 + super(REQ_ALL_FLOW_TRAFFIC);
466 } 467 }
467 468
468 @Override 469 @Override
469 public void process(long sid, ObjectNode payload) { 470 public void process(long sid, ObjectNode payload) {
470 - trafficEvent = 471 + trafficEvent = new TrafficEvent(TrafficEvent.Type.ALL_FLOW_TRAFFIC, payload);
471 - new TrafficEvent(TrafficEvent.Type.ALL_TRAFFIC, payload); 472 + requestAllFlowTraffic();
472 - requestAllTraffic(); 473 + }
474 + }
475 +
476 + private final class ReqAllPortTraffic extends RequestHandler {
477 + private ReqAllPortTraffic() {
478 + super(REQ_ALL_PORT_TRAFFIC);
479 + }
480 +
481 + @Override
482 + public void process(long sid, ObjectNode payload) {
483 + trafficEvent = new TrafficEvent(TrafficEvent.Type.ALL_PORT_TRAFFIC, payload);
484 + requestAllPortTraffic();
473 } 485 }
474 } 486 }
475 487
...@@ -480,8 +492,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -480,8 +492,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
480 492
481 @Override 493 @Override
482 public void process(long sid, ObjectNode payload) { 494 public void process(long sid, ObjectNode payload) {
483 - trafficEvent = 495 + trafficEvent = new TrafficEvent(TrafficEvent.Type.DEV_LINK_FLOWS, payload);
484 - new TrafficEvent(TrafficEvent.Type.DEV_LINK_FLOWS, payload);
485 requestDeviceLinkFlows(payload); 496 requestDeviceLinkFlows(payload);
486 } 497 }
487 } 498 }
...@@ -615,10 +626,16 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -615,10 +626,16 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
615 } 626 }
616 } 627 }
617 628
618 - // Subscribes for host traffic messages. 629 + // Subscribes for flow traffic messages.
619 - private synchronized void requestAllTraffic() { 630 + private synchronized void requestAllFlowTraffic() {
620 startTrafficMonitoring(); 631 startTrafficMonitoring();
621 - sendMessage(trafficSummaryMessage()); 632 + sendMessage(trafficSummaryMessage(StatsType.FLOW));
633 + }
634 +
635 + // Subscribes for port traffic messages.
636 + private synchronized void requestAllPortTraffic() {
637 + startTrafficMonitoring();
638 + sendMessage(trafficSummaryMessage(StatsType.PORT));
622 } 639 }
623 640
624 private void requestDeviceLinkFlows(ObjectNode payload) { 641 private void requestDeviceLinkFlows(ObjectNode payload) {
...@@ -822,7 +839,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -822,7 +839,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
822 // encapsulate 839 // encapsulate
823 private static class TrafficEvent { 840 private static class TrafficEvent {
824 enum Type { 841 enum Type {
825 - ALL_TRAFFIC, DEV_LINK_FLOWS, SEL_INTENT 842 + ALL_FLOW_TRAFFIC, ALL_PORT_TRAFFIC, DEV_LINK_FLOWS, SEL_INTENT
826 } 843 }
827 844
828 private final Type type; 845 private final Type type;
...@@ -841,8 +858,11 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -841,8 +858,11 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
841 try { 858 try {
842 if (trafficEvent != null) { 859 if (trafficEvent != null) {
843 switch (trafficEvent.type) { 860 switch (trafficEvent.type) {
844 - case ALL_TRAFFIC: 861 + case ALL_FLOW_TRAFFIC:
845 - requestAllTraffic(); 862 + requestAllFlowTraffic();
863 + break;
864 + case ALL_PORT_TRAFFIC:
865 + requestAllPortTraffic();
846 break; 866 break;
847 case DEV_LINK_FLOWS: 867 case DEV_LINK_FLOWS:
848 requestDeviceLinkFlows(trafficEvent.payload); 868 requestDeviceLinkFlows(trafficEvent.payload);
......
...@@ -27,6 +27,7 @@ import org.onosproject.cluster.ClusterService; ...@@ -27,6 +27,7 @@ import org.onosproject.cluster.ClusterService;
27 import org.onosproject.cluster.ControllerNode; 27 import org.onosproject.cluster.ControllerNode;
28 import org.onosproject.cluster.NodeId; 28 import org.onosproject.cluster.NodeId;
29 import org.onosproject.core.CoreService; 29 import org.onosproject.core.CoreService;
30 +import org.onosproject.incubator.net.PortStatisticsService;
30 import org.onosproject.mastership.MastershipService; 31 import org.onosproject.mastership.MastershipService;
31 import org.onosproject.net.Annotated; 32 import org.onosproject.net.Annotated;
32 import org.onosproject.net.AnnotationKeys; 33 import org.onosproject.net.AnnotationKeys;
...@@ -100,6 +101,7 @@ import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED; ...@@ -100,6 +101,7 @@ import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
100 import static org.onosproject.net.host.HostEvent.Type.HOST_REMOVED; 101 import static org.onosproject.net.host.HostEvent.Type.HOST_REMOVED;
101 import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED; 102 import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
102 import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED; 103 import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED;
104 +import static org.onosproject.ui.impl.TopologyViewMessageHandlerBase.StatsType.*;
103 105
104 /** 106 /**
105 * Facility for creating messages bound for the topology viewer. 107 * Facility for creating messages bound for the topology viewer.
...@@ -123,6 +125,8 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -123,6 +125,8 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
123 private static final String KB_UNIT = "KB"; 125 private static final String KB_UNIT = "KB";
124 private static final String B_UNIT = "B"; 126 private static final String B_UNIT = "B";
125 127
128 + private static final long BPS_THRESHOLD = 1024;
129 +
126 protected ServiceDirectory directory; 130 protected ServiceDirectory directory;
127 protected ClusterService clusterService; 131 protected ClusterService clusterService;
128 protected DeviceService deviceService; 132 protected DeviceService deviceService;
...@@ -131,9 +135,14 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -131,9 +135,14 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
131 protected MastershipService mastershipService; 135 protected MastershipService mastershipService;
132 protected IntentService intentService; 136 protected IntentService intentService;
133 protected FlowRuleService flowService; 137 protected FlowRuleService flowService;
134 - protected StatisticService statService; 138 + protected StatisticService flowStatsService;
139 + protected PortStatisticsService portStatsService;
135 protected TopologyService topologyService; 140 protected TopologyService topologyService;
136 141
142 + protected enum StatsType {
143 + FLOW, PORT
144 + }
145 +
137 private String version; 146 private String version;
138 147
139 // TODO: extract into an external & durable state; good enough for now and demo 148 // TODO: extract into an external & durable state; good enough for now and demo
...@@ -159,7 +168,8 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -159,7 +168,8 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
159 mastershipService = directory.get(MastershipService.class); 168 mastershipService = directory.get(MastershipService.class);
160 intentService = directory.get(IntentService.class); 169 intentService = directory.get(IntentService.class);
161 flowService = directory.get(FlowRuleService.class); 170 flowService = directory.get(FlowRuleService.class);
162 - statService = directory.get(StatisticService.class); 171 + flowStatsService = directory.get(StatisticService.class);
172 + portStatsService = directory.get(PortStatisticsService.class);
163 topologyService = directory.get(TopologyService.class); 173 topologyService = directory.get(TopologyService.class);
164 174
165 String ver = directory.get(CoreService.class).version().toString(); 175 String ver = directory.get(CoreService.class).version().toString();
...@@ -532,8 +542,8 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -532,8 +542,8 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
532 } 542 }
533 543
534 544
535 - // Produces JSON message to trigger traffic overview visualization 545 + // Produces JSON message to trigger flow traffic overview visualization
536 - protected ObjectNode trafficSummaryMessage() { 546 + protected ObjectNode trafficSummaryMessage(StatsType type) {
537 ObjectNode payload = objectNode(); 547 ObjectNode payload = objectNode();
538 ArrayNode paths = arrayNode(); 548 ArrayNode paths = arrayNode();
539 payload.set("paths", paths); 549 payload.set("paths", paths);
...@@ -560,11 +570,18 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -560,11 +570,18 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
560 boolean bi = link.two != null; 570 boolean bi = link.two != null;
561 if (isInfrastructureEgress(link.one) || 571 if (isInfrastructureEgress(link.one) ||
562 (bi && isInfrastructureEgress(link.two))) { 572 (bi && isInfrastructureEgress(link.two))) {
563 - link.addLoad(statService.load(link.one)); 573 + if (type == FLOW) {
564 - link.addLoad(bi ? statService.load(link.two) : null); 574 + link.addLoad(flowStatsService.load(link.one));
575 + link.addLoad(bi ? flowStatsService.load(link.two) : null);
576 + } else if (type == PORT) {
577 + link.addLoad(portStatsService.load(link.one.src()), BPS_THRESHOLD);
578 + link.addLoad(bi ? portStatsService.load(link.two.src()) : null, BPS_THRESHOLD);
579 + }
565 if (link.hasTraffic) { 580 if (link.hasTraffic) {
566 linksNodeT.add(compactLinkString(link.one)); 581 linksNodeT.add(compactLinkString(link.one));
567 - labelsT.add(formatBytes(link.bytes)); 582 + labelsT.add(type == PORT ?
583 + formatBytes(link.rate) + "ps" :
584 + formatBytes(link.bytes));
568 } else { 585 } else {
569 linksNodeN.add(compactLinkString(link.one)); 586 linksNodeN.add(compactLinkString(link.one));
570 labelsN.add(""); 587 labelsN.add("");
...@@ -692,7 +709,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -692,7 +709,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
692 BiLink biLink = addLink(biLinks, link); 709 BiLink biLink = addLink(biLinks, link);
693 if (isInfrastructureEgress(link)) { 710 if (isInfrastructureEgress(link)) {
694 if (showTraffic) { 711 if (showTraffic) {
695 - biLink.addLoad(statService.load(link)); 712 + biLink.addLoad(flowStatsService.load(link));
696 } 713 }
697 biLink.addClass(type); 714 biLink.addClass(type);
698 } 715 }
...@@ -727,7 +744,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -727,7 +744,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
727 for (Link link : links) { 744 for (Link link : links) {
728 if (isInfrastructureEgress(link)) { 745 if (isInfrastructureEgress(link)) {
729 linksNode.add(compactLinkString(link)); 746 linksNode.add(compactLinkString(link));
730 - Load load = statService.load(link); 747 + Load load = flowStatsService.load(link);
731 String label = ""; 748 String label = "";
732 if (load.rate() > 0) { 749 if (load.rate() > 0) {
733 hasTraffic = true; 750 hasTraffic = true;
...@@ -814,6 +831,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -814,6 +831,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
814 public long bytes = 0; 831 public long bytes = 0;
815 832
816 private Set<String> classes = new HashSet<>(); 833 private Set<String> classes = new HashSet<>();
834 + private long rate;
817 835
818 BiLink(LinkKey key, Link link) { 836 BiLink(LinkKey key, Link link) {
819 this.key = key; 837 this.key = key;
...@@ -825,9 +843,14 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -825,9 +843,14 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
825 } 843 }
826 844
827 void addLoad(Load load) { 845 void addLoad(Load load) {
846 + addLoad(load, 0);
847 + }
848 +
849 + void addLoad(Load load, long threshold) {
828 if (load != null) { 850 if (load != null) {
829 - this.hasTraffic = hasTraffic || load.rate() > 0; 851 + this.hasTraffic = hasTraffic || load.rate() > threshold;
830 this.bytes += load.latest(); 852 this.bytes += load.latest();
853 + this.rate = load.rate();
831 } 854 }
832 } 855 }
833 856
......
...@@ -67,7 +67,8 @@ ...@@ -67,7 +67,8 @@
67 rightArrow: [tts.showNextIntentAction, 'Show next related intent'], 67 rightArrow: [tts.showNextIntentAction, 'Show next related intent'],
68 leftArrow: [tts.showPrevIntentAction, 'Show previous related intent'], 68 leftArrow: [tts.showPrevIntentAction, 'Show previous related intent'],
69 W: [tts.showSelectedIntentTrafficAction, 'Monitor traffic of selected intent'], 69 W: [tts.showSelectedIntentTrafficAction, 'Monitor traffic of selected intent'],
70 - A: [tts.showAllTrafficAction, 'Monitor all traffic'], 70 + A: [tts.showAllFlowTrafficAction, 'Monitor all traffic using flow stats'],
71 + Q: [tts.showAllPortTrafficAction, 'Monitor all traffic using port stats'],
71 F: [tts.showDeviceLinkFlowsAction, 'Show device link flows'], 72 F: [tts.showDeviceLinkFlowsAction, 'Show device link flows'],
72 73
73 E: [equalizeMasters, 'Equalize mastership roles'], 74 E: [equalizeMasters, 'Equalize mastership roles'],
......
...@@ -150,10 +150,17 @@ ...@@ -150,10 +150,17 @@
150 } 150 }
151 151
152 // keystroke-A (see topo.js) 152 // keystroke-A (see topo.js)
153 - function showAllTrafficAction() { 153 + function showAllFlowTrafficAction() {
154 hoverMode = hoverModeAll; 154 hoverMode = hoverModeAll;
155 - wss.sendEvent('requestAllTraffic'); 155 + wss.sendEvent('requestAllFlowTraffic');
156 - flash.flash('All Traffic'); 156 + flash.flash('All Flow Traffic');
157 + }
158 +
159 + // keystroke-A (see topo.js)
160 + function showAllPortTrafficAction() {
161 + hoverMode = hoverModeAll;
162 + wss.sendEvent('requestAllPortTraffic');
163 + flash.flash('All Port Traffic');
157 } 164 }
158 165
159 // === ----------------------------- 166 // === -----------------------------
...@@ -228,7 +235,8 @@ ...@@ -228,7 +235,8 @@
228 showNextIntentAction: showNextIntentAction, 235 showNextIntentAction: showNextIntentAction,
229 showPrevIntentAction: showPrevIntentAction, 236 showPrevIntentAction: showPrevIntentAction,
230 showSelectedIntentTrafficAction: showSelectedIntentTrafficAction, 237 showSelectedIntentTrafficAction: showSelectedIntentTrafficAction,
231 - showAllTrafficAction: showAllTrafficAction 238 + showAllFlowTrafficAction: showAllFlowTrafficAction,
239 + showAllPortTrafficAction: showAllPortTrafficAction
232 }; 240 };
233 }]); 241 }]);
234 }()); 242 }());
......
...@@ -48,6 +48,11 @@ ...@@ -48,6 +48,11 @@
48 48
49 <dependency> 49 <dependency>
50 <groupId>org.onosproject</groupId> 50 <groupId>org.onosproject</groupId>
51 + <artifactId>onos-incubator-api</artifactId>
52 + </dependency>
53 +
54 + <dependency>
55 + <groupId>org.onosproject</groupId>
51 <artifactId>onlab-osgi</artifactId> 56 <artifactId>onlab-osgi</artifactId>
52 <version>${project.version}</version> 57 <version>${project.version}</version>
53 </dependency> 58 </dependency>
......