blob: 16d3db7f47bff73c6e6c5c0b3281255825af1923 [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 Hunt191c84a2015-08-21 08:24:48 -070026import org.onosproject.ui.topo.TopoUtils;
Simon Hunt4fc86852015-08-20 17:57:52 -070027
Andrea Campanellaaf934682017-03-05 11:06:40 +010028import java.util.HashSet;
29import java.util.Set;
30
31import static org.onosproject.ui.topo.LinkHighlight.Flavor.*;
Simon Hunt4fc86852015-08-20 17:57:52 -070032
33/**
34 * Representation of a link and its inverse, and associated traffic data.
35 * This class understands how to generate the appropriate
36 * {@link LinkHighlight}s for showing traffic data on the topology view.
37 */
38public class TrafficLink extends BiLink {
39
40 private static final String EMPTY = "";
41 private static final String QUE = "?";
42
43 private long bytes = 0;
44 private long rate = 0;
45 private long flows = 0;
46 private Flavor taggedFlavor = NO_HIGHLIGHT;
47 private boolean hasTraffic = false;
48 private boolean isOptical = false;
49 private boolean antMarch = false;
Andrea Campanellaaf934682017-03-05 11:06:40 +010050 private Set<Mod> mods = new HashSet<>();
Simon Hunt4fc86852015-08-20 17:57:52 -070051
52 /**
53 * Constructs a traffic link for the given key and initial link.
54 *
55 * @param key canonical key for this traffic link
56 * @param link first link
57 */
58 public TrafficLink(LinkKey key, Link link) {
59 super(key, link);
60 }
61
62 /**
63 * Sets the optical flag to the given value.
64 *
65 * @param b true if an optical link
66 * @return self, for chaining
67 */
68 public TrafficLink optical(boolean b) {
69 isOptical = b;
70 return this;
71 }
72
73 /**
74 * Sets the ant march flag to the given value.
75 *
76 * @param b true if marching ants required
77 * @return self, for chaining
78 */
79 public TrafficLink antMarch(boolean b) {
80 antMarch = b;
81 return this;
82 }
83
84 /**
85 * Tags this traffic link with the flavor to be used in visual rendering.
86 *
87 * @param flavor the flavor to tag
88 * @return self, for chaining
89 */
90 public TrafficLink tagFlavor(Flavor flavor) {
91 this.taggedFlavor = flavor;
92 return this;
93 }
94
95 /**
Andrea Campanellaaf934682017-03-05 11:06:40 +010096 * Tags this traffic link with the mods to be used in visual rendering.
97 *
98 * @param mods the mods to tag on this link
99 * @return self, for chaining
100 */
101 public TrafficLink tagMods(Set<Mod> mods) {
102 if (mods != null) {
103 this.mods.addAll(mods);
104 }
105 return this;
106 }
107
108 /**
Simon Hunt4fc86852015-08-20 17:57:52 -0700109 * Adds load statistics, marks the traffic link as having traffic.
110 *
111 * @param load load to add
112 */
113 public void addLoad(Load load) {
114 addLoad(load, 0);
115 }
116
117 /**
118 * Adds load statistics, marks the traffic link as having traffic, if the
119 * load {@link Load#rate rate} is greater than the given threshold
120 * (expressed in bytes per second).
121 *
Andrea Campanellaaf934682017-03-05 11:06:40 +0100122 * @param load load to add
Simon Hunt4fc86852015-08-20 17:57:52 -0700123 * @param threshold threshold to register traffic
124 */
125 public void addLoad(Load load, double threshold) {
126 if (load != null) {
127 this.hasTraffic = hasTraffic || load.rate() > threshold;
128 this.bytes += load.latest();
129 this.rate += load.rate();
130 }
131 }
132
133 /**
134 * Adds the given count of flows to this traffic link.
135 *
136 * @param count count of flows
137 */
138 public void addFlows(int count) {
139 this.flows += count;
140 }
141
142 @Override
143 public LinkHighlight highlight(Enum<?> type) {
144 StatsType statsType = (StatsType) type;
145 switch (statsType) {
146 case FLOW_COUNT:
147 return highlightForFlowCount(statsType);
148
149 case FLOW_STATS:
150 case PORT_STATS:
151 return highlightForStats(statsType);
152
153 case TAGGED:
154 return highlightForTagging(statsType);
155
156 default:
157 throw new IllegalStateException("unexpected case: " + statsType);
158 }
159 }
160
161 private LinkHighlight highlightForStats(StatsType type) {
Andrea Campanellaaf934682017-03-05 11:06:40 +0100162 LinkHighlight hlite = new LinkHighlight(linkId(), SECONDARY_HIGHLIGHT)
Simon Hunt4fc86852015-08-20 17:57:52 -0700163 .setLabel(generateLabel(type));
Andrea Campanellaaf934682017-03-05 11:06:40 +0100164 if (!mods.isEmpty()) {
165 mods.forEach(hlite::addMod);
166 }
167 return hlite;
Simon Hunt4fc86852015-08-20 17:57:52 -0700168 }
169
170 private LinkHighlight highlightForFlowCount(StatsType type) {
171 Flavor flavor = flows > 0 ? PRIMARY_HIGHLIGHT : SECONDARY_HIGHLIGHT;
Andrea Campanellaaf934682017-03-05 11:06:40 +0100172 LinkHighlight hlite = new LinkHighlight(linkId(), flavor)
Simon Hunt4fc86852015-08-20 17:57:52 -0700173 .setLabel(generateLabel(type));
Andrea Campanellaaf934682017-03-05 11:06:40 +0100174 if (!mods.isEmpty()) {
175 mods.forEach(hlite::addMod);
176 }
177 return hlite;
178
Simon Hunt4fc86852015-08-20 17:57:52 -0700179 }
180
181 private LinkHighlight highlightForTagging(StatsType type) {
182 LinkHighlight hlite = new LinkHighlight(linkId(), taggedFlavor)
183 .setLabel(generateLabel(type));
184 if (isOptical) {
185 hlite.addMod(LinkHighlight.MOD_OPTICAL);
186 }
187 if (antMarch) {
188 hlite.addMod(LinkHighlight.MOD_ANIMATED);
189 }
Andrea Campanellaaf934682017-03-05 11:06:40 +0100190 if (!mods.isEmpty()) {
191 mods.forEach(hlite::addMod);
192 }
Simon Hunt4fc86852015-08-20 17:57:52 -0700193 return hlite;
194 }
195
196 // Generates a string representation of the load, to be used as a label
197 private String generateLabel(StatsType type) {
198 switch (type) {
199 case FLOW_COUNT:
200 return TopoUtils.formatFlows(flows);
201
202 case FLOW_STATS:
203 return TopoUtils.formatBytes(bytes);
204
205 case PORT_STATS:
206 return TopoUtils.formatBitRate(rate);
207
208 case TAGGED:
209 return hasTraffic ? TopoUtils.formatBytes(bytes) : EMPTY;
210
211 default:
212 return QUE;
213 }
214 }
215
216 /**
217 * Returns true if this link has been deemed to have enough traffic
218 * to register on the topology view in the web UI.
219 *
220 * @return true if this link has displayable traffic
221 */
222 public boolean hasTraffic() {
223 return hasTraffic;
224 }
225
226 /**
227 * Designates type of traffic statistics to report on a highlighted link.
228 */
229 public enum StatsType {
230 /**
231 * Number of flows.
232 */
233 FLOW_COUNT,
234
235 /**
236 * Number of bytes.
237 */
238 FLOW_STATS,
239
240 /**
241 * Number of bits per second.
242 */
243 PORT_STATS,
244
245 /**
246 * Custom tagged information.
247 */
248 TAGGED
249 }
250}