blob: 73bda39e82a0e1d1a535ca1dfb97c79f23acb536 [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 servicesBundle bundle of services
63 * @param msgHandler our message handler
Simon Hunta17fa672015-08-19 18:42:22 -070064 */
Thomas Vachuskaa5e986d2021-04-06 11:14:09 -070065 public TrafficMonitor(ServicesBundle servicesBundle, TopologyViewMessageHandler msgHandler) {
66 super(servicesBundle, msgHandler);
Simon Hunt4fc86852015-08-20 17:57:52 -070067 this.msgHandler = msgHandler;
Simon Hunta17fa672015-08-19 18:42:22 -070068
Simon Hunta17fa672015-08-19 18:42:22 -070069 }
70
71 // =======================================================================
Simon Hunt4fc86852015-08-20 17:57:52 -070072 // === API ===
Simon Hunta17fa672015-08-19 18:42:22 -070073
Simon Hunta7aea842017-05-03 19:42:50 -070074 // monitor(Mode) is now implemented in the super class
Simon Hunta17fa672015-08-19 18:42:22 -070075
Simon Hunt4fc86852015-08-20 17:57:52 -070076 // TODO: move this out to the "h2h/multi-intent app"
Simon Hunt5328f792017-01-11 17:43:31 -080077
Simon Hunt4fc86852015-08-20 17:57:52 -070078 /**
Simon Hunt4fc86852015-08-20 17:57:52 -070079 * Selects the next intent in the select group (if there is one),
80 * and sends highlighting data back to the web client to display
81 * which path is selected.
82 */
Simon Hunta17fa672015-08-19 18:42:22 -070083 public synchronized void selectNextIntent() {
84 if (selectedIntents != null) {
85 selectedIntents.next();
86 sendSelectedIntents();
Simon Hunt57830172015-08-26 13:25:17 -070087 if (mode == SELECTED_INTENT) {
88 mode = RELATED_INTENTS;
89 }
Simon Hunta17fa672015-08-19 18:42:22 -070090 }
91 }
92
Simon Hunt4fc86852015-08-20 17:57:52 -070093 /**
94 * Selects the previous intent in the select group (if there is one),
95 * and sends highlighting data back to the web client to display
96 * which path is selected.
97 */
Simon Hunta17fa672015-08-19 18:42:22 -070098 public synchronized void selectPreviousIntent() {
99 if (selectedIntents != null) {
100 selectedIntents.prev();
101 sendSelectedIntents();
Simon Hunt57830172015-08-26 13:25:17 -0700102 if (mode == SELECTED_INTENT) {
103 mode = RELATED_INTENTS;
104 }
Simon Hunta17fa672015-08-19 18:42:22 -0700105 }
106 }
107
Simon Hunt4fc86852015-08-20 17:57:52 -0700108 /**
109 * Resends selected intent traffic data. This is called, for example,
110 * when the system detects an intent update happened.
111 */
Simon Hunta17fa672015-08-19 18:42:22 -0700112 public synchronized void pokeIntent() {
Simon Hunt4fc86852015-08-20 17:57:52 -0700113 if (mode == SELECTED_INTENT) {
Simon Hunta17fa672015-08-19 18:42:22 -0700114 sendSelectedIntentTraffic();
115 }
116 }
117
Simon Hunta17fa672015-08-19 18:42:22 -0700118 // =======================================================================
Simon Hunt1911fe42017-05-02 18:25:58 -0700119 // === Abstract method implementations ===
Simon Hunta17fa672015-08-19 18:42:22 -0700120
Simon Hunt1911fe42017-05-02 18:25:58 -0700121 @Override
122 protected void sendAllFlowTraffic() {
Simon Hunta17fa672015-08-19 18:42:22 -0700123 log.debug("sendAllFlowTraffic");
Simon Hunt57830172015-08-26 13:25:17 -0700124 msgHandler.sendHighlights(trafficSummary(StatsType.FLOW_STATS));
Simon Hunta17fa672015-08-19 18:42:22 -0700125 }
126
Simon Hunt1911fe42017-05-02 18:25:58 -0700127 @Override
128 protected void sendAllPortTrafficBits() {
129 log.debug("sendAllPortTrafficBits");
130 msgHandler.sendHighlights(trafficSummary(StatsType.PORT_STATS));
Simon Hunta17fa672015-08-19 18:42:22 -0700131 }
132
Simon Hunt1911fe42017-05-02 18:25:58 -0700133 @Override
134 protected void sendAllPortTrafficPackets() {
135 log.debug("sendAllPortTrafficPackets");
136 msgHandler.sendHighlights(trafficSummary(StatsType.PORT_PACKET_STATS));
137 }
138
139 @Override
140 protected void sendDeviceLinkFlows() {
Simon Hunta17fa672015-08-19 18:42:22 -0700141 log.debug("sendDeviceLinkFlows: {}", selectedNodes);
Simon Hunt4fc86852015-08-20 17:57:52 -0700142 msgHandler.sendHighlights(deviceLinkFlows());
Simon Hunta17fa672015-08-19 18:42:22 -0700143 }
144
Simon Hunt1911fe42017-05-02 18:25:58 -0700145 @Override
146 protected void sendSelectedIntentTraffic() {
Simon Hunta17fa672015-08-19 18:42:22 -0700147 log.debug("sendSelectedIntentTraffic: {}", selectedIntents);
Simon Hunt4fc86852015-08-20 17:57:52 -0700148 msgHandler.sendHighlights(intentTraffic());
Simon Hunta17fa672015-08-19 18:42:22 -0700149 }
150
Simon Hunt1911fe42017-05-02 18:25:58 -0700151 @Override
Thomas Vachuska2b4de872021-03-30 16:31:34 -0700152 protected void sendCustomTraffic() {
153 log.debug("sendCustomTraffic");
154 if (topoHighlighter != null) {
155 msgHandler.sendHighlights(topoHighlighter.createHighlights());
156 }
157 }
158
159 @Override
Simon Hunt1911fe42017-05-02 18:25:58 -0700160 protected void sendClearHighlights() {
Simon Hunta17fa672015-08-19 18:42:22 -0700161 log.debug("sendClearHighlights");
Simon Hunt4fc86852015-08-20 17:57:52 -0700162 msgHandler.sendHighlights(new Highlights());
Simon Hunta17fa672015-08-19 18:42:22 -0700163 }
164
Simon Hunt1911fe42017-05-02 18:25:58 -0700165 @Override
166 protected void clearSelection() {
167 selectedNodes = null;
168 selectedIntents = null;
169 }
170
Simon Hunta17fa672015-08-19 18:42:22 -0700171 // =======================================================================
172 // === Generate messages in JSON object node format
173
Simon Hunta7aea842017-05-03 19:42:50 -0700174 // NOTE: trafficSummary(StatsType) => Highlights
175 // has been moved to the superclass
Simon Hunta17fa672015-08-19 18:42:22 -0700176
177 // create highlights for links, showing flows for selected devices.
178 private Highlights deviceLinkFlows() {
179 Highlights highlights = new Highlights();
180
Simon Hunt72297212015-08-25 10:15:33 -0700181 if (selectedNodes != null && !selectedNodes.devicesWithHover().isEmpty()) {
Simon Hunta17fa672015-08-19 18:42:22 -0700182 // capture flow counts on bilinks
Simon Hunt4fc86852015-08-20 17:57:52 -0700183 TrafficLinkMap linkMap = new TrafficLinkMap();
Simon Hunta17fa672015-08-19 18:42:22 -0700184
Simon Hunt72297212015-08-25 10:15:33 -0700185 for (Device device : selectedNodes.devicesWithHover()) {
Simon Hunta17fa672015-08-19 18:42:22 -0700186 Map<Link, Integer> counts = getLinkFlowCounts(device.id());
187 for (Link link : counts.keySet()) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700188 TrafficLink tlink = linkMap.add(link);
189 tlink.addFlows(counts.get(link));
Simon Hunta17fa672015-08-19 18:42:22 -0700190 }
191 }
192
193 // now report on our collated links
Simon Hunt4fc86852015-08-20 17:57:52 -0700194 for (TrafficLink tlink : linkMap.biLinks()) {
Simon Hunt57830172015-08-26 13:25:17 -0700195 highlights.add(tlink.highlight(StatsType.FLOW_COUNT));
Simon Hunta17fa672015-08-19 18:42:22 -0700196 }
197
198 }
199 return highlights;
200 }
201
Simon Hunta17fa672015-08-19 18:42:22 -0700202 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
203
Simon Hunta17fa672015-08-19 18:42:22 -0700204 // Counts all flow entries that egress on the links of the given device.
205 private Map<Link, Integer> getLinkFlowCounts(DeviceId deviceId) {
206 // get the flows for the device
207 List<FlowEntry> entries = new ArrayList<>();
Simon Hunt1911fe42017-05-02 18:25:58 -0700208 for (FlowEntry flowEntry : services.flow().getFlowEntries(deviceId)) {
Simon Hunta17fa672015-08-19 18:42:22 -0700209 entries.add(flowEntry);
210 }
211
212 // get egress links from device, and include edge links
Simon Hunt1911fe42017-05-02 18:25:58 -0700213 Set<Link> links = new HashSet<>(services.link()
214 .getDeviceEgressLinks(deviceId));
215 Set<Host> hosts = services.host().getConnectedHosts(deviceId);
Simon Hunta17fa672015-08-19 18:42:22 -0700216 if (hosts != null) {
217 for (Host host : hosts) {
Pier59266bc2018-03-15 12:10:24 -0700218 links.addAll(createEdgeLinks(host, false));
Simon Hunta17fa672015-08-19 18:42:22 -0700219 }
220 }
221
222 // compile flow counts per link
223 Map<Link, Integer> counts = new HashMap<>();
224 for (Link link : links) {
225 counts.put(link, getEgressFlows(link, entries));
226 }
227 return counts;
228 }
229
230 // Counts all entries that egress on the link source port.
231 private int getEgressFlows(Link link, List<FlowEntry> entries) {
232 int count = 0;
233 PortNumber out = link.src().port();
234 for (FlowEntry entry : entries) {
235 TrafficTreatment treatment = entry.treatment();
236 for (Instruction instruction : treatment.allInstructions()) {
237 if (instruction.type() == Instruction.Type.OUTPUT &&
238 ((OutputInstruction) instruction).port().equals(out)) {
239 count++;
240 }
241 }
242 }
243 return count;
244 }
245
Simon Hunta17fa672015-08-19 18:42:22 -0700246}