Thomas Vachuska
Committed by Gerrit Code Review

Adding multi-instance support for flow stats.

Change-Id: I428c5a7cb58f4f9773a125fc94fb368ed846cb0d
...@@ -61,6 +61,22 @@ public final class DefaultPortStatistics implements PortStatistics { ...@@ -61,6 +61,22 @@ public final class DefaultPortStatistics implements PortStatistics {
61 this.durationNano = durationNano; 61 this.durationNano = durationNano;
62 } 62 }
63 63
64 + // Constructor for serializer
65 + private DefaultPortStatistics() {
66 + this.deviceId = null;
67 + this.port = 0;
68 + this.packetsReceived = 0;
69 + this.packetsSent = 0;
70 + this.bytesReceived = 0;
71 + this.bytesSent = 0;
72 + this.packetsRxDropped = 0;
73 + this.packetsTxDropped = 0;
74 + this.packetsRxErrors = 0;
75 + this.packetsTxErrors = 0;
76 + this.durationSec = 0;
77 + this.durationNano = 0;
78 + }
79 +
64 /** 80 /**
65 * Creates a builder for DefaultPortStatistics object. 81 * Creates a builder for DefaultPortStatistics object.
66 * 82 *
......
...@@ -50,6 +50,7 @@ import org.onosproject.net.OduCltPort; ...@@ -50,6 +50,7 @@ import org.onosproject.net.OduCltPort;
50 import org.onosproject.net.OmsPort; 50 import org.onosproject.net.OmsPort;
51 import org.onosproject.net.Port; 51 import org.onosproject.net.Port;
52 import org.onosproject.net.PortNumber; 52 import org.onosproject.net.PortNumber;
53 +import org.onosproject.net.device.DefaultPortStatistics;
53 import org.onosproject.net.device.DeviceClockService; 54 import org.onosproject.net.device.DeviceClockService;
54 import org.onosproject.net.device.DeviceDescription; 55 import org.onosproject.net.device.DeviceDescription;
55 import org.onosproject.net.device.DeviceEvent; 56 import org.onosproject.net.device.DeviceEvent;
...@@ -68,8 +69,16 @@ import org.onosproject.store.cluster.messaging.ClusterMessage; ...@@ -68,8 +69,16 @@ import org.onosproject.store.cluster.messaging.ClusterMessage;
68 import org.onosproject.store.cluster.messaging.ClusterMessageHandler; 69 import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
69 import org.onosproject.store.cluster.messaging.MessageSubject; 70 import org.onosproject.store.cluster.messaging.MessageSubject;
70 import org.onosproject.store.impl.Timestamped; 71 import org.onosproject.store.impl.Timestamped;
72 +import org.onosproject.store.serializers.KryoNamespaces;
71 import org.onosproject.store.serializers.KryoSerializer; 73 import org.onosproject.store.serializers.KryoSerializer;
72 import org.onosproject.store.serializers.custom.DistributedStoreSerializers; 74 import org.onosproject.store.serializers.custom.DistributedStoreSerializers;
75 +import org.onosproject.store.service.EventuallyConsistentMap;
76 +import org.onosproject.store.service.EventuallyConsistentMapEvent;
77 +import org.onosproject.store.service.EventuallyConsistentMapListener;
78 +import org.onosproject.store.service.MultiValuedTimestamp;
79 +import org.onosproject.store.service.StorageService;
80 +import org.onosproject.store.service.WallClockTimestamp;
81 +import org.onosproject.store.service.WallclockClockManager;
73 import org.slf4j.Logger; 82 import org.slf4j.Logger;
74 83
75 import java.io.IOException; 84 import java.io.IOException;
...@@ -102,6 +111,7 @@ import static org.onosproject.net.DefaultAnnotations.merge; ...@@ -102,6 +111,7 @@ import static org.onosproject.net.DefaultAnnotations.merge;
102 import static org.onosproject.net.device.DeviceEvent.Type.*; 111 import static org.onosproject.net.device.DeviceEvent.Type.*;
103 import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED; 112 import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED;
104 import static org.onosproject.store.device.impl.GossipDeviceStoreMessageSubjects.*; 113 import static org.onosproject.store.device.impl.GossipDeviceStoreMessageSubjects.*;
114 +import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT;
105 import static org.slf4j.LoggerFactory.getLogger; 115 import static org.slf4j.LoggerFactory.getLogger;
106 116
107 /** 117 /**
...@@ -128,8 +138,10 @@ public class GossipDeviceStore ...@@ -128,8 +138,10 @@ public class GossipDeviceStore
128 // cache of Device and Ports generated by compositing descriptions from providers 138 // cache of Device and Ports generated by compositing descriptions from providers
129 private final ConcurrentMap<DeviceId, Device> devices = Maps.newConcurrentMap(); 139 private final ConcurrentMap<DeviceId, Device> devices = Maps.newConcurrentMap();
130 private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>> devicePorts = Maps.newConcurrentMap(); 140 private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>> devicePorts = Maps.newConcurrentMap();
131 - private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, PortStatistics>> 141 +
132 - devicePortStats = Maps.newConcurrentMap(); 142 + private EventuallyConsistentMap<DeviceId, Map<PortNumber, PortStatistics>> devicePortStats;
143 + private final EventuallyConsistentMapListener<DeviceId, Map<PortNumber, PortStatistics>>
144 + portStatsListener = new InternalPortStatsListener();
133 145
134 // to be updated under Device lock 146 // to be updated under Device lock
135 private final Map<DeviceId, Timestamp> offline = Maps.newHashMap(); 147 private final Map<DeviceId, Timestamp> offline = Maps.newHashMap();
...@@ -142,6 +154,9 @@ public class GossipDeviceStore ...@@ -142,6 +154,9 @@ public class GossipDeviceStore
142 protected DeviceClockService deviceClockService; 154 protected DeviceClockService deviceClockService;
143 155
144 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 156 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
157 + protected StorageService storageService;
158 +
159 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
145 protected ClusterCommunicationService clusterCommunicator; 160 protected ClusterCommunicationService clusterCommunicator;
146 161
147 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 162 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
...@@ -182,10 +197,8 @@ public class GossipDeviceStore ...@@ -182,10 +197,8 @@ public class GossipDeviceStore
182 private long initialDelaySec = 5; 197 private long initialDelaySec = 5;
183 private long periodSec = 5; 198 private long periodSec = 5;
184 199
185 -
186 @Activate 200 @Activate
187 public void activate() { 201 public void activate() {
188 -
189 executor = Executors.newCachedThreadPool(groupedThreads("onos/device", "fg-%d")); 202 executor = Executors.newCachedThreadPool(groupedThreads("onos/device", "fg-%d"));
190 203
191 backgroundExecutor = 204 backgroundExecutor =
...@@ -219,6 +232,22 @@ public class GossipDeviceStore ...@@ -219,6 +232,22 @@ public class GossipDeviceStore
219 backgroundExecutor.scheduleAtFixedRate(new SendAdvertisementTask(), 232 backgroundExecutor.scheduleAtFixedRate(new SendAdvertisementTask(),
220 initialDelaySec, periodSec, TimeUnit.SECONDS); 233 initialDelaySec, periodSec, TimeUnit.SECONDS);
221 234
235 + // Create a distributed map for port stats.
236 + KryoNamespace.Builder deviceDataSerializer = KryoNamespace.newBuilder()
237 + .register(KryoNamespaces.API)
238 + .register(DefaultPortStatistics.class)
239 + .register(DeviceId.class)
240 + .register(MultiValuedTimestamp.class)
241 + .register(WallClockTimestamp.class);
242 +
243 + devicePortStats = storageService.<DeviceId, Map<PortNumber, PortStatistics>>eventuallyConsistentMapBuilder()
244 + .withName("port-stats")
245 + .withSerializer(deviceDataSerializer)
246 + .withAntiEntropyPeriod(5, TimeUnit.SECONDS)
247 + .withClockService(new WallclockClockManager<>())
248 + .withTombstonesDisabled()
249 + .build();
250 + devicePortStats.addListener(portStatsListener);
222 log.info("Started"); 251 log.info("Started");
223 } 252 }
224 253
...@@ -702,7 +731,6 @@ public class GossipDeviceStore ...@@ -702,7 +731,6 @@ public class GossipDeviceStore
702 private DeviceDescriptions getOrCreateProviderDeviceDescriptions( 731 private DeviceDescriptions getOrCreateProviderDeviceDescriptions(
703 Map<ProviderId, DeviceDescriptions> device, 732 Map<ProviderId, DeviceDescriptions> device,
704 ProviderId providerId, Timestamped<DeviceDescription> deltaDesc) { 733 ProviderId providerId, Timestamped<DeviceDescription> deltaDesc) {
705 -
706 synchronized (device) { 734 synchronized (device) {
707 DeviceDescriptions r = device.get(providerId); 735 DeviceDescriptions r = device.get(providerId);
708 if (r == null) { 736 if (r == null) {
...@@ -747,7 +775,6 @@ public class GossipDeviceStore ...@@ -747,7 +775,6 @@ public class GossipDeviceStore
747 775
748 private DeviceEvent updatePortStatusInternal(ProviderId providerId, DeviceId deviceId, 776 private DeviceEvent updatePortStatusInternal(ProviderId providerId, DeviceId deviceId,
749 Timestamped<PortDescription> deltaDesc) { 777 Timestamped<PortDescription> deltaDesc) {
750 -
751 Device device = devices.get(deviceId); 778 Device device = devices.get(deviceId);
752 checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); 779 checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
753 780
...@@ -805,24 +832,21 @@ public class GossipDeviceStore ...@@ -805,24 +832,21 @@ public class GossipDeviceStore
805 @Override 832 @Override
806 public DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId, 833 public DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId,
807 Collection<PortStatistics> portStats) { 834 Collection<PortStatistics> portStats) {
808 - 835 + Map<PortNumber, PortStatistics> statsMap = devicePortStats.get(deviceId);
809 - ConcurrentMap<PortNumber, PortStatistics> statsMap = devicePortStats.get(deviceId);
810 if (statsMap == null) { 836 if (statsMap == null) {
811 - statsMap = Maps.newConcurrentMap(); 837 + statsMap = Maps.newHashMap();
812 - devicePortStats.put(deviceId, statsMap);
813 } 838 }
814 839
815 - for (PortStatistics stat: portStats) { 840 + for (PortStatistics stat : portStats) {
816 PortNumber portNumber = PortNumber.portNumber(stat.port()); 841 PortNumber portNumber = PortNumber.portNumber(stat.port());
817 statsMap.put(portNumber, stat); 842 statsMap.put(portNumber, stat);
818 } 843 }
819 - 844 + devicePortStats.put(deviceId, statsMap);
820 - return new DeviceEvent(PORT_STATS_UPDATED, devices.get(deviceId), null); 845 + return null; // new DeviceEvent(PORT_STATS_UPDATED, devices.get(deviceId), null);
821 } 846 }
822 847
823 @Override 848 @Override
824 public List<PortStatistics> getPortStatistics(DeviceId deviceId) { 849 public List<PortStatistics> getPortStatistics(DeviceId deviceId) {
825 -
826 Map<PortNumber, PortStatistics> portStats = devicePortStats.get(deviceId); 850 Map<PortNumber, PortStatistics> portStats = devicePortStats.get(deviceId);
827 if (portStats == null) { 851 if (portStats == null) {
828 return Collections.emptyList(); 852 return Collections.emptyList();
...@@ -978,7 +1002,7 @@ public class GossipDeviceStore ...@@ -978,7 +1002,7 @@ public class GossipDeviceStore
978 annotations = merge(annotations, e.getValue().getDeviceDesc().value().annotations()); 1002 annotations = merge(annotations, e.getValue().getDeviceDesc().value().annotations());
979 } 1003 }
980 1004
981 - return new DefaultDevice(primary, deviceId , type, manufacturer, 1005 + return new DefaultDevice(primary, deviceId, type, manufacturer,
982 hwVersion, swVersion, serialNumber, 1006 hwVersion, swVersion, serialNumber,
983 chassisId, annotations); 1007 chassisId, annotations);
984 } 1008 }
...@@ -1192,7 +1216,7 @@ public class GossipDeviceStore ...@@ -1192,7 +1216,7 @@ public class GossipDeviceStore
1192 1216
1193 /** 1217 /**
1194 * Responds to anti-entropy advertisement message. 1218 * Responds to anti-entropy advertisement message.
1195 - * <P> 1219 + * <p/>
1196 * Notify sender about out-dated information using regular replication message. 1220 * Notify sender about out-dated information using regular replication message.
1197 * Send back advertisement to sender if not in sync. 1221 * Send back advertisement to sender if not in sync.
1198 * 1222 *
...@@ -1386,7 +1410,6 @@ public class GossipDeviceStore ...@@ -1386,7 +1410,6 @@ public class GossipDeviceStore
1386 implements ClusterMessageHandler { 1410 implements ClusterMessageHandler {
1387 @Override 1411 @Override
1388 public void handle(ClusterMessage message) { 1412 public void handle(ClusterMessage message) {
1389 -
1390 log.debug("Received device update event from peer: {}", message.sender()); 1413 log.debug("Received device update event from peer: {}", message.sender());
1391 InternalDeviceEvent event = SERIALIZER.decode(message.payload()); 1414 InternalDeviceEvent event = SERIALIZER.decode(message.payload());
1392 1415
...@@ -1406,7 +1429,6 @@ public class GossipDeviceStore ...@@ -1406,7 +1429,6 @@ public class GossipDeviceStore
1406 implements ClusterMessageHandler { 1429 implements ClusterMessageHandler {
1407 @Override 1430 @Override
1408 public void handle(ClusterMessage message) { 1431 public void handle(ClusterMessage message) {
1409 -
1410 log.debug("Received device offline event from peer: {}", message.sender()); 1432 log.debug("Received device offline event from peer: {}", message.sender());
1411 InternalDeviceOfflineEvent event = SERIALIZER.decode(message.payload()); 1433 InternalDeviceOfflineEvent event = SERIALIZER.decode(message.payload());
1412 1434
...@@ -1440,7 +1462,6 @@ public class GossipDeviceStore ...@@ -1440,7 +1462,6 @@ public class GossipDeviceStore
1440 implements ClusterMessageHandler { 1462 implements ClusterMessageHandler {
1441 @Override 1463 @Override
1442 public void handle(ClusterMessage message) { 1464 public void handle(ClusterMessage message) {
1443 -
1444 log.debug("Received device removed event from peer: {}", message.sender()); 1465 log.debug("Received device removed event from peer: {}", message.sender());
1445 InternalDeviceRemovedEvent event = SERIALIZER.decode(message.payload()); 1466 InternalDeviceRemovedEvent event = SERIALIZER.decode(message.payload());
1446 1467
...@@ -1509,7 +1530,6 @@ public class GossipDeviceStore ...@@ -1509,7 +1530,6 @@ public class GossipDeviceStore
1509 1530
1510 private final class InternalDeviceAdvertisementListener 1531 private final class InternalDeviceAdvertisementListener
1511 implements ClusterMessageHandler { 1532 implements ClusterMessageHandler {
1512 -
1513 @Override 1533 @Override
1514 public void handle(ClusterMessage message) { 1534 public void handle(ClusterMessage message) {
1515 log.trace("Received Device Anti-Entropy advertisement from peer: {}", message.sender()); 1535 log.trace("Received Device Anti-Entropy advertisement from peer: {}", message.sender());
...@@ -1526,7 +1546,6 @@ public class GossipDeviceStore ...@@ -1526,7 +1546,6 @@ public class GossipDeviceStore
1526 implements ClusterMessageHandler { 1546 implements ClusterMessageHandler {
1527 @Override 1547 @Override
1528 public void handle(ClusterMessage message) { 1548 public void handle(ClusterMessage message) {
1529 -
1530 log.debug("Received injected device event from peer: {}", message.sender()); 1549 log.debug("Received injected device event from peer: {}", message.sender());
1531 DeviceInjectedEvent event = SERIALIZER.decode(message.payload()); 1550 DeviceInjectedEvent event = SERIALIZER.decode(message.payload());
1532 1551
...@@ -1551,7 +1570,6 @@ public class GossipDeviceStore ...@@ -1551,7 +1570,6 @@ public class GossipDeviceStore
1551 implements ClusterMessageHandler { 1570 implements ClusterMessageHandler {
1552 @Override 1571 @Override
1553 public void handle(ClusterMessage message) { 1572 public void handle(ClusterMessage message) {
1554 -
1555 log.debug("Received injected port event from peer: {}", message.sender()); 1573 log.debug("Received injected port event from peer: {}", message.sender());
1556 PortInjectedEvent event = SERIALIZER.decode(message.payload()); 1574 PortInjectedEvent event = SERIALIZER.decode(message.payload());
1557 1575
...@@ -1571,4 +1589,17 @@ public class GossipDeviceStore ...@@ -1571,4 +1589,17 @@ public class GossipDeviceStore
1571 } 1589 }
1572 } 1590 }
1573 } 1591 }
1592 +
1593 + private class InternalPortStatsListener
1594 + implements EventuallyConsistentMapListener<DeviceId, Map<PortNumber, PortStatistics>> {
1595 + @Override
1596 + public void event(EventuallyConsistentMapEvent<DeviceId, Map<PortNumber, PortStatistics>> event) {
1597 + if (event.type() == PUT) {
1598 + Device device = devices.get(event.key());
1599 + if (device != null) {
1600 + delegate.notify(new DeviceEvent(PORT_STATS_UPDATED, device));
1601 + }
1602 + }
1603 + }
1604 + }
1574 } 1605 }
......
...@@ -55,6 +55,7 @@ import org.onosproject.store.cluster.messaging.ClusterCommunicationService; ...@@ -55,6 +55,7 @@ import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
55 import org.onosproject.store.cluster.messaging.ClusterMessage; 55 import org.onosproject.store.cluster.messaging.ClusterMessage;
56 import org.onosproject.store.cluster.messaging.ClusterMessageHandler; 56 import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
57 import org.onosproject.store.cluster.messaging.MessageSubject; 57 import org.onosproject.store.cluster.messaging.MessageSubject;
58 +import org.onosproject.store.consistent.impl.DatabaseManager;
58 59
59 import java.io.IOException; 60 import java.io.IOException;
60 import java.util.Arrays; 61 import java.util.Arrays;
...@@ -165,6 +166,10 @@ public class GossipDeviceStoreTest { ...@@ -165,6 +166,10 @@ public class GossipDeviceStoreTest {
165 testGossipDeviceStore = new TestGossipDeviceStore(deviceClockService, clusterService, clusterCommunicator); 166 testGossipDeviceStore = new TestGossipDeviceStore(deviceClockService, clusterService, clusterCommunicator);
166 testGossipDeviceStore.mastershipService = new TestMastershipService(); 167 testGossipDeviceStore.mastershipService = new TestMastershipService();
167 168
169 + TestDatabaseManager testDatabaseManager = new TestDatabaseManager();
170 + testDatabaseManager.init(clusterService, clusterCommunicator);
171 + testGossipDeviceStore.storageService = testDatabaseManager;
172 +
168 gossipDeviceStore = testGossipDeviceStore; 173 gossipDeviceStore = testGossipDeviceStore;
169 gossipDeviceStore.activate(); 174 gossipDeviceStore.activate();
170 deviceStore = gossipDeviceStore; 175 deviceStore = gossipDeviceStore;
...@@ -885,4 +890,12 @@ public class GossipDeviceStoreTest { ...@@ -885,4 +890,12 @@ public class GossipDeviceStoreTest {
885 nodeStates.put(NID2, ACTIVE); 890 nodeStates.put(NID2, ACTIVE);
886 } 891 }
887 } 892 }
893 +
894 + private class TestDatabaseManager extends DatabaseManager {
895 + void init(ClusterService clusterService,
896 + ClusterCommunicationService clusterCommunicator) {
897 + this.clusterService = clusterService;
898 + this.clusterCommunicator = clusterCommunicator;
899 + }
900 + }
888 } 901 }
......
...@@ -71,9 +71,11 @@ import org.onosproject.net.Port; ...@@ -71,9 +71,11 @@ import org.onosproject.net.Port;
71 import org.onosproject.net.PortNumber; 71 import org.onosproject.net.PortNumber;
72 import org.onosproject.net.device.DefaultDeviceDescription; 72 import org.onosproject.net.device.DefaultDeviceDescription;
73 import org.onosproject.net.device.DefaultPortDescription; 73 import org.onosproject.net.device.DefaultPortDescription;
74 +import org.onosproject.net.device.DefaultPortStatistics;
74 import org.onosproject.net.device.OchPortDescription; 75 import org.onosproject.net.device.OchPortDescription;
75 import org.onosproject.net.device.OduCltPortDescription; 76 import org.onosproject.net.device.OduCltPortDescription;
76 import org.onosproject.net.device.OmsPortDescription; 77 import org.onosproject.net.device.OmsPortDescription;
78 +import org.onosproject.net.device.PortStatistics;
77 import org.onosproject.net.flow.CompletedBatchOperation; 79 import org.onosproject.net.flow.CompletedBatchOperation;
78 import org.onosproject.net.flow.DefaultFlowEntry; 80 import org.onosproject.net.flow.DefaultFlowEntry;
79 import org.onosproject.net.flow.DefaultFlowRule; 81 import org.onosproject.net.flow.DefaultFlowRule;
...@@ -380,7 +382,9 @@ public final class KryoNamespaces { ...@@ -380,7 +382,9 @@ public final class KryoNamespaces {
380 IntentOperation.class, 382 IntentOperation.class,
381 FlowRuleExtPayLoad.class, 383 FlowRuleExtPayLoad.class,
382 Frequency.class, 384 Frequency.class,
383 - DefaultAnnotations.class 385 + DefaultAnnotations.class,
386 + PortStatistics.class,
387 + DefaultPortStatistics.class
384 ) 388 )
385 .register(new DefaultApplicationIdSerializer(), DefaultApplicationId.class) 389 .register(new DefaultApplicationIdSerializer(), DefaultApplicationId.class)
386 .register(new URISerializer(), URI.class) 390 .register(new URISerializer(), URI.class)
......
...@@ -14,7 +14,7 @@ cut -c7- $aux | cut -d\ -f1 | sort > $aux.1 ...@@ -14,7 +14,7 @@ cut -c7- $aux | cut -d\ -f1 | sort > $aux.1
14 14
15 # Normalize the expected apps 15 # Normalize the expected apps
16 apps=${ONOS_APPS:-drivers,openflow} 16 apps=${ONOS_APPS:-drivers,openflow}
17 -(for app in ${apps/,/ }; do echo org.onosproject.$app; done) | sort > $aux.2 17 +(for app in ${apps//,/ }; do echo org.onosproject.$app; done) | sort > $aux.2
18 18
19 # Check for differences 19 # Check for differences
20 diff $aux.1 $aux.2 20 diff $aux.1 $aux.2
......
1 +# Madan's ProxMox ONOS instances 1,2,3 & ONOS mininet box
2 +
3 +export ONOS_NIC="10.128.4.*"
4 +export OC1="10.128.4.2"
5 +export OC2="10.128.4.3"
6 +export OC3="10.128.4.4"
7 +export OCN="10.128.4.5"
1 -# Office ProxMox ONOS instances 1,2,3 & ONOS mininet box 1 +# Tom's ProxMox ONOS instances 1,2,3 & ONOS mininet box
2 2
3 -export ONOS_NIC=10.128.11.* 3 +export ONOS_NIC="10.128.11.*"
4 export OC1="10.128.11.1" 4 export OC1="10.128.11.1"
5 export OC2="10.128.11.2" 5 export OC2="10.128.11.2"
6 export OC3="10.128.11.3" 6 export OC3="10.128.11.3"
......
...@@ -850,7 +850,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -850,7 +850,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
850 if (load != null) { 850 if (load != null) {
851 this.hasTraffic = hasTraffic || load.rate() > threshold; 851 this.hasTraffic = hasTraffic || load.rate() > threshold;
852 this.bytes += load.latest(); 852 this.bytes += load.latest();
853 - this.rate = load.rate(); 853 + this.rate += load.rate();
854 } 854 }
855 } 855 }
856 856
......