blob: b585ffc24fcf70e59308470ac65e6aea8a919610 [file] [log] [blame]
Simon Hunta17fa672015-08-19 18:42:22 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Simon Hunta17fa672015-08-19 18:42:22 -07003 *
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 */
17
18package org.onosproject.ui.impl;
19
Simon Hunta17fa672015-08-19 18:42:22 -070020import org.onosproject.net.Device;
21import org.onosproject.net.DeviceId;
22import org.onosproject.net.Host;
23import org.onosproject.net.Link;
Simon Hunta17fa672015-08-19 18:42:22 -070024import org.onosproject.net.PortNumber;
25import org.onosproject.net.flow.FlowEntry;
26import org.onosproject.net.flow.TrafficTreatment;
27import org.onosproject.net.flow.instructions.Instruction;
28import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
Simon Hunted804d52016-03-30 09:51:40 -070029import org.onosproject.ui.impl.topo.util.ServicesBundle;
Simon Hunted804d52016-03-30 09:51:40 -070030import org.onosproject.ui.impl.topo.util.TrafficLink;
31import org.onosproject.ui.impl.topo.util.TrafficLink.StatsType;
32import org.onosproject.ui.impl.topo.util.TrafficLinkMap;
Simon Hunta17fa672015-08-19 18:42:22 -070033import org.onosproject.ui.topo.Highlights;
34import org.slf4j.Logger;
35import org.slf4j.LoggerFactory;
36
37import java.util.ArrayList;
Simon Hunta17fa672015-08-19 18:42:22 -070038import java.util.HashMap;
39import java.util.HashSet;
40import java.util.List;
41import java.util.Map;
42import java.util.Set;
Simon Hunta17fa672015-08-19 18:42:22 -070043
Pier59266bc2018-03-15 12:10:24 -070044import static org.onosproject.net.DefaultEdgeLink.createEdgeLinks;
Simon Hunt1911fe42017-05-02 18:25:58 -070045import static org.onosproject.ui.impl.TrafficMonitorBase.Mode.RELATED_INTENTS;
46import static org.onosproject.ui.impl.TrafficMonitorBase.Mode.SELECTED_INTENT;
Simon Hunta17fa672015-08-19 18:42:22 -070047
48/**
49 * Encapsulates the behavior of monitoring specific traffic patterns.
50 */
Simon Hunt1911fe42017-05-02 18:25:58 -070051public class TrafficMonitor extends TrafficMonitorBase {
Simon Hunta17fa672015-08-19 18:42:22 -070052
53 private static final Logger log =
Simon Hunt4fc86852015-08-20 17:57:52 -070054 LoggerFactory.getLogger(TrafficMonitor.class);
Simon Hunta17fa672015-08-19 18:42:22 -070055
Simon Hunt4fc86852015-08-20 17:57:52 -070056 private final TopologyViewMessageHandler msgHandler;
Simon Hunta17fa672015-08-19 18:42:22 -070057
58
59 /**
60 * Constructs a traffic monitor.
61 *
Simon Hunt5328f792017-01-11 17:43:31 -080062 * @param trafficPeriod traffic task period in ms
63 * @param servicesBundle bundle of services
64 * @param msgHandler our message handler
Simon Hunta17fa672015-08-19 18:42:22 -070065 */
Simon Hunt4fc86852015-08-20 17:57:52 -070066 public TrafficMonitor(long trafficPeriod, ServicesBundle servicesBundle,
67 TopologyViewMessageHandler msgHandler) {
Sean Condonadeb7162019-04-13 20:56:14 +010068 super(trafficPeriod, servicesBundle, msgHandler);
Simon Hunt4fc86852015-08-20 17:57:52 -070069 this.msgHandler = msgHandler;
Simon Hunta17fa672015-08-19 18:42:22 -070070
Simon Hunta17fa672015-08-19 18:42:22 -070071 }
72
73 // =======================================================================
Simon Hunt4fc86852015-08-20 17:57:52 -070074 // === API ===
Simon Hunta17fa672015-08-19 18:42:22 -070075
Simon Hunta7aea842017-05-03 19:42:50 -070076 // monitor(Mode) is now implemented in the super class
Simon Hunta17fa672015-08-19 18:42:22 -070077
Simon Hunt4fc86852015-08-20 17:57:52 -070078 // TODO: move this out to the "h2h/multi-intent app"
Simon Hunt5328f792017-01-11 17:43:31 -080079
Simon Hunt4fc86852015-08-20 17:57:52 -070080 /**
Simon Hunt4fc86852015-08-20 17:57:52 -070081 * Selects the next intent in the select group (if there is one),
82 * and sends highlighting data back to the web client to display
83 * which path is selected.
84 */
Simon Hunta17fa672015-08-19 18:42:22 -070085 public synchronized void selectNextIntent() {
86 if (selectedIntents != null) {
87 selectedIntents.next();
88 sendSelectedIntents();
Simon Hunt57830172015-08-26 13:25:17 -070089 if (mode == SELECTED_INTENT) {
90 mode = RELATED_INTENTS;
91 }
Simon Hunta17fa672015-08-19 18:42:22 -070092 }
93 }
94
Simon Hunt4fc86852015-08-20 17:57:52 -070095 /**
96 * Selects the previous intent in the select group (if there is one),
97 * and sends highlighting data back to the web client to display
98 * which path is selected.
99 */
Simon Hunta17fa672015-08-19 18:42:22 -0700100 public synchronized void selectPreviousIntent() {
101 if (selectedIntents != null) {
102 selectedIntents.prev();
103 sendSelectedIntents();
Simon Hunt57830172015-08-26 13:25:17 -0700104 if (mode == SELECTED_INTENT) {
105 mode = RELATED_INTENTS;
106 }
Simon Hunta17fa672015-08-19 18:42:22 -0700107 }
108 }
109
Simon Hunt4fc86852015-08-20 17:57:52 -0700110 /**
111 * Resends selected intent traffic data. This is called, for example,
112 * when the system detects an intent update happened.
113 */
Simon Hunta17fa672015-08-19 18:42:22 -0700114 public synchronized void pokeIntent() {
Simon Hunt4fc86852015-08-20 17:57:52 -0700115 if (mode == SELECTED_INTENT) {
Simon Hunta17fa672015-08-19 18:42:22 -0700116 sendSelectedIntentTraffic();
117 }
118 }
119
Simon Hunta17fa672015-08-19 18:42:22 -0700120 // =======================================================================
Simon Hunt1911fe42017-05-02 18:25:58 -0700121 // === Abstract method implementations ===
Simon Hunta17fa672015-08-19 18:42:22 -0700122
Simon Hunt1911fe42017-05-02 18:25:58 -0700123 @Override
124 protected void sendAllFlowTraffic() {
Simon Hunta17fa672015-08-19 18:42:22 -0700125 log.debug("sendAllFlowTraffic");
Simon Hunt57830172015-08-26 13:25:17 -0700126 msgHandler.sendHighlights(trafficSummary(StatsType.FLOW_STATS));
Simon Hunta17fa672015-08-19 18:42:22 -0700127 }
128
Simon Hunt1911fe42017-05-02 18:25:58 -0700129 @Override
130 protected void sendAllPortTrafficBits() {
131 log.debug("sendAllPortTrafficBits");
132 msgHandler.sendHighlights(trafficSummary(StatsType.PORT_STATS));
Simon Hunta17fa672015-08-19 18:42:22 -0700133 }
134
Simon Hunt1911fe42017-05-02 18:25:58 -0700135 @Override
136 protected void sendAllPortTrafficPackets() {
137 log.debug("sendAllPortTrafficPackets");
138 msgHandler.sendHighlights(trafficSummary(StatsType.PORT_PACKET_STATS));
139 }
140
141 @Override
142 protected void sendDeviceLinkFlows() {
Simon Hunta17fa672015-08-19 18:42:22 -0700143 log.debug("sendDeviceLinkFlows: {}", selectedNodes);
Simon Hunt4fc86852015-08-20 17:57:52 -0700144 msgHandler.sendHighlights(deviceLinkFlows());
Simon Hunta17fa672015-08-19 18:42:22 -0700145 }
146
Simon Hunt1911fe42017-05-02 18:25:58 -0700147 @Override
148 protected void sendSelectedIntentTraffic() {
Simon Hunta17fa672015-08-19 18:42:22 -0700149 log.debug("sendSelectedIntentTraffic: {}", selectedIntents);
Simon Hunt4fc86852015-08-20 17:57:52 -0700150 msgHandler.sendHighlights(intentTraffic());
Simon Hunta17fa672015-08-19 18:42:22 -0700151 }
152
Simon Hunt1911fe42017-05-02 18:25:58 -0700153 @Override
Thomas Vachuska2b4de872021-03-30 16:31:34 -0700154 protected void sendCustomTraffic() {
155 log.debug("sendCustomTraffic");
156 if (topoHighlighter != null) {
157 msgHandler.sendHighlights(topoHighlighter.createHighlights());
158 }
159 }
160
161 @Override
Simon Hunt1911fe42017-05-02 18:25:58 -0700162 protected void sendClearHighlights() {
Simon Hunta17fa672015-08-19 18:42:22 -0700163 log.debug("sendClearHighlights");
Simon Hunt4fc86852015-08-20 17:57:52 -0700164 msgHandler.sendHighlights(new Highlights());
Simon Hunta17fa672015-08-19 18:42:22 -0700165 }
166
Simon Hunt1911fe42017-05-02 18:25:58 -0700167 @Override
168 protected void clearSelection() {
169 selectedNodes = null;
170 selectedIntents = null;
171 }
172
Simon Hunta17fa672015-08-19 18:42:22 -0700173 // =======================================================================
174 // === Generate messages in JSON object node format
175
Simon Hunta7aea842017-05-03 19:42:50 -0700176 // NOTE: trafficSummary(StatsType) => Highlights
177 // has been moved to the superclass
Simon Hunta17fa672015-08-19 18:42:22 -0700178
179 // create highlights for links, showing flows for selected devices.
180 private Highlights deviceLinkFlows() {
181 Highlights highlights = new Highlights();
182
Simon Hunt72297212015-08-25 10:15:33 -0700183 if (selectedNodes != null && !selectedNodes.devicesWithHover().isEmpty()) {
Simon Hunta17fa672015-08-19 18:42:22 -0700184 // capture flow counts on bilinks
Simon Hunt4fc86852015-08-20 17:57:52 -0700185 TrafficLinkMap linkMap = new TrafficLinkMap();
Simon Hunta17fa672015-08-19 18:42:22 -0700186
Simon Hunt72297212015-08-25 10:15:33 -0700187 for (Device device : selectedNodes.devicesWithHover()) {
Simon Hunta17fa672015-08-19 18:42:22 -0700188 Map<Link, Integer> counts = getLinkFlowCounts(device.id());
189 for (Link link : counts.keySet()) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700190 TrafficLink tlink = linkMap.add(link);
191 tlink.addFlows(counts.get(link));
Simon Hunta17fa672015-08-19 18:42:22 -0700192 }
193 }
194
195 // now report on our collated links
Simon Hunt4fc86852015-08-20 17:57:52 -0700196 for (TrafficLink tlink : linkMap.biLinks()) {
Simon Hunt57830172015-08-26 13:25:17 -0700197 highlights.add(tlink.highlight(StatsType.FLOW_COUNT));
Simon Hunta17fa672015-08-19 18:42:22 -0700198 }
199
200 }
201 return highlights;
202 }
203
Simon Hunta17fa672015-08-19 18:42:22 -0700204 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
205
Simon Hunta17fa672015-08-19 18:42:22 -0700206 // Counts all flow entries that egress on the links of the given device.
207 private Map<Link, Integer> getLinkFlowCounts(DeviceId deviceId) {
208 // get the flows for the device
209 List<FlowEntry> entries = new ArrayList<>();
Simon Hunt1911fe42017-05-02 18:25:58 -0700210 for (FlowEntry flowEntry : services.flow().getFlowEntries(deviceId)) {
Simon Hunta17fa672015-08-19 18:42:22 -0700211 entries.add(flowEntry);
212 }
213
214 // get egress links from device, and include edge links
Simon Hunt1911fe42017-05-02 18:25:58 -0700215 Set<Link> links = new HashSet<>(services.link()
216 .getDeviceEgressLinks(deviceId));
217 Set<Host> hosts = services.host().getConnectedHosts(deviceId);
Simon Hunta17fa672015-08-19 18:42:22 -0700218 if (hosts != null) {
219 for (Host host : hosts) {
Pier59266bc2018-03-15 12:10:24 -0700220 links.addAll(createEdgeLinks(host, false));
Simon Hunta17fa672015-08-19 18:42:22 -0700221 }
222 }
223
224 // compile flow counts per link
225 Map<Link, Integer> counts = new HashMap<>();
226 for (Link link : links) {
227 counts.put(link, getEgressFlows(link, entries));
228 }
229 return counts;
230 }
231
232 // Counts all entries that egress on the link source port.
233 private int getEgressFlows(Link link, List<FlowEntry> entries) {
234 int count = 0;
235 PortNumber out = link.src().port();
236 for (FlowEntry entry : entries) {
237 TrafficTreatment treatment = entry.treatment();
238 for (Instruction instruction : treatment.allInstructions()) {
239 if (instruction.type() == Instruction.Type.OUTPUT &&
240 ((OutputInstruction) instruction).port().equals(out)) {
241 count++;
242 }
243 }
244 }
245 return count;
246 }
247
Simon Hunta17fa672015-08-19 18:42:22 -0700248}