blob: 1321bb65795dfcffb881d6cb680b795b1bbb9920 [file] [log] [blame]
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -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
17package org.onosproject.ui.impl;
18
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070019import com.fasterxml.jackson.databind.node.ObjectNode;
Simon Huntabd16f62015-05-01 13:14:40 -070020import com.google.common.base.Strings;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070021import com.google.common.collect.ImmutableSet;
Viswanath KSPd1212c72016-10-21 01:03:35 +053022import org.onosproject.core.ApplicationId;
23import org.onosproject.core.DefaultApplicationId;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070024import org.onosproject.net.DeviceId;
25import org.onosproject.net.flow.FlowEntry;
Viswanath KSPd1212c72016-10-21 01:03:35 +053026import org.onosproject.net.flow.FlowRule;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070027import org.onosproject.net.flow.FlowRuleService;
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +053028import org.onosproject.net.flow.TrafficTreatment;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070029import org.onosproject.net.flow.criteria.Criterion;
30import org.onosproject.net.flow.instructions.Instruction;
Simon Huntd2747a02015-04-30 22:41:16 -070031import org.onosproject.ui.RequestHandler;
Simon Hunta0ddb022015-05-01 09:53:01 -070032import org.onosproject.ui.UiMessageHandler;
Bri Prebilic Cole9467a232015-05-06 16:59:05 -070033import org.onosproject.ui.table.CellFormatter;
Simon Hunt3d1b0652015-05-05 17:27:24 -070034import org.onosproject.ui.table.TableModel;
Simon Huntabd16f62015-05-01 13:14:40 -070035import org.onosproject.ui.table.TableRequestHandler;
Bri Prebilic Cole9467a232015-05-06 16:59:05 -070036import org.onosproject.ui.table.cell.EnumFormatter;
Simon Hunt3e4ccaf2016-01-12 19:59:54 -080037import org.onosproject.ui.table.cell.HexLongFormatter;
Simon Huntbe60dde2016-01-13 12:26:56 -080038import org.onosproject.ui.table.cell.NumberFormatter;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070039
Simon Huntd2747a02015-04-30 22:41:16 -070040import java.util.Collection;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070041import java.util.List;
42import java.util.Set;
43
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +053044
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070045/**
46 * Message handler for flow view related messages.
47 */
Simon Hunta0ddb022015-05-01 09:53:01 -070048public class FlowViewMessageHandler extends UiMessageHandler {
Simon Huntd2747a02015-04-30 22:41:16 -070049
50 private static final String FLOW_DATA_REQ = "flowDataRequest";
Simon Huntabd16f62015-05-01 13:14:40 -070051 private static final String FLOW_DATA_RESP = "flowDataResponse";
52 private static final String FLOWS = "flows";
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070053
Viswanath KSPd1212c72016-10-21 01:03:35 +053054 private static final String FLOW_DETAILS_REQ = "flowDetailsRequest";
55 private static final String FLOW_DETAILS_RESP = "flowDetailsResponse";
56 private static final String DETAILS = "details";
57 private static final String FLOW_PRIORITY = "priority";
58
Simon Huntabd16f62015-05-01 13:14:40 -070059 private static final String ID = "id";
Viswanath KSPd1212c72016-10-21 01:03:35 +053060 private static final String FLOW_ID = "flowId";
Simon Huntabd16f62015-05-01 13:14:40 -070061 private static final String APP_ID = "appId";
62 private static final String GROUP_ID = "groupId";
63 private static final String TABLE_ID = "tableId";
64 private static final String PRIORITY = "priority";
Simon Hunt9bff5952017-07-13 14:05:09 -070065 private static final String SELECTOR_C = "selector_c"; // for table column
Simon Huntabd16f62015-05-01 13:14:40 -070066 private static final String SELECTOR = "selector";
Simon Hunt9bff5952017-07-13 14:05:09 -070067 private static final String TREATMENT_C = "treatment_c"; // for table column
Simon Huntabd16f62015-05-01 13:14:40 -070068 private static final String TREATMENT = "treatment";
69 private static final String TIMEOUT = "timeout";
70 private static final String PERMANENT = "permanent";
71 private static final String STATE = "state";
Bri Prebilic Cole641b97b2015-05-05 14:47:40 -070072 private static final String PACKETS = "packets";
Simon Hunt9bff5952017-07-13 14:05:09 -070073 private static final String DURATION = "duration";
Bri Prebilic Cole641b97b2015-05-05 14:47:40 -070074 private static final String BYTES = "bytes";
Simon Huntabd16f62015-05-01 13:14:40 -070075
76 private static final String COMMA = ", ";
Viswanath KSP70e0d142016-10-28 21:58:32 +053077 private static final String OX = "0x";
78 private static final String EMPTY = "";
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070079
Simon Hunt3d1b0652015-05-05 17:27:24 -070080 private static final String[] COL_IDS = {
Simon Hunt9bff5952017-07-13 14:05:09 -070081 ID,
82 STATE,
83 BYTES,
84 PACKETS,
85 DURATION,
86 PRIORITY,
87 TABLE_ID,
88 APP_ID,
89
90 GROUP_ID,
91 TIMEOUT,
92 PERMANENT,
93
94 SELECTOR_C,
95 SELECTOR,
96 TREATMENT_C,
97 TREATMENT,
Simon Hunt3d1b0652015-05-05 17:27:24 -070098 };
99
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700100 @Override
Simon Huntda580882015-05-12 20:58:18 -0700101 protected Collection<RequestHandler> createRequestHandlers() {
Viswanath KSPd1212c72016-10-21 01:03:35 +0530102 return ImmutableSet.of(
103 new FlowDataRequest(),
104 new DetailRequestHandler()
105 );
Simon Huntd2747a02015-04-30 22:41:16 -0700106 }
107
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530108 private StringBuilder removeTrailingComma(StringBuilder sb) {
109 int pos = sb.lastIndexOf(COMMA);
110 sb.delete(pos, sb.length());
111 return sb;
112 }
113
Simon Huntabd16f62015-05-01 13:14:40 -0700114 // handler for flow table requests
115 private final class FlowDataRequest extends TableRequestHandler {
Simon Huntd2747a02015-04-30 22:41:16 -0700116
Jian Li69f66632016-01-15 12:27:42 -0800117 private static final String NO_ROWS_MESSAGE = "No flows found";
118
Simon Huntd2747a02015-04-30 22:41:16 -0700119 private FlowDataRequest() {
Simon Huntabd16f62015-05-01 13:14:40 -0700120 super(FLOW_DATA_REQ, FLOW_DATA_RESP, FLOWS);
Simon Huntd2747a02015-04-30 22:41:16 -0700121 }
122
123 @Override
Simon Hunt3d1b0652015-05-05 17:27:24 -0700124 protected String[] getColumnIds() {
125 return COL_IDS;
Simon Hunt44aa2f82015-04-30 15:01:35 -0700126 }
Simon Hunt44aa2f82015-04-30 15:01:35 -0700127
Simon Hunt3d1b0652015-05-05 17:27:24 -0700128 @Override
Jian Li8baf4472016-01-15 15:08:09 -0800129 protected String noRowsMessage(ObjectNode payload) {
Jian Li69f66632016-01-15 12:27:42 -0800130 return NO_ROWS_MESSAGE;
131 }
132
133 @Override
Simon Hunt3d1b0652015-05-05 17:27:24 -0700134 protected TableModel createTableModel() {
135 TableModel tm = super.createTableModel();
Simon Hunt3e4ccaf2016-01-12 19:59:54 -0800136 tm.setFormatter(ID, HexLongFormatter.INSTANCE);
Simon Huntbe60dde2016-01-13 12:26:56 -0800137 tm.setFormatter(STATE, EnumFormatter.INSTANCE);
Simon Huntbe60dde2016-01-13 12:26:56 -0800138 tm.setFormatter(BYTES, NumberFormatter.INTEGER);
Simon Hunt9bff5952017-07-13 14:05:09 -0700139 tm.setFormatter(PACKETS, NumberFormatter.INTEGER);
140 tm.setFormatter(DURATION, NumberFormatter.INTEGER);
141
142 tm.setFormatter(SELECTOR_C, new SelectorShortFormatter());
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700143 tm.setFormatter(SELECTOR, new SelectorFormatter());
Simon Hunt9bff5952017-07-13 14:05:09 -0700144 tm.setFormatter(TREATMENT_C, new TreatmentShortFormatter());
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700145 tm.setFormatter(TREATMENT, new TreatmentFormatter());
Simon Hunt3d1b0652015-05-05 17:27:24 -0700146 return tm;
147 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700148
Simon Hunt3d1b0652015-05-05 17:27:24 -0700149 @Override
150 protected void populateTable(TableModel tm, ObjectNode payload) {
151 String uri = string(payload, "devId");
152 if (!Strings.isNullOrEmpty(uri)) {
153 DeviceId deviceId = DeviceId.deviceId(uri);
154 FlowRuleService frs = get(FlowRuleService.class);
155 for (FlowEntry flow : frs.getFlowEntries(deviceId)) {
156 populateRow(tm.addRow(), flow);
157 }
158 }
159 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700160
Simon Hunt3d1b0652015-05-05 17:27:24 -0700161 private void populateRow(TableModel.Row row, FlowEntry flow) {
162 row.cell(ID, flow.id().value())
Simon Hunt9bff5952017-07-13 14:05:09 -0700163 .cell(STATE, flow.state())
164 .cell(BYTES, flow.bytes())
165 .cell(PACKETS, flow.packets())
166 .cell(DURATION, flow.life())
Simon Hunt8a0429a2017-01-06 16:52:47 -0800167 .cell(PRIORITY, flow.priority())
Simon Hunt9bff5952017-07-13 14:05:09 -0700168 .cell(TABLE_ID, flow.tableId())
169 .cell(APP_ID, flow.appId())
170
171 .cell(GROUP_ID, flow.groupId().id())
Simon Hunt8a0429a2017-01-06 16:52:47 -0800172 .cell(TIMEOUT, flow.timeout())
173 .cell(PERMANENT, flow.isPermanent())
Simon Hunt9bff5952017-07-13 14:05:09 -0700174
175 .cell(SELECTOR_C, flow)
Simon Hunt8a0429a2017-01-06 16:52:47 -0800176 .cell(SELECTOR, flow)
Simon Hunt9bff5952017-07-13 14:05:09 -0700177 .cell(TREATMENT_C, flow)
Simon Hunt8a0429a2017-01-06 16:52:47 -0800178 .cell(TREATMENT, flow);
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700179 }
180
Simon Hunt9bff5952017-07-13 14:05:09 -0700181
182 private class InternalSelectorFormatter implements CellFormatter {
183 private final boolean shortFormat;
184
185 InternalSelectorFormatter(boolean shortFormat) {
186 this.shortFormat = shortFormat;
187 }
188
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700189 @Override
190 public String format(Object value) {
191 FlowEntry flow = (FlowEntry) value;
192 Set<Criterion> criteria = flow.selector().criteria();
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700193
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700194 if (criteria.isEmpty()) {
195 return "(No traffic selector criteria for this flow)";
196 }
Simon Hunt9bff5952017-07-13 14:05:09 -0700197
198 StringBuilder sb = new StringBuilder();
199 if (!shortFormat) {
200 sb.append("Criteria: ");
201 }
202
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700203 for (Criterion c : criteria) {
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700204 sb.append(c).append(COMMA);
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700205 }
206 removeTrailingComma(sb);
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700207
208 return sb.toString();
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700209 }
210 }
211
Simon Hunt9bff5952017-07-13 14:05:09 -0700212 private final class SelectorShortFormatter extends InternalSelectorFormatter {
213 SelectorShortFormatter() {
214 super(true);
215 }
216 }
217
218 private final class SelectorFormatter extends InternalSelectorFormatter {
219 SelectorFormatter() {
220 super(false);
221 }
222 }
223
224 private class InternalTreatmentFormatter implements CellFormatter {
225 private final boolean shortFormat;
226
227 InternalTreatmentFormatter(boolean shortFormat) {
228 this.shortFormat = shortFormat;
229 }
230
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700231 @Override
232 public String format(Object value) {
233 FlowEntry flow = (FlowEntry) value;
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530234 TrafficTreatment treatment = flow.treatment();
235 List<Instruction> imm = treatment.immediate();
236 List<Instruction> def = treatment.deferred();
237 if (imm.isEmpty() &&
238 def.isEmpty() &&
239 treatment.metered() == null &&
240 treatment.tableTransition() == null) {
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700241 return "(No traffic treatment instructions for this flow)";
242 }
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530243
Simon Hunt9bff5952017-07-13 14:05:09 -0700244 StringBuilder sb = new StringBuilder();
245
246 if (!shortFormat) {
247 sb.append("Treatment Instructions: ");
248 }
249
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530250 formatInstructs(sb, imm, "immediate:");
251 formatInstructs(sb, def, "deferred:");
252
253 if (treatment.metered() != null) {
254 sb.append("metered:")
255 .append(treatment.metered())
256 .append(COMMA);
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700257 }
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530258
259 if (treatment.tableTransition() != null) {
260 sb.append("transition:")
261 .append(treatment.tableTransition())
262 .append(COMMA);
Konstantinos Kanonakis845c3282016-04-01 17:34:20 -0500263 }
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530264
265 if (treatment.writeMetadata() != null) {
266 sb.append("metadata:")
267 .append(treatment.writeMetadata())
268 .append(COMMA);
Konstantinos Kanonakis845c3282016-04-01 17:34:20 -0500269 }
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530270
271 sb.append("cleared:").append(treatment.clearedDeferred());
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700272
273 return sb.toString();
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700274 }
275 }
276
Simon Hunt9bff5952017-07-13 14:05:09 -0700277 private final class TreatmentShortFormatter extends InternalTreatmentFormatter {
278 TreatmentShortFormatter() {
279 super(true);
280 }
281 }
282
283 private final class TreatmentFormatter extends InternalTreatmentFormatter {
284 TreatmentFormatter() {
285 super(false);
286 }
287 }
288
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530289 private void formatInstructs(StringBuilder sb,
290 List<Instruction> instructs,
291 String type) {
292 if (!instructs.isEmpty()) {
293 sb.append(type);
294 for (Instruction i : instructs) {
295 sb.append(i).append(COMMA);
296 }
297 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700298 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700299 }
Viswanath KSPd1212c72016-10-21 01:03:35 +0530300
301 private final class DetailRequestHandler extends RequestHandler {
302 private DetailRequestHandler() {
303 super(FLOW_DETAILS_REQ);
304 }
305
Bharath Thiruveedula99849dc2016-11-17 22:04:38 +0530306 private FlowEntry findFlowById(String appIdText, String flowId) {
Viswanath KSP70e0d142016-10-28 21:58:32 +0530307 String strippedFlowId = flowId.replaceAll(OX, EMPTY);
Viswanath KSPd1212c72016-10-21 01:03:35 +0530308 FlowRuleService fs = get(FlowRuleService.class);
309 int appIdInt = Integer.parseInt(appIdText);
Viswanath KSP70e0d142016-10-28 21:58:32 +0530310 ApplicationId appId = new DefaultApplicationId(appIdInt, DETAILS);
Bharath Thiruveedula99849dc2016-11-17 22:04:38 +0530311 Iterable<FlowEntry> entries = fs.getFlowEntriesById(appId);
Viswanath KSPd1212c72016-10-21 01:03:35 +0530312
Bharath Thiruveedula99849dc2016-11-17 22:04:38 +0530313 for (FlowEntry entry : entries) {
314 if (entry.id().toString().equals(strippedFlowId)) {
315 return entry;
Viswanath KSPd1212c72016-10-21 01:03:35 +0530316 }
317 }
318
319 return null;
320 }
321
Viswanath KSP70e0d142016-10-28 21:58:32 +0530322 private String decorateFlowId(FlowRule flow) {
323 return OX + flow.id();
324 }
325
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530326 private String decorateGroupId(FlowRule flow) {
327 return OX + flow.groupId().id();
328 }
329
330 private String getCriteriaString(FlowRule flow) {
331 Set<Criterion> criteria = flow.selector().criteria();
332 StringBuilder sb = new StringBuilder();
333 for (Criterion c : criteria) {
334 sb.append(c).append(COMMA);
335 }
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530336 removeTrailingComma(sb);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530337 return sb.toString();
338 }
339
340 private String getTreatmentString(FlowRule flow) {
341 List<Instruction> instructions = flow.treatment().allInstructions();
342 StringBuilder sb = new StringBuilder();
343 for (Instruction inst : instructions) {
344 sb.append(inst).append(COMMA);
345 }
346 if (flow.treatment().metered() != null) {
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530347 sb.append(flow.treatment().metered()).append(COMMA);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530348 }
349 if (flow.treatment().tableTransition() != null) {
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530350 sb.append(flow.treatment().tableTransition()).append(COMMA);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530351 }
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530352
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530353 removeTrailingComma(sb);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530354 return sb.toString();
355 }
356
Viswanath KSPd1212c72016-10-21 01:03:35 +0530357 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800358 public void process(ObjectNode payload) {
Viswanath KSPd1212c72016-10-21 01:03:35 +0530359
360 String flowId = string(payload, FLOW_ID);
361 String appId = string(payload, APP_ID);
Simon Hunt9bff5952017-07-13 14:05:09 -0700362
363 FlowEntry flow = findFlowById(appId, flowId);
Viswanath KSP70e0d142016-10-28 21:58:32 +0530364 if (flow != null) {
365 ObjectNode data = objectNode();
Viswanath KSPd1212c72016-10-21 01:03:35 +0530366
Viswanath KSP70e0d142016-10-28 21:58:32 +0530367 data.put(FLOW_ID, decorateFlowId(flow));
Simon Hunt9bff5952017-07-13 14:05:09 -0700368
369 // TODO: use formatters for these values..
370 data.put(STATE, flow.state().toString());
371 data.put(BYTES, flow.bytes());
372 data.put(PACKETS, flow.packets());
373 data.put(DURATION, flow.life());
374
Viswanath KSP70e0d142016-10-28 21:58:32 +0530375 data.put(FLOW_PRIORITY, flow.priority());
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530376 data.put(TABLE_ID, flow.tableId());
Simon Hunt9bff5952017-07-13 14:05:09 -0700377 data.put(APP_ID, flow.appId());
378
379 data.put(GROUP_ID, decorateGroupId(flow));
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530380 data.put(TIMEOUT, flow.hardTimeout());
381 data.put(PERMANENT, Boolean.toString(flow.isPermanent()));
Simon Hunt9bff5952017-07-13 14:05:09 -0700382
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530383 data.put(SELECTOR, getCriteriaString(flow));
384 data.put(TREATMENT, getTreatmentString(flow));
385
Viswanath KSP70e0d142016-10-28 21:58:32 +0530386 ObjectNode rootNode = objectNode();
387 rootNode.set(DETAILS, data);
388 sendMessage(FLOW_DETAILS_RESP, rootNode);
389 }
Viswanath KSPd1212c72016-10-21 01:03:35 +0530390 }
391 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700392}