blob: 8cb8d001552812f6e70861f7cf5211fd1220c6bb [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
Simon Hunt8f057ee2017-07-19 14:05:26 -070019import com.fasterxml.jackson.databind.node.ArrayNode;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070020import com.fasterxml.jackson.databind.node.ObjectNode;
Simon Huntabd16f62015-05-01 13:14:40 -070021import com.google.common.base.Strings;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070022import com.google.common.collect.ImmutableSet;
Simon Hunt36b658d2017-07-14 16:20:11 -070023import org.onosproject.app.ApplicationService;
24import org.onosproject.core.Application;
Viswanath KSPd1212c72016-10-21 01:03:35 +053025import org.onosproject.core.ApplicationId;
26import org.onosproject.core.DefaultApplicationId;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070027import org.onosproject.net.DeviceId;
28import org.onosproject.net.flow.FlowEntry;
Viswanath KSPd1212c72016-10-21 01:03:35 +053029import org.onosproject.net.flow.FlowRule;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070030import org.onosproject.net.flow.FlowRuleService;
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +053031import org.onosproject.net.flow.TrafficTreatment;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070032import org.onosproject.net.flow.criteria.Criterion;
33import org.onosproject.net.flow.instructions.Instruction;
Simon Hunt8f057ee2017-07-19 14:05:26 -070034import org.onosproject.net.flow.instructions.Instructions;
Simon Huntd2747a02015-04-30 22:41:16 -070035import org.onosproject.ui.RequestHandler;
Simon Hunta0ddb022015-05-01 09:53:01 -070036import org.onosproject.ui.UiMessageHandler;
Bri Prebilic Cole9467a232015-05-06 16:59:05 -070037import org.onosproject.ui.table.CellFormatter;
Simon Hunt3d1b0652015-05-05 17:27:24 -070038import org.onosproject.ui.table.TableModel;
Simon Huntabd16f62015-05-01 13:14:40 -070039import org.onosproject.ui.table.TableRequestHandler;
Bri Prebilic Cole9467a232015-05-06 16:59:05 -070040import org.onosproject.ui.table.cell.EnumFormatter;
Simon Hunt3e4ccaf2016-01-12 19:59:54 -080041import org.onosproject.ui.table.cell.HexLongFormatter;
Simon Huntbe60dde2016-01-13 12:26:56 -080042import org.onosproject.ui.table.cell.NumberFormatter;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070043
Simon Huntd2747a02015-04-30 22:41:16 -070044import java.util.Collection;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070045import java.util.List;
Simon Hunt36b658d2017-07-14 16:20:11 -070046import java.util.Map;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070047import java.util.Set;
Simon Hunt36b658d2017-07-14 16:20:11 -070048import java.util.stream.Collectors;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070049
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +053050
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070051/**
52 * Message handler for flow view related messages.
53 */
Simon Hunta0ddb022015-05-01 09:53:01 -070054public class FlowViewMessageHandler extends UiMessageHandler {
Simon Huntd2747a02015-04-30 22:41:16 -070055
56 private static final String FLOW_DATA_REQ = "flowDataRequest";
Simon Huntabd16f62015-05-01 13:14:40 -070057 private static final String FLOW_DATA_RESP = "flowDataResponse";
58 private static final String FLOWS = "flows";
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070059
Viswanath KSPd1212c72016-10-21 01:03:35 +053060 private static final String FLOW_DETAILS_REQ = "flowDetailsRequest";
61 private static final String FLOW_DETAILS_RESP = "flowDetailsResponse";
62 private static final String DETAILS = "details";
63 private static final String FLOW_PRIORITY = "priority";
64
Simon Hunt8f057ee2017-07-19 14:05:26 -070065 private static final String DEV_ID = "devId";
66
Simon Huntabd16f62015-05-01 13:14:40 -070067 private static final String ID = "id";
Viswanath KSPd1212c72016-10-21 01:03:35 +053068 private static final String FLOW_ID = "flowId";
Simon Huntabd16f62015-05-01 13:14:40 -070069 private static final String APP_ID = "appId";
Simon Hunt36b658d2017-07-14 16:20:11 -070070 private static final String APP_NAME = "appName";
Simon Huntabd16f62015-05-01 13:14:40 -070071 private static final String GROUP_ID = "groupId";
72 private static final String TABLE_ID = "tableId";
73 private static final String PRIORITY = "priority";
Simon Hunt9bff5952017-07-13 14:05:09 -070074 private static final String SELECTOR_C = "selector_c"; // for table column
Simon Huntabd16f62015-05-01 13:14:40 -070075 private static final String SELECTOR = "selector";
Simon Hunt9bff5952017-07-13 14:05:09 -070076 private static final String TREATMENT_C = "treatment_c"; // for table column
Simon Huntabd16f62015-05-01 13:14:40 -070077 private static final String TREATMENT = "treatment";
78 private static final String TIMEOUT = "timeout";
79 private static final String PERMANENT = "permanent";
80 private static final String STATE = "state";
Bri Prebilic Cole641b97b2015-05-05 14:47:40 -070081 private static final String PACKETS = "packets";
Simon Hunt9bff5952017-07-13 14:05:09 -070082 private static final String DURATION = "duration";
Bri Prebilic Cole641b97b2015-05-05 14:47:40 -070083 private static final String BYTES = "bytes";
Simon Huntabd16f62015-05-01 13:14:40 -070084
85 private static final String COMMA = ", ";
Viswanath KSP70e0d142016-10-28 21:58:32 +053086 private static final String OX = "0x";
87 private static final String EMPTY = "";
Simon Hunt8f057ee2017-07-19 14:05:26 -070088 private static final String SPACE = " ";
89 private static final String COLON = ":";
90 private static final String ANGLE_O = "<";
91 private static final String ANGLE_C = ">";
92 private static final String SQUARE_O = "[";
93 private static final String SQUARE_C = "]";
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070094
Simon Hunt36b658d2017-07-14 16:20:11 -070095 private static final String ONOS_PREFIX = "org.onosproject.";
96 private static final String ONOS_MARKER = "*";
97
Simon Hunt8f057ee2017-07-19 14:05:26 -070098 // TODO: replace the use of the following constants with localized text
99 private static final String MSG_NO_SELECTOR =
100 "(No traffic selector criteria for this flow)";
101 private static final String MSG_NO_TREATMENT =
102 "(No traffic treatment instructions for this flow)";
103 private static final String NO_ROWS_NO_FLOWS = "No flows found";
104
105 private static final String CRITERIA = "Criteria";
106 private static final String TREATMENT_INSTRUCTIONS = "Treatment Instructions";
107 private static final String IMM = "imm";
108 private static final String DEF = "def";
109 private static final String METERED = "metered";
110 private static final String TRANSITION = "transition";
111 private static final String METADATA = "metadata";
112 private static final String CLEARED = "cleared";
113 private static final String UNKNOWN = "Unknown";
114
115
Simon Hunt3d1b0652015-05-05 17:27:24 -0700116 private static final String[] COL_IDS = {
Simon Hunt9bff5952017-07-13 14:05:09 -0700117 ID,
118 STATE,
119 BYTES,
120 PACKETS,
121 DURATION,
122 PRIORITY,
123 TABLE_ID,
124 APP_ID,
Simon Hunt36b658d2017-07-14 16:20:11 -0700125 APP_NAME,
Simon Hunt9bff5952017-07-13 14:05:09 -0700126
127 GROUP_ID,
128 TIMEOUT,
129 PERMANENT,
130
131 SELECTOR_C,
132 SELECTOR,
133 TREATMENT_C,
134 TREATMENT,
Simon Hunt3d1b0652015-05-05 17:27:24 -0700135 };
136
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700137 @Override
Simon Huntda580882015-05-12 20:58:18 -0700138 protected Collection<RequestHandler> createRequestHandlers() {
Viswanath KSPd1212c72016-10-21 01:03:35 +0530139 return ImmutableSet.of(
140 new FlowDataRequest(),
141 new DetailRequestHandler()
142 );
Simon Huntd2747a02015-04-30 22:41:16 -0700143 }
144
Simon Hunt8f057ee2017-07-19 14:05:26 -0700145 private void removeTrailingComma(StringBuilder sb) {
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530146 int pos = sb.lastIndexOf(COMMA);
147 sb.delete(pos, sb.length());
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530148 }
149
Simon Hunt36b658d2017-07-14 16:20:11 -0700150 // Generate a map of shorts->application IDs
151 // (working around deficiency(?) in Application Service API)
152 private Map<Short, ApplicationId> appShortMap() {
153 Set<Application> apps =
154 get(ApplicationService.class).getApplications();
155
156 return apps.stream()
157 .collect(Collectors.toMap(a -> a.id().id(), Application::id));
158 }
159
160 // Return an application name, based on a lookup of the internal short ID
161 private String makeAppName(short id, Map<Short, ApplicationId> lookup) {
162 ApplicationId appId = lookup.get(id);
163 if (appId == null) {
Simon Hunt8f057ee2017-07-19 14:05:26 -0700164 return UNKNOWN + SPACE + ANGLE_O + id + ANGLE_C;
Simon Hunt36b658d2017-07-14 16:20:11 -0700165 }
166 String appName = appId.name();
167 return appName.startsWith(ONOS_PREFIX)
168 ? appName.replaceFirst(ONOS_PREFIX, ONOS_MARKER) : appName;
169 }
170
Simon Huntabd16f62015-05-01 13:14:40 -0700171 // handler for flow table requests
172 private final class FlowDataRequest extends TableRequestHandler {
Simon Huntd2747a02015-04-30 22:41:16 -0700173
174 private FlowDataRequest() {
Simon Huntabd16f62015-05-01 13:14:40 -0700175 super(FLOW_DATA_REQ, FLOW_DATA_RESP, FLOWS);
Simon Huntd2747a02015-04-30 22:41:16 -0700176 }
177
178 @Override
Simon Hunt3d1b0652015-05-05 17:27:24 -0700179 protected String[] getColumnIds() {
180 return COL_IDS;
Simon Hunt44aa2f82015-04-30 15:01:35 -0700181 }
Simon Hunt44aa2f82015-04-30 15:01:35 -0700182
Simon Hunt3d1b0652015-05-05 17:27:24 -0700183 @Override
Jian Li8baf4472016-01-15 15:08:09 -0800184 protected String noRowsMessage(ObjectNode payload) {
Simon Hunt8f057ee2017-07-19 14:05:26 -0700185 return NO_ROWS_NO_FLOWS;
Jian Li69f66632016-01-15 12:27:42 -0800186 }
187
188 @Override
Simon Hunt3d1b0652015-05-05 17:27:24 -0700189 protected TableModel createTableModel() {
190 TableModel tm = super.createTableModel();
Simon Hunt3e4ccaf2016-01-12 19:59:54 -0800191 tm.setFormatter(ID, HexLongFormatter.INSTANCE);
Simon Huntbe60dde2016-01-13 12:26:56 -0800192 tm.setFormatter(STATE, EnumFormatter.INSTANCE);
Simon Huntbe60dde2016-01-13 12:26:56 -0800193 tm.setFormatter(BYTES, NumberFormatter.INTEGER);
Simon Hunt9bff5952017-07-13 14:05:09 -0700194 tm.setFormatter(PACKETS, NumberFormatter.INTEGER);
195 tm.setFormatter(DURATION, NumberFormatter.INTEGER);
196
197 tm.setFormatter(SELECTOR_C, new SelectorShortFormatter());
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700198 tm.setFormatter(SELECTOR, new SelectorFormatter());
Simon Hunt9bff5952017-07-13 14:05:09 -0700199 tm.setFormatter(TREATMENT_C, new TreatmentShortFormatter());
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700200 tm.setFormatter(TREATMENT, new TreatmentFormatter());
Simon Hunt3d1b0652015-05-05 17:27:24 -0700201 return tm;
202 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700203
Simon Hunt3d1b0652015-05-05 17:27:24 -0700204 @Override
205 protected void populateTable(TableModel tm, ObjectNode payload) {
Simon Hunt8f057ee2017-07-19 14:05:26 -0700206 String uri = string(payload, DEV_ID);
Simon Hunt3d1b0652015-05-05 17:27:24 -0700207 if (!Strings.isNullOrEmpty(uri)) {
208 DeviceId deviceId = DeviceId.deviceId(uri);
Simon Hunt36b658d2017-07-14 16:20:11 -0700209 Map<Short, ApplicationId> lookup = appShortMap();
Simon Hunt3d1b0652015-05-05 17:27:24 -0700210 FlowRuleService frs = get(FlowRuleService.class);
Simon Hunt36b658d2017-07-14 16:20:11 -0700211
Simon Hunt3d1b0652015-05-05 17:27:24 -0700212 for (FlowEntry flow : frs.getFlowEntries(deviceId)) {
Simon Hunt36b658d2017-07-14 16:20:11 -0700213 populateRow(tm.addRow(), flow, lookup);
Simon Hunt3d1b0652015-05-05 17:27:24 -0700214 }
215 }
216 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700217
Simon Hunt36b658d2017-07-14 16:20:11 -0700218 private void populateRow(TableModel.Row row, FlowEntry flow,
219 Map<Short, ApplicationId> lookup) {
Simon Hunt3d1b0652015-05-05 17:27:24 -0700220 row.cell(ID, flow.id().value())
Simon Hunt9bff5952017-07-13 14:05:09 -0700221 .cell(STATE, flow.state())
222 .cell(BYTES, flow.bytes())
223 .cell(PACKETS, flow.packets())
224 .cell(DURATION, flow.life())
Simon Hunt8a0429a2017-01-06 16:52:47 -0800225 .cell(PRIORITY, flow.priority())
Simon Hunt9bff5952017-07-13 14:05:09 -0700226 .cell(TABLE_ID, flow.tableId())
227 .cell(APP_ID, flow.appId())
Simon Hunt36b658d2017-07-14 16:20:11 -0700228 .cell(APP_NAME, makeAppName(flow.appId(), lookup))
Simon Hunt9bff5952017-07-13 14:05:09 -0700229
230 .cell(GROUP_ID, flow.groupId().id())
Simon Hunt8a0429a2017-01-06 16:52:47 -0800231 .cell(TIMEOUT, flow.timeout())
232 .cell(PERMANENT, flow.isPermanent())
Simon Hunt9bff5952017-07-13 14:05:09 -0700233
234 .cell(SELECTOR_C, flow)
Simon Hunt8a0429a2017-01-06 16:52:47 -0800235 .cell(SELECTOR, flow)
Simon Hunt9bff5952017-07-13 14:05:09 -0700236 .cell(TREATMENT_C, flow)
Simon Hunt8a0429a2017-01-06 16:52:47 -0800237 .cell(TREATMENT, flow);
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700238 }
239
Simon Hunt9bff5952017-07-13 14:05:09 -0700240 private class InternalSelectorFormatter implements CellFormatter {
241 private final boolean shortFormat;
242
243 InternalSelectorFormatter(boolean shortFormat) {
244 this.shortFormat = shortFormat;
245 }
246
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700247 @Override
248 public String format(Object value) {
249 FlowEntry flow = (FlowEntry) value;
250 Set<Criterion> criteria = flow.selector().criteria();
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700251
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700252 if (criteria.isEmpty()) {
Simon Hunt8f057ee2017-07-19 14:05:26 -0700253 return MSG_NO_SELECTOR;
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700254 }
Simon Hunt9bff5952017-07-13 14:05:09 -0700255
256 StringBuilder sb = new StringBuilder();
257 if (!shortFormat) {
Simon Hunt8f057ee2017-07-19 14:05:26 -0700258 sb.append(CRITERIA).append(COLON).append(SPACE);
Simon Hunt9bff5952017-07-13 14:05:09 -0700259 }
260
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700261 for (Criterion c : criteria) {
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700262 sb.append(c).append(COMMA);
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700263 }
264 removeTrailingComma(sb);
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700265
266 return sb.toString();
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700267 }
268 }
269
Simon Hunt9bff5952017-07-13 14:05:09 -0700270 private final class SelectorShortFormatter extends InternalSelectorFormatter {
271 SelectorShortFormatter() {
272 super(true);
273 }
274 }
275
276 private final class SelectorFormatter extends InternalSelectorFormatter {
277 SelectorFormatter() {
278 super(false);
279 }
280 }
281
282 private class InternalTreatmentFormatter implements CellFormatter {
283 private final boolean shortFormat;
284
285 InternalTreatmentFormatter(boolean shortFormat) {
286 this.shortFormat = shortFormat;
287 }
288
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700289 @Override
290 public String format(Object value) {
291 FlowEntry flow = (FlowEntry) value;
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530292 TrafficTreatment treatment = flow.treatment();
293 List<Instruction> imm = treatment.immediate();
294 List<Instruction> def = treatment.deferred();
295 if (imm.isEmpty() &&
296 def.isEmpty() &&
297 treatment.metered() == null &&
Simon Hunt8f057ee2017-07-19 14:05:26 -0700298 treatment.tableTransition() == null &&
299 treatment.writeMetadata() == null) {
300 return MSG_NO_TREATMENT;
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700301 }
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530302
Simon Hunt9bff5952017-07-13 14:05:09 -0700303 StringBuilder sb = new StringBuilder();
304
305 if (!shortFormat) {
Simon Hunt8f057ee2017-07-19 14:05:26 -0700306 sb.append(TREATMENT_INSTRUCTIONS).append(COLON).append(SPACE);
Simon Hunt9bff5952017-07-13 14:05:09 -0700307 }
308
Simon Hunt8f057ee2017-07-19 14:05:26 -0700309 formatInstructs(sb, imm, IMM);
310 formatInstructs(sb, def, DEF);
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530311
Simon Hunt8f057ee2017-07-19 14:05:26 -0700312 addLabVal(sb, METERED, treatment.metered());
313 addLabVal(sb, TRANSITION, treatment.tableTransition());
314 addLabVal(sb, METADATA, treatment.writeMetadata());
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530315
Simon Hunt8f057ee2017-07-19 14:05:26 -0700316 sb.append(CLEARED).append(COLON)
317 .append(treatment.clearedDeferred());
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700318
319 return sb.toString();
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700320 }
Simon Hunt8f057ee2017-07-19 14:05:26 -0700321
322 private void addLabVal(StringBuilder sb, String label, Instruction value) {
323 if (value != null) {
324 sb.append(label).append(COLON).append(value).append(COMMA);
325 }
326 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700327 }
328
Simon Hunt9bff5952017-07-13 14:05:09 -0700329 private final class TreatmentShortFormatter extends InternalTreatmentFormatter {
330 TreatmentShortFormatter() {
331 super(true);
332 }
333 }
334
335 private final class TreatmentFormatter extends InternalTreatmentFormatter {
336 TreatmentFormatter() {
337 super(false);
338 }
339 }
340
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530341 private void formatInstructs(StringBuilder sb,
342 List<Instruction> instructs,
343 String type) {
344 if (!instructs.isEmpty()) {
Simon Hunt8f057ee2017-07-19 14:05:26 -0700345 sb.append(type).append(SQUARE_O);
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530346 for (Instruction i : instructs) {
347 sb.append(i).append(COMMA);
348 }
Simon Hunt8f057ee2017-07-19 14:05:26 -0700349 removeTrailingComma(sb);
350 sb.append(SQUARE_C).append(COMMA);
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530351 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700352 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700353 }
Viswanath KSPd1212c72016-10-21 01:03:35 +0530354
355 private final class DetailRequestHandler extends RequestHandler {
356 private DetailRequestHandler() {
357 super(FLOW_DETAILS_REQ);
358 }
359
Bharath Thiruveedula99849dc2016-11-17 22:04:38 +0530360 private FlowEntry findFlowById(String appIdText, String flowId) {
Viswanath KSP70e0d142016-10-28 21:58:32 +0530361 String strippedFlowId = flowId.replaceAll(OX, EMPTY);
Viswanath KSPd1212c72016-10-21 01:03:35 +0530362 FlowRuleService fs = get(FlowRuleService.class);
363 int appIdInt = Integer.parseInt(appIdText);
Viswanath KSP70e0d142016-10-28 21:58:32 +0530364 ApplicationId appId = new DefaultApplicationId(appIdInt, DETAILS);
Bharath Thiruveedula99849dc2016-11-17 22:04:38 +0530365 Iterable<FlowEntry> entries = fs.getFlowEntriesById(appId);
Viswanath KSPd1212c72016-10-21 01:03:35 +0530366
Bharath Thiruveedula99849dc2016-11-17 22:04:38 +0530367 for (FlowEntry entry : entries) {
368 if (entry.id().toString().equals(strippedFlowId)) {
369 return entry;
Viswanath KSPd1212c72016-10-21 01:03:35 +0530370 }
371 }
372
373 return null;
374 }
375
Viswanath KSP70e0d142016-10-28 21:58:32 +0530376 private String decorateFlowId(FlowRule flow) {
377 return OX + flow.id();
378 }
379
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530380 private String decorateGroupId(FlowRule flow) {
381 return OX + flow.groupId().id();
382 }
383
Viswanath KSPd1212c72016-10-21 01:03:35 +0530384 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800385 public void process(ObjectNode payload) {
Viswanath KSPd1212c72016-10-21 01:03:35 +0530386
387 String flowId = string(payload, FLOW_ID);
388 String appId = string(payload, APP_ID);
Simon Hunt9bff5952017-07-13 14:05:09 -0700389
390 FlowEntry flow = findFlowById(appId, flowId);
Viswanath KSP70e0d142016-10-28 21:58:32 +0530391 if (flow != null) {
392 ObjectNode data = objectNode();
Viswanath KSPd1212c72016-10-21 01:03:35 +0530393
Viswanath KSP70e0d142016-10-28 21:58:32 +0530394 data.put(FLOW_ID, decorateFlowId(flow));
Simon Hunt9bff5952017-07-13 14:05:09 -0700395
Simon Hunt8f057ee2017-07-19 14:05:26 -0700396 data.put(STATE, EnumFormatter.INSTANCE.format(flow.state()));
397 data.put(BYTES, NumberFormatter.INTEGER.format(flow.bytes()));
398 data.put(PACKETS, NumberFormatter.INTEGER.format(flow.packets()));
399 data.put(DURATION, NumberFormatter.INTEGER.format(flow.life()));
Simon Hunt9bff5952017-07-13 14:05:09 -0700400
Viswanath KSP70e0d142016-10-28 21:58:32 +0530401 data.put(FLOW_PRIORITY, flow.priority());
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530402 data.put(TABLE_ID, flow.tableId());
Simon Hunt9bff5952017-07-13 14:05:09 -0700403 data.put(APP_ID, flow.appId());
Simon Hunt36b658d2017-07-14 16:20:11 -0700404 // NOTE: horribly inefficient... make a map and retrieve a single value...
405 data.put(APP_NAME, makeAppName(flow.appId(), appShortMap()));
Simon Hunt9bff5952017-07-13 14:05:09 -0700406
407 data.put(GROUP_ID, decorateGroupId(flow));
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530408 data.put(TIMEOUT, flow.hardTimeout());
Simon Hunt8f057ee2017-07-19 14:05:26 -0700409 data.put(PERMANENT, flow.isPermanent());
Simon Hunt9bff5952017-07-13 14:05:09 -0700410
Simon Hunt8f057ee2017-07-19 14:05:26 -0700411 data.set(SELECTOR, jsonCriteria(flow));
412 data.set(TREATMENT, jsonTreatment(flow));
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530413
Viswanath KSP70e0d142016-10-28 21:58:32 +0530414 ObjectNode rootNode = objectNode();
415 rootNode.set(DETAILS, data);
416 sendMessage(FLOW_DETAILS_RESP, rootNode);
417 }
Viswanath KSPd1212c72016-10-21 01:03:35 +0530418 }
Simon Hunt8f057ee2017-07-19 14:05:26 -0700419
420 private ArrayNode jsonCriteria(FlowEntry flow) {
421 ArrayNode crits = arrayNode();
422 for (Criterion c : flow.selector().criteria()) {
423 crits.add(c.toString());
424 }
425 return crits;
426 }
427
428 private ObjectNode jsonTreatment(FlowEntry flow) {
429 ObjectNode treat = objectNode();
430 TrafficTreatment treatment = flow.treatment();
431 List<Instruction> imm = treatment.immediate();
432 List<Instruction> def = treatment.deferred();
433 Instructions.MeterInstruction meter = treatment.metered();
434 Instructions.TableTypeTransition table = treatment.tableTransition();
435 Instructions.MetadataInstruction meta = treatment.writeMetadata();
436
437 if (!imm.isEmpty()) {
438 treat.set(IMMED, jsonInstrList(imm));
439 }
440 if (!def.isEmpty()) {
441 treat.set(DEFER, jsonInstrList(def));
442 }
443 if (meter != null) {
444 treat.put(METER, meter.toString());
445 }
446 if (table != null) {
447 treat.put(TABLE, table.toString());
448 }
449 if (meta != null) {
450 treat.put(META, meta.toString());
451 }
452 treat.put(CLEARDEF, treatment.clearedDeferred());
453 return treat;
454 }
455
456 private ArrayNode jsonInstrList(List<Instruction> instructions) {
457 ArrayNode array = arrayNode();
458 for (Instruction i : instructions) {
459 array.add(i.toString());
460 }
461 return array;
462 }
Viswanath KSPd1212c72016-10-21 01:03:35 +0530463 }
Simon Hunt8f057ee2017-07-19 14:05:26 -0700464
465 // json structure keys
466 private static final String IMMED = "immed";
467 private static final String DEFER = "defer";
468 private static final String METER = "meter";
469 private static final String TABLE = "table";
470 private static final String META = "meta";
471 private static final String CLEARDEF = "clearDef";
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700472}