blob: 9d9b3c31fdad1c19269829368fdbc3623149b8c0 [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
154 protected void sendClearHighlights() {
Simon Hunta17fa672015-08-19 18:42:22 -0700155 log.debug("sendClearHighlights");
Simon Hunt4fc86852015-08-20 17:57:52 -0700156 msgHandler.sendHighlights(new Highlights());
Simon Hunta17fa672015-08-19 18:42:22 -0700157 }
158
Simon Hunt1911fe42017-05-02 18:25:58 -0700159 @Override
160 protected void clearSelection() {
161 selectedNodes = null;
162 selectedIntents = null;
163 }
164
Simon Hunta17fa672015-08-19 18:42:22 -0700165 // =======================================================================
166 // === Generate messages in JSON object node format
167
Simon Hunta7aea842017-05-03 19:42:50 -0700168 // NOTE: trafficSummary(StatsType) => Highlights
169 // has been moved to the superclass
Simon Hunta17fa672015-08-19 18:42:22 -0700170
171 // create highlights for links, showing flows for selected devices.
172 private Highlights deviceLinkFlows() {
173 Highlights highlights = new Highlights();
174
Simon Hunt72297212015-08-25 10:15:33 -0700175 if (selectedNodes != null && !selectedNodes.devicesWithHover().isEmpty()) {
Simon Hunta17fa672015-08-19 18:42:22 -0700176 // capture flow counts on bilinks
Simon Hunt4fc86852015-08-20 17:57:52 -0700177 TrafficLinkMap linkMap = new TrafficLinkMap();
Simon Hunta17fa672015-08-19 18:42:22 -0700178
Simon Hunt72297212015-08-25 10:15:33 -0700179 for (Device device : selectedNodes.devicesWithHover()) {
Simon Hunta17fa672015-08-19 18:42:22 -0700180 Map<Link, Integer> counts = getLinkFlowCounts(device.id());
181 for (Link link : counts.keySet()) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700182 TrafficLink tlink = linkMap.add(link);
183 tlink.addFlows(counts.get(link));
Simon Hunta17fa672015-08-19 18:42:22 -0700184 }
185 }
186
187 // now report on our collated links
Simon Hunt4fc86852015-08-20 17:57:52 -0700188 for (TrafficLink tlink : linkMap.biLinks()) {
Simon Hunt57830172015-08-26 13:25:17 -0700189 highlights.add(tlink.highlight(StatsType.FLOW_COUNT));
Simon Hunta17fa672015-08-19 18:42:22 -0700190 }
191
192 }
193 return highlights;
194 }
195
Simon Hunta17fa672015-08-19 18:42:22 -0700196 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
197
Simon Hunta17fa672015-08-19 18:42:22 -0700198 // Counts all flow entries that egress on the links of the given device.
199 private Map<Link, Integer> getLinkFlowCounts(DeviceId deviceId) {
200 // get the flows for the device
201 List<FlowEntry> entries = new ArrayList<>();
Simon Hunt1911fe42017-05-02 18:25:58 -0700202 for (FlowEntry flowEntry : services.flow().getFlowEntries(deviceId)) {
Simon Hunta17fa672015-08-19 18:42:22 -0700203 entries.add(flowEntry);
204 }
205
206 // get egress links from device, and include edge links
Simon Hunt1911fe42017-05-02 18:25:58 -0700207 Set<Link> links = new HashSet<>(services.link()
208 .getDeviceEgressLinks(deviceId));
209 Set<Host> hosts = services.host().getConnectedHosts(deviceId);
Simon Hunta17fa672015-08-19 18:42:22 -0700210 if (hosts != null) {
211 for (Host host : hosts) {
Pier59266bc2018-03-15 12:10:24 -0700212 links.addAll(createEdgeLinks(host, false));
Simon Hunta17fa672015-08-19 18:42:22 -0700213 }
214 }
215
216 // compile flow counts per link
217 Map<Link, Integer> counts = new HashMap<>();
218 for (Link link : links) {
219 counts.put(link, getEgressFlows(link, entries));
220 }
221 return counts;
222 }
223
224 // Counts all entries that egress on the link source port.
225 private int getEgressFlows(Link link, List<FlowEntry> entries) {
226 int count = 0;
227 PortNumber out = link.src().port();
228 for (FlowEntry entry : entries) {
229 TrafficTreatment treatment = entry.treatment();
230 for (Instruction instruction : treatment.allInstructions()) {
231 if (instruction.type() == Instruction.Type.OUTPUT &&
232 ((OutputInstruction) instruction).port().equals(out)) {
233 count++;
234 }
235 }
236 }
237 return count;
238 }
239
Simon Hunta17fa672015-08-19 18:42:22 -0700240}