blob: ca9d6683ace57acacccb20bc1e6d01f02febc9a1 [file] [log] [blame]
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -08001/*
2 * Copyright 2014,2015 Open Networking Laboratory
3 *
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 */
16package org.onosproject.pathpainter;
17
18import com.fasterxml.jackson.databind.node.ObjectNode;
19import com.google.common.collect.ImmutableList;
20import com.google.common.collect.ImmutableSet;
Andrea Campanella8583e6b2015-12-01 21:24:45 -080021import com.google.common.collect.Sets;
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080022import org.onlab.osgi.ServiceDirectory;
23import org.onosproject.net.DeviceId;
Thomas Vachuska08bef152015-12-02 17:08:59 -080024import org.onosproject.net.DisjointPath;
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080025import org.onosproject.net.ElementId;
26import org.onosproject.net.HostId;
27import org.onosproject.net.Link;
28import org.onosproject.net.Path;
29import org.onosproject.net.topology.PathService;
30import org.onosproject.ui.RequestHandler;
31import org.onosproject.ui.UiConnection;
32import org.onosproject.ui.UiMessageHandler;
33import org.onosproject.ui.topo.Highlights;
34import org.onosproject.ui.topo.TopoJson;
35import org.slf4j.Logger;
36import org.slf4j.LoggerFactory;
37
38import java.util.Collection;
39import java.util.List;
40import java.util.Set;
41
42/**
43 * Skeletal ONOS UI Topology-Overlay message handler.
44 */
45public class PathPainterTopovMessageHandler extends UiMessageHandler {
46
47 private static final String PAINTER_SET_SRC = "ppTopovSetSrc";
48 private static final String PAINTER_SET_DST = "ppTopovSetDst";
49 private static final String PAINTER_SWAP_SRC_DST = "ppTopovSwapSrcDst";
50 private static final String PAINTER_SET_MODE = "ppTopovSetMode";
51
52 private static final String PAINTER_NEXT_PATH = "ppTopovNextPath";
53 private static final String PAINTER_PREV_PATH = "ppTopovPrevPath";
54
55 private static final String ID = "id";
56 private static final String MODE = "mode";
57
58 private Set<Link> allPathLinks;
59
60 private enum Mode {
61 SHORTEST, DISJOINT, SRLG
62 }
63
64 private final Logger log = LoggerFactory.getLogger(getClass());
65
66 private PathService pathService;
67
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080068 private ElementId src, dst;
Andrea Campanella8583e6b2015-12-01 21:24:45 -080069 private Mode currentMode = Mode.SHORTEST;
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080070 private List<Path> paths;
71 private int pathIndex;
72
73
74 // ===============-=-=-=-=-=-======================-=-=-=-=-=-=-================================
75
76
77 @Override
78 public void init(UiConnection connection, ServiceDirectory directory) {
79 super.init(connection, directory);
80 pathService = directory.get(PathService.class);
81 }
82
83 @Override
84 protected Collection<RequestHandler> createRequestHandlers() {
85 return ImmutableSet.of(
86 new SetSrcHandler(),
87 new SetDstHandler(),
Andrea Campanella0c17a0a2015-12-01 09:53:51 -080088 new SwapSrcDstHandler(),
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080089 new NextPathHandler(),
Andrea Campanella8583e6b2015-12-01 21:24:45 -080090 new PrevPathHandler(),
91 new SetModeHandler()
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080092 );
93 }
94
95 // === -------------------------
96 // === Handler classes
97
98 private final class SetSrcHandler extends RequestHandler {
99 public SetSrcHandler() {
100 super(PAINTER_SET_SRC);
101 }
102
103 @Override
104 public void process(long sid, ObjectNode payload) {
105 String id = string(payload, ID);
106 src = elementId(id);
107 if (src.equals(dst)) {
108 dst = null;
109 }
110 findAndSendPaths();
111 }
112 }
113
114 private final class SetDstHandler extends RequestHandler {
115 public SetDstHandler() {
116 super(PAINTER_SET_DST);
117 }
118
119 @Override
120 public void process(long sid, ObjectNode payload) {
121 String id = string(payload, ID);
122 dst = elementId(id);
123 if (src.equals(dst)) {
124 src = null;
125 }
126 findAndSendPaths();
127 }
128 }
129
Andrea Campanella0c17a0a2015-12-01 09:53:51 -0800130 private final class SwapSrcDstHandler extends RequestHandler {
131 public SwapSrcDstHandler() {
132 super(PAINTER_SWAP_SRC_DST);
133 }
134
135 @Override
136 public void process(long sid, ObjectNode payload) {
137 ElementId temp = src;
138 src = dst;
139 dst = temp;
140 findAndSendPaths();
141 }
142 }
143
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800144 private final class NextPathHandler extends RequestHandler {
145 public NextPathHandler() {
146 super(PAINTER_NEXT_PATH);
147 }
148
149 @Override
150 public void process(long sid, ObjectNode payload) {
151 pathIndex = (pathIndex >= paths.size() - 1 ? 0 : pathIndex + 1);
152 hilightAndSendPaths();
153 }
154 }
155
156 private final class PrevPathHandler extends RequestHandler {
157 public PrevPathHandler() {
158 super(PAINTER_PREV_PATH);
159 }
160
161 @Override
162 public void process(long sid, ObjectNode payload) {
163 pathIndex = (pathIndex <= 0 ? paths.size() - 1 : pathIndex - 1);
164 hilightAndSendPaths();
165 }
166 }
167
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800168 private final class SetModeHandler extends RequestHandler {
169 public SetModeHandler() {
170 super(PAINTER_SET_MODE);
171 }
172
173 @Override
174 public void process(long sid, ObjectNode payload) {
175 String mode = string(payload, MODE);
176 currentMode = (mode.equals("shortest") ?
177 Mode.SHORTEST : (mode.equals("disjoint") ?
178 Mode.DISJOINT : Mode.SRLG));
179 //TODO: add support for SRLG
180 if (currentMode.equals(Mode.SHORTEST)) {
181 findAndSendPaths();
182 } else {
183 findAndSendDisjointPaths();
184 }
185 }
186 }
187
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800188 // === ------------
189
190 private ElementId elementId(String id) {
191 try {
192 return DeviceId.deviceId(id);
193 } catch (IllegalArgumentException e) {
194 return HostId.hostId(id);
195 }
196 }
197
198 private void findAndSendPaths() {
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800199 if (src != null && dst != null) {
200 paths = ImmutableList.copyOf(pathService.getPaths(src, dst));
201 pathIndex = 0;
202
203 ImmutableSet.Builder<Link> builder = ImmutableSet.builder();
204 paths.forEach(path -> path.links().forEach(builder::add));
205 allPathLinks = builder.build();
206 } else {
207 paths = ImmutableList.of();
208 allPathLinks = ImmutableSet.of();
209 }
210 hilightAndSendPaths();
211 }
212
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800213 private void findAndSendDisjointPaths() {
214 log.info("src={}; dst={}; mode={}", src, dst, currentMode);
215 if (src != null && dst != null) {
216 log.info("test" + src + dst);
Thomas Vachuska08bef152015-12-02 17:08:59 -0800217 paths = ImmutableList.copyOf(pathService.getDisjointPaths(src, dst));
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800218 pathIndex = 0;
219
220 ImmutableSet.Builder<Link> builder = ImmutableSet.builder();
Thomas Vachuska08bef152015-12-02 17:08:59 -0800221 paths.forEach(path -> {
222 DisjointPath dp = (DisjointPath) path;
223 builder.addAll(dp.primary().links());
224 builder.addAll(dp.backup().links());
225 });
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800226 allPathLinks = builder.build();
227 } else {
228 paths = ImmutableList.of();
229 allPathLinks = ImmutableSet.of();
230 }
231 hilightAndSendPaths();
232 }
233
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800234 private void hilightAndSendPaths() {
235 PathLinkMap linkMap = new PathLinkMap();
236 allPathLinks.forEach(linkMap::add);
237
Thomas Vachuska08bef152015-12-02 17:08:59 -0800238 Set<Link> selectedPathLinks;
239
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800240 // Prepare two working sets; one containing selected path links and
241 // the other containing all paths links.
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800242 if (currentMode.equals(Mode.DISJOINT)) {
Thomas Vachuska08bef152015-12-02 17:08:59 -0800243 DisjointPath dp = (DisjointPath) paths.get(pathIndex);
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800244 selectedPathLinks = paths.isEmpty() ?
Thomas Vachuska08bef152015-12-02 17:08:59 -0800245 ImmutableSet.of() : Sets.newHashSet(dp.primary().links());
246 selectedPathLinks.addAll(dp.backup().links());
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800247 } else {
248 selectedPathLinks = paths.isEmpty() ?
Thomas Vachuska08bef152015-12-02 17:08:59 -0800249 ImmutableSet.of() : ImmutableSet.copyOf(paths.get(pathIndex).links());
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800250 }
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800251 Highlights highlights = new Highlights();
252 for (PathLink plink : linkMap.biLinks()) {
253 plink.computeHilight(selectedPathLinks, allPathLinks);
254 highlights.add(plink.highlight(null));
255 }
256
257 sendMessage(TopoJson.highlightsMessage(highlights));
258 }
259
260 /*
261 private void addDeviceBadge(Highlights h, DeviceId devId, int n) {
262 DeviceHighlight dh = new DeviceHighlight(devId.toString());
263 dh.setBadge(createBadge(n));
264 h.add(dh);
265 }
266
267 private NodeBadge createBadge(int n) {
268 Status status = n > 3 ? Status.ERROR : Status.WARN;
269 String noun = n > 3 ? "(critical)" : "(problematic)";
270 String msg = "Egress links: " + n + " " + noun;
271 return NodeBadge.number(status, n, msg);
272 }
273 */
274
275}