blob: 166a83a6725616e52c5979e831bc2e3ab9de02d8 [file] [log] [blame]
Simon Hunt4fc86852015-08-20 17:57:52 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Simon Hunt4fc86852015-08-20 17:57:52 -07003 *
Simon Hunted804d52016-03-30 09:51:40 -07004 * 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
Simon Hunt4fc86852015-08-20 17:57:52 -07007 *
Simon Hunted804d52016-03-30 09:51:40 -07008 * http://www.apache.org/licenses/LICENSE-2.0
Simon Hunt4fc86852015-08-20 17:57:52 -07009 *
Simon Hunted804d52016-03-30 09:51:40 -070010 * 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.
Simon Hunt4fc86852015-08-20 17:57:52 -070015 */
16
Simon Hunted804d52016-03-30 09:51:40 -070017package org.onosproject.ui.impl.topo.util;
Simon Hunt4fc86852015-08-20 17:57:52 -070018
19import org.onosproject.net.Link;
20import org.onosproject.net.LinkKey;
21import org.onosproject.net.statistic.Load;
Simon Hunt191c84a2015-08-21 08:24:48 -070022import org.onosproject.ui.topo.BiLink;
Simon Hunt4fc86852015-08-20 17:57:52 -070023import org.onosproject.ui.topo.LinkHighlight;
24import org.onosproject.ui.topo.LinkHighlight.Flavor;
Andrea Campanellaaf934682017-03-05 11:06:40 +010025import org.onosproject.ui.topo.Mod;
Simon Hunt21281fd2017-03-30 22:28:28 -070026import org.onosproject.ui.topo.TopoUtils.Magnitude;
27import org.onosproject.ui.topo.TopoUtils.ValueLabel;
Simon Hunt4fc86852015-08-20 17:57:52 -070028
Andrea Campanellaaf934682017-03-05 11:06:40 +010029import java.util.HashSet;
30import java.util.Set;
31
Simon Hunt21281fd2017-03-30 22:28:28 -070032import static org.onosproject.ui.topo.LinkHighlight.Flavor.NO_HIGHLIGHT;
33import static org.onosproject.ui.topo.LinkHighlight.Flavor.PRIMARY_HIGHLIGHT;
34import static org.onosproject.ui.topo.LinkHighlight.Flavor.SECONDARY_HIGHLIGHT;
35import static org.onosproject.ui.topo.TopoUtils.formatBytes;
36import static org.onosproject.ui.topo.TopoUtils.formatClippedBitRate;
37import static org.onosproject.ui.topo.TopoUtils.formatFlows;
38import static org.onosproject.ui.topo.TopoUtils.formatPacketRate;
Simon Hunt4fc86852015-08-20 17:57:52 -070039
40/**
41 * Representation of a link and its inverse, and associated traffic data.
42 * This class understands how to generate the appropriate
43 * {@link LinkHighlight}s for showing traffic data on the topology view.
44 */
45public class TrafficLink extends BiLink {
Simon Hunt21281fd2017-03-30 22:28:28 -070046 private static final Mod PORT_TRAFFIC_GREEN = new Mod("port-traffic-green");
47 private static final Mod PORT_TRAFFIC_YELLOW = new Mod("port-traffic-yellow");
48 private static final Mod PORT_TRAFFIC_ORANGE = new Mod("port-traffic-orange");
49 private static final Mod PORT_TRAFFIC_RED = new Mod("port-traffic-red");
Simon Hunt4fc86852015-08-20 17:57:52 -070050
51 private static final String EMPTY = "";
Simon Hunt4fc86852015-08-20 17:57:52 -070052
53 private long bytes = 0;
54 private long rate = 0;
55 private long flows = 0;
56 private Flavor taggedFlavor = NO_HIGHLIGHT;
57 private boolean hasTraffic = false;
58 private boolean isOptical = false;
59 private boolean antMarch = false;
Andrea Campanellaaf934682017-03-05 11:06:40 +010060 private Set<Mod> mods = new HashSet<>();
Simon Hunt4fc86852015-08-20 17:57:52 -070061
62 /**
63 * Constructs a traffic link for the given key and initial link.
64 *
65 * @param key canonical key for this traffic link
66 * @param link first link
67 */
68 public TrafficLink(LinkKey key, Link link) {
69 super(key, link);
70 }
71
72 /**
73 * Sets the optical flag to the given value.
74 *
75 * @param b true if an optical link
76 * @return self, for chaining
77 */
78 public TrafficLink optical(boolean b) {
79 isOptical = b;
80 return this;
81 }
82
83 /**
84 * Sets the ant march flag to the given value.
85 *
86 * @param b true if marching ants required
87 * @return self, for chaining
88 */
89 public TrafficLink antMarch(boolean b) {
90 antMarch = b;
91 return this;
92 }
93
94 /**
95 * Tags this traffic link with the flavor to be used in visual rendering.
96 *
97 * @param flavor the flavor to tag
98 * @return self, for chaining
99 */
100 public TrafficLink tagFlavor(Flavor flavor) {
Simon Hunt21281fd2017-03-30 22:28:28 -0700101 taggedFlavor = flavor;
Simon Hunt4fc86852015-08-20 17:57:52 -0700102 return this;
103 }
104
105 /**
Andrea Campanellaaf934682017-03-05 11:06:40 +0100106 * Tags this traffic link with the mods to be used in visual rendering.
107 *
108 * @param mods the mods to tag on this link
109 * @return self, for chaining
110 */
111 public TrafficLink tagMods(Set<Mod> mods) {
112 if (mods != null) {
113 this.mods.addAll(mods);
114 }
115 return this;
116 }
117
118 /**
Simon Hunt4fc86852015-08-20 17:57:52 -0700119 * Adds load statistics, marks the traffic link as having traffic.
120 *
121 * @param load load to add
122 */
123 public void addLoad(Load load) {
124 addLoad(load, 0);
125 }
126
127 /**
128 * Adds load statistics, marks the traffic link as having traffic, if the
129 * load {@link Load#rate rate} is greater than the given threshold
130 * (expressed in bytes per second).
131 *
Andrea Campanellaaf934682017-03-05 11:06:40 +0100132 * @param load load to add
Simon Hunt4fc86852015-08-20 17:57:52 -0700133 * @param threshold threshold to register traffic
134 */
135 public void addLoad(Load load, double threshold) {
136 if (load != null) {
137 this.hasTraffic = hasTraffic || load.rate() > threshold;
138 this.bytes += load.latest();
139 this.rate += load.rate();
140 }
141 }
142
143 /**
144 * Adds the given count of flows to this traffic link.
145 *
146 * @param count count of flows
147 */
148 public void addFlows(int count) {
149 this.flows += count;
150 }
151
152 @Override
153 public LinkHighlight highlight(Enum<?> type) {
154 StatsType statsType = (StatsType) type;
155 switch (statsType) {
156 case FLOW_COUNT:
Simon Hunt21281fd2017-03-30 22:28:28 -0700157 return highlightForFlowCount();
Simon Hunt4fc86852015-08-20 17:57:52 -0700158
159 case FLOW_STATS:
160 case PORT_STATS:
Simon Hunt21281fd2017-03-30 22:28:28 -0700161 case PORT_PACKET_STATS:
Simon Hunt4fc86852015-08-20 17:57:52 -0700162 return highlightForStats(statsType);
163
164 case TAGGED:
Simon Hunt21281fd2017-03-30 22:28:28 -0700165 return highlightForTagging();
Simon Hunt4fc86852015-08-20 17:57:52 -0700166
167 default:
168 throw new IllegalStateException("unexpected case: " + statsType);
169 }
170 }
171
172 private LinkHighlight highlightForStats(StatsType type) {
Simon Hunt21281fd2017-03-30 22:28:28 -0700173 ValueLabel vl = null;
174 Mod m = null;
175
176 // based on the type of stats, need to determine the label and "color"...
177 switch (type) {
178 case FLOW_STATS:
179 vl = formatBytes(bytes);
180 // default to "secondary highlighting" of link
181 break;
182
183 case PORT_STATS:
184 vl = formatClippedBitRate(rate);
185
186 // set color based on bits per second...
187 if (vl.magnitude() == Magnitude.ONE ||
188 vl.magnitude() == Magnitude.KILO) {
189 m = PORT_TRAFFIC_GREEN;
190
191 } else if (vl.magnitude() == Magnitude.MEGA) {
192 m = PORT_TRAFFIC_YELLOW;
193
194 } else if (vl.magnitude() == Magnitude.GIGA) {
195 m = vl.clipped() ? PORT_TRAFFIC_RED : PORT_TRAFFIC_ORANGE;
196 }
197 break;
198
199 case PORT_PACKET_STATS:
200 vl = formatPacketRate(rate);
201
Thomas Vachuska605134d2017-03-31 11:15:39 -0700202 // FIXME: Provisional color threshold parameters for packets
203 // set color based on bits per second...
204 if (rate < 10) {
205 m = PORT_TRAFFIC_GREEN;
206
207 } else if (rate < 1000) {
208 m = PORT_TRAFFIC_YELLOW;
209
210 } else if (rate < 100000) {
211 m = PORT_TRAFFIC_ORANGE;
212 } else {
213 m = PORT_TRAFFIC_RED;
214 }
Simon Hunt21281fd2017-03-30 22:28:28 -0700215 break;
216
217 default:
218 break;
Andrea Campanellaaf934682017-03-05 11:06:40 +0100219 }
Simon Hunt21281fd2017-03-30 22:28:28 -0700220
221 LinkHighlight hlite = new LinkHighlight(linkId(), SECONDARY_HIGHLIGHT);
222 if (vl != null) {
223 hlite.setLabel(vl.toString());
224 }
225 if (m != null) {
226 hlite.addMod(m);
227 }
228
229 return addCustomMods(hlite);
Simon Hunt4fc86852015-08-20 17:57:52 -0700230 }
231
Simon Hunt21281fd2017-03-30 22:28:28 -0700232 private LinkHighlight highlightForFlowCount() {
Simon Hunt4fc86852015-08-20 17:57:52 -0700233 Flavor flavor = flows > 0 ? PRIMARY_HIGHLIGHT : SECONDARY_HIGHLIGHT;
Andrea Campanellaaf934682017-03-05 11:06:40 +0100234 LinkHighlight hlite = new LinkHighlight(linkId(), flavor)
Simon Hunt21281fd2017-03-30 22:28:28 -0700235 .setLabel(formatFlows(flows));
Andrea Campanellaaf934682017-03-05 11:06:40 +0100236
Simon Hunt21281fd2017-03-30 22:28:28 -0700237 return addCustomMods(hlite);
Simon Hunt4fc86852015-08-20 17:57:52 -0700238 }
239
Simon Hunt21281fd2017-03-30 22:28:28 -0700240 private LinkHighlight highlightForTagging() {
Simon Hunt4fc86852015-08-20 17:57:52 -0700241 LinkHighlight hlite = new LinkHighlight(linkId(), taggedFlavor)
Simon Hunt21281fd2017-03-30 22:28:28 -0700242 .setLabel(hasTraffic ? formatBytes(bytes).toString() : EMPTY);
243
Simon Hunt4fc86852015-08-20 17:57:52 -0700244 if (isOptical) {
245 hlite.addMod(LinkHighlight.MOD_OPTICAL);
246 }
247 if (antMarch) {
248 hlite.addMod(LinkHighlight.MOD_ANIMATED);
249 }
Simon Hunt21281fd2017-03-30 22:28:28 -0700250 return addCustomMods(hlite);
251 }
252
253 private LinkHighlight addCustomMods(LinkHighlight hlite) {
Andrea Campanellaaf934682017-03-05 11:06:40 +0100254 if (!mods.isEmpty()) {
255 mods.forEach(hlite::addMod);
256 }
Simon Hunt4fc86852015-08-20 17:57:52 -0700257 return hlite;
258 }
259
Simon Hunt4fc86852015-08-20 17:57:52 -0700260 /**
261 * Returns true if this link has been deemed to have enough traffic
262 * to register on the topology view in the web UI.
263 *
264 * @return true if this link has displayable traffic
265 */
266 public boolean hasTraffic() {
267 return hasTraffic;
268 }
269
270 /**
271 * Designates type of traffic statistics to report on a highlighted link.
272 */
273 public enum StatsType {
274 /**
275 * Number of flows.
276 */
277 FLOW_COUNT,
278
279 /**
280 * Number of bytes.
281 */
282 FLOW_STATS,
283
284 /**
285 * Number of bits per second.
286 */
287 PORT_STATS,
288
289 /**
Thomas Vachuska0932ac52017-03-30 13:28:49 -0700290 * Number of packets per second.
291 */
292 PORT_PACKET_STATS,
293
294 /**
Simon Hunt4fc86852015-08-20 17:57:52 -0700295 * Custom tagged information.
296 */
297 TAGGED
298 }
299}