blob: 9c84563b3270503c0dcb7de20c9d4ec87aac0e1c [file] [log] [blame]
Simon Hunte6f64612017-04-28 00:01:48 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Simon Hunte6f64612017-04-28 00:01:48 -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.topo;
19
Sean Condonadeb7162019-04-13 20:56:14 +010020import com.fasterxml.jackson.databind.JsonNode;
21import com.fasterxml.jackson.databind.node.ArrayNode;
Simon Hunte6f64612017-04-28 00:01:48 -070022import com.fasterxml.jackson.databind.node.ObjectNode;
23import com.google.common.collect.ImmutableSet;
24import org.onlab.osgi.ServiceDirectory;
Sean Condonadeb7162019-04-13 20:56:14 +010025import org.onosproject.core.ApplicationId;
26import org.onosproject.core.CoreService;
27import org.onosproject.net.FilteredConnectPoint;
28import org.onosproject.net.Host;
29import org.onosproject.net.HostId;
30import org.onosproject.net.HostLocation;
31import org.onosproject.net.flow.DefaultTrafficSelector;
32import org.onosproject.net.flow.DefaultTrafficTreatment;
33import org.onosproject.net.flow.TrafficSelector;
34import org.onosproject.net.flow.TrafficTreatment;
35import org.onosproject.net.intent.HostToHostIntent;
36import org.onosproject.net.intent.MultiPointToSinglePointIntent;
Simon Hunte6f64612017-04-28 00:01:48 -070037import org.onosproject.ui.RequestHandler;
38import org.onosproject.ui.UiConnection;
Simon Hunt9e2413e2017-05-03 14:25:40 -070039import org.onosproject.ui.impl.TrafficMonitorBase.Mode;
Simon Hunt0e161092017-05-08 17:41:38 -070040import org.onosproject.ui.impl.UiWebSocket;
Simon Hunt1911fe42017-05-02 18:25:58 -070041import org.onosproject.ui.impl.topo.util.ServicesBundle;
Simon Hunt0e161092017-05-08 17:41:38 -070042import org.onosproject.ui.model.topo.UiLinkId;
43import org.onosproject.ui.model.topo.UiSynthLink;
Simon Hunt8e258112017-05-05 13:19:04 -070044import org.onosproject.ui.topo.Highlights;
Sean Condonadeb7162019-04-13 20:56:14 +010045import org.onosproject.ui.topo.NodeSelection;
Simon Hunte6f64612017-04-28 00:01:48 -070046import org.slf4j.Logger;
47import org.slf4j.LoggerFactory;
48
49import java.util.Collection;
Sean Condonadeb7162019-04-13 20:56:14 +010050import java.util.HashSet;
Simon Hunt0e161092017-05-08 17:41:38 -070051import java.util.Map;
Sean Condonadeb7162019-04-13 20:56:14 +010052import java.util.Set;
Simon Hunte6f64612017-04-28 00:01:48 -070053
Sean Condonadeb7162019-04-13 20:56:14 +010054import static org.onosproject.net.HostId.hostId;
Simon Hunt8e258112017-05-05 13:19:04 -070055import static org.onosproject.ui.topo.TopoJson.topo2HighlightsMessage;
56
Simon Hunte6f64612017-04-28 00:01:48 -070057/**
58 * Server-side component to handle messages pertaining to topo-2 traffic.
59 */
Sean Condonadeb7162019-04-13 20:56:14 +010060public class Topo2TrafficMessageHandler extends TopoologyTrafficMessageHandlerAbstract {
Simon Hunte6f64612017-04-28 00:01:48 -070061
62 private final Logger log = LoggerFactory.getLogger(getClass());
63
64 // === Inbound event identifiers
65 private static final String REQUEST_ALL_TRAFFIC = "topo2RequestAllTraffic";
66 private static final String CANCEL_TRAFFIC = "topo2CancelTraffic";
Sean Condonadeb7162019-04-13 20:56:14 +010067 private static final String ADD_HOST_INTENT = "topo2AddHostIntent";
68 private static final String ADD_MULTI_SRC_INTENT = "topo2AddMultiSourceIntent";
69 private static final String REQ_RELATED_INTENTS = "topo2RequestRelatedIntents";
Simon Hunte6f64612017-04-28 00:01:48 -070070
Simon Hunt9e2413e2017-05-03 14:25:40 -070071 // field values
72 private static final String TRAFFIC_TYPE = "trafficType";
73 private static final String FLOW_STATS_BYTES = "flowStatsBytes";
74 private static final String PORT_STATS_BIT_SEC = "portStatsBitSec";
75 private static final String PORT_STATS_PKT_SEC = "portStatsPktSec";
Simon Hunt1911fe42017-05-02 18:25:58 -070076
Sean Condonadeb7162019-04-13 20:56:14 +010077 // fields
78 private static final String ONE = "one";
79 private static final String TWO = "two";
80 private static final String SRC = "src";
81 private static final String DST = "dst";
82
Simon Hunt1911fe42017-05-02 18:25:58 -070083 protected ServicesBundle services;
Sean Condonadeb7162019-04-13 20:56:14 +010084 private static final String MY_APP_ID = "org.onosproject.gui";
85 private ApplicationId appId;
Simon Hunt0e161092017-05-08 17:41:38 -070086 private UiTopoSession topoSession;
Sean Condonadeb7162019-04-13 20:56:14 +010087 private Topo2OverlayCache overlay2Cache;
88 private Traffic2Monitor traffic2;
Simon Hunt1911fe42017-05-02 18:25:58 -070089
90
Simon Hunte6f64612017-04-28 00:01:48 -070091 @Override
92 public void init(UiConnection connection, ServiceDirectory directory) {
93 super.init(connection, directory);
Sean Condonadeb7162019-04-13 20:56:14 +010094 appId = directory.get(CoreService.class).registerApplication(MY_APP_ID);
Simon Hunt1911fe42017-05-02 18:25:58 -070095 services = new ServicesBundle(directory);
Thomas Vachuskae33e2dc2021-04-06 11:14:09 -070096 traffic2 = new Traffic2Monitor(services, this);
Simon Hunt0e161092017-05-08 17:41:38 -070097 topoSession = ((UiWebSocket) connection).topoSession();
Simon Hunte6f64612017-04-28 00:01:48 -070098 }
99
100 @Override
pierventre2c39dea2021-10-25 12:54:48 +0200101 public void destroy() {
102 super.destroy();
103 traffic2.stopMonitoring();
104 }
105
106 @Override
Simon Hunte6f64612017-04-28 00:01:48 -0700107 protected Collection<RequestHandler> createRequestHandlers() {
108 return ImmutableSet.of(
109 new Topo2AllTraffic(),
Sean Condonadeb7162019-04-13 20:56:14 +0100110 new Topo2CancelTraffic(),
111 new Topo2AddHostIntent(),
112 new Topo2AddMultiSourceIntent()
Simon Hunte6f64612017-04-28 00:01:48 -0700113 );
114 }
115
Simon Hunt2d7cd6f2017-05-04 13:04:50 -0700116 /**
Sean Condonadeb7162019-04-13 20:56:14 +0100117 * Injects the topology overlay cache.
118 *
119 * @param overlay2Cache injected cache
120 */
121 public void setOverlayCache(Topo2OverlayCache overlay2Cache) {
122 this.overlay2Cache = overlay2Cache;
123 }
124
125 /**
Simon Hunt2d7cd6f2017-05-04 13:04:50 -0700126 * Shuts down the background traffic monitoring task.
127 */
128 void ceaseAndDesist() {
Sean Condonadeb7162019-04-13 20:56:14 +0100129 traffic2.stopMonitoring();
Simon Hunt2d7cd6f2017-05-04 13:04:50 -0700130 }
131
Simon Hunt8e258112017-05-05 13:19:04 -0700132 /**
133 * Sends a highlights message back to the client.
134 *
135 * @param highlights the highlights for transmission
136 */
Sean Condonadeb7162019-04-13 20:56:14 +0100137 @Override
138 public void sendHighlights(Highlights highlights) {
Simon Hunt8e258112017-05-05 13:19:04 -0700139 sendMessage(topo2HighlightsMessage(highlights));
140 }
141
Simon Hunt0e161092017-05-08 17:41:38 -0700142 /**
143 * Asks the topo session for the relevant synth links for current region.
144 * The returned map is keyed by "original" link.
145 *
146 * @return synth link map
147 */
148 Map<UiLinkId, UiSynthLink> retrieveRelevantSynthLinks() {
149 return topoSession.relevantSynthLinks();
150 }
151
Simon Hunte6f64612017-04-28 00:01:48 -0700152 // ==================================================================
153
154 private final class Topo2AllTraffic extends RequestHandler {
Simon Hunt9e2413e2017-05-03 14:25:40 -0700155
Simon Hunte6f64612017-04-28 00:01:48 -0700156 private Topo2AllTraffic() {
157 super(REQUEST_ALL_TRAFFIC);
158 }
159
160 @Override
161 public void process(ObjectNode payload) {
Simon Hunt9e2413e2017-05-03 14:25:40 -0700162 String mode = string(payload, TRAFFIC_TYPE);
163 log.debug("SHOW TRAFFIC: {}", mode);
164
Simon Hunte6f64612017-04-28 00:01:48 -0700165 switch (mode) {
Simon Hunt9e2413e2017-05-03 14:25:40 -0700166 case FLOW_STATS_BYTES:
Sean Condonadeb7162019-04-13 20:56:14 +0100167 traffic2.monitor(Mode.ALL_FLOW_TRAFFIC_BYTES);
Simon Hunte6f64612017-04-28 00:01:48 -0700168 break;
169
Simon Hunt9e2413e2017-05-03 14:25:40 -0700170 case PORT_STATS_BIT_SEC:
Sean Condonadeb7162019-04-13 20:56:14 +0100171 traffic2.monitor(Mode.ALL_PORT_TRAFFIC_BIT_PS);
Simon Hunte6f64612017-04-28 00:01:48 -0700172 break;
173
Simon Hunt9e2413e2017-05-03 14:25:40 -0700174 case PORT_STATS_PKT_SEC:
Sean Condonadeb7162019-04-13 20:56:14 +0100175 traffic2.monitor(Mode.ALL_PORT_TRAFFIC_PKT_PS);
Simon Hunte6f64612017-04-28 00:01:48 -0700176 break;
177
178 default:
179 log.warn("Unknown traffic monitor type: " + mode);
180 break;
181 }
182 }
183 }
184
185 private final class Topo2CancelTraffic extends RequestHandler {
186 private Topo2CancelTraffic() {
187 super(CANCEL_TRAFFIC);
188 }
189
190 @Override
191 public void process(ObjectNode payload) {
192 log.debug("CANCEL TRAFFIC");
Sean Condonadeb7162019-04-13 20:56:14 +0100193 traffic2.stopMonitoring();
Simon Hunte6f64612017-04-28 00:01:48 -0700194 }
195 }
Sean Condonadeb7162019-04-13 20:56:14 +0100196
197 private final class Topo2AddHostIntent extends RequestHandler {
198 private Topo2AddHostIntent() {
199 super(ADD_HOST_INTENT);
200 }
201
202 @Override
203 public void process(ObjectNode payload) {
204 // TODO: add protection against device ids and non-existent hosts.
205 HostId one = hostId(string(payload, ONE));
206 HostId two = hostId(string(payload, TWO));
207
208 HostToHostIntent intent = HostToHostIntent.builder()
209 .appId(appId)
210 .one(one)
211 .two(two)
212 .build();
213
214 services.intent().submit(intent);
215 if (overlay2Cache.isActive(Traffic2Overlay.OVERLAY_ID)) {
216 traffic2.monitor(intent);
217 }
218 }
219 }
220
221 private final class Topo2AddMultiSourceIntent extends RequestHandler {
222 private Topo2AddMultiSourceIntent() {
223 super(ADD_MULTI_SRC_INTENT);
224 }
225
226 @Override
227 public void process(ObjectNode payload) {
228 // TODO: add protection against device ids and non-existent hosts.
229 Set<HostId> src = getHostIds((ArrayNode) payload.path(SRC));
230 HostId dst = hostId(string(payload, DST));
231 Host dstHost = services.host().getHost(dst);
232
233 Set<FilteredConnectPoint> ingressPoints = getHostLocations(src);
234
235 // FIXME: clearly, this is not enough
236 TrafficSelector selector = DefaultTrafficSelector.builder()
237 .matchEthDst(dstHost.mac()).build();
238 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
239
240 MultiPointToSinglePointIntent intent =
241 MultiPointToSinglePointIntent.builder()
242 .appId(appId)
243 .selector(selector)
244 .treatment(treatment)
245 .filteredIngressPoints(ingressPoints)
246 .filteredEgressPoint(new FilteredConnectPoint(dstHost.location()))
247 .build();
248
249 services.intent().submit(intent);
250 if (overlay2Cache.isActive(Traffic2Overlay.OVERLAY_ID)) {
251 traffic2.monitor(intent);
252 }
253 }
254 }
255
256 private final class ReqRelatedIntents extends RequestHandler {
257 private ReqRelatedIntents() {
258 super(REQ_RELATED_INTENTS);
259 }
260
261 @Override
262 public void process(ObjectNode payload) {
263 traffic2.monitor(Mode.RELATED_INTENTS, makeNodeSelection(payload));
264 }
265 }
266
267 // Produces a list of host ids from the specified JSON array.
268 private Set<HostId> getHostIds(ArrayNode ids) {
269 Set<HostId> hostIds = new HashSet<>();
270 for (JsonNode id : ids) {
271 hostIds.add(hostId(id.asText()));
272 }
273 return hostIds;
274 }
275
276 private Set<FilteredConnectPoint> getHostLocations(Set<HostId> hostIds) {
277 Set<FilteredConnectPoint> points = new HashSet<>();
278 for (HostId hostId : hostIds) {
279 points.add(new FilteredConnectPoint(getHostLocation(hostId)));
280 }
281 return points;
282 }
283
284 private HostLocation getHostLocation(HostId hostId) {
285 return services.host().getHost(hostId).location();
286 }
287
288 private NodeSelection makeNodeSelection(ObjectNode payload) {
289 return new NodeSelection(payload, services.device(), services.host(),
290 services.link());
291 }
Simon Hunte6f64612017-04-28 00:01:48 -0700292}
293
294