blob: a5c7a606cb9606c297870e61c9a3135371772669 [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.HexFormatter;
38import org.onosproject.ui.table.cell.HexLongFormatter;
Simon Huntbe60dde2016-01-13 12:26:56 -080039import org.onosproject.ui.table.cell.NumberFormatter;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070040
Simon Huntd2747a02015-04-30 22:41:16 -070041import java.util.Collection;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070042import java.util.List;
43import java.util.Set;
44
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +053045
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070046/**
47 * Message handler for flow view related messages.
48 */
Simon Hunta0ddb022015-05-01 09:53:01 -070049public class FlowViewMessageHandler extends UiMessageHandler {
Simon Huntd2747a02015-04-30 22:41:16 -070050
51 private static final String FLOW_DATA_REQ = "flowDataRequest";
Simon Huntabd16f62015-05-01 13:14:40 -070052 private static final String FLOW_DATA_RESP = "flowDataResponse";
53 private static final String FLOWS = "flows";
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070054
Viswanath KSPd1212c72016-10-21 01:03:35 +053055 private static final String FLOW_DETAILS_REQ = "flowDetailsRequest";
56 private static final String FLOW_DETAILS_RESP = "flowDetailsResponse";
57 private static final String DETAILS = "details";
58 private static final String FLOW_PRIORITY = "priority";
59
Simon Huntabd16f62015-05-01 13:14:40 -070060 private static final String ID = "id";
Viswanath KSPd1212c72016-10-21 01:03:35 +053061 private static final String FLOW_ID = "flowId";
Simon Huntabd16f62015-05-01 13:14:40 -070062 private static final String APP_ID = "appId";
63 private static final String GROUP_ID = "groupId";
64 private static final String TABLE_ID = "tableId";
65 private static final String PRIORITY = "priority";
66 private static final String SELECTOR = "selector";
67 private static final String TREATMENT = "treatment";
68 private static final String TIMEOUT = "timeout";
69 private static final String PERMANENT = "permanent";
70 private static final String STATE = "state";
Bri Prebilic Cole641b97b2015-05-05 14:47:40 -070071 private static final String PACKETS = "packets";
72 private static final String BYTES = "bytes";
Simon Huntabd16f62015-05-01 13:14:40 -070073
74 private static final String COMMA = ", ";
Viswanath KSP70e0d142016-10-28 21:58:32 +053075 private static final String OX = "0x";
76 private static final String EMPTY = "";
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070077
Simon Hunt3d1b0652015-05-05 17:27:24 -070078 private static final String[] COL_IDS = {
79 ID, APP_ID, GROUP_ID, TABLE_ID, PRIORITY, SELECTOR,
80 TREATMENT, TIMEOUT, PERMANENT, STATE, PACKETS, BYTES
81 };
82
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070083 @Override
Simon Huntda580882015-05-12 20:58:18 -070084 protected Collection<RequestHandler> createRequestHandlers() {
Viswanath KSPd1212c72016-10-21 01:03:35 +053085 return ImmutableSet.of(
86 new FlowDataRequest(),
87 new DetailRequestHandler()
88 );
Simon Huntd2747a02015-04-30 22:41:16 -070089 }
90
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +053091 private StringBuilder removeTrailingComma(StringBuilder sb) {
92 int pos = sb.lastIndexOf(COMMA);
93 sb.delete(pos, sb.length());
94 return sb;
95 }
96
Simon Huntabd16f62015-05-01 13:14:40 -070097 // handler for flow table requests
98 private final class FlowDataRequest extends TableRequestHandler {
Simon Huntd2747a02015-04-30 22:41:16 -070099
Jian Li69f66632016-01-15 12:27:42 -0800100 private static final String NO_ROWS_MESSAGE = "No flows found";
101
Simon Huntd2747a02015-04-30 22:41:16 -0700102 private FlowDataRequest() {
Simon Huntabd16f62015-05-01 13:14:40 -0700103 super(FLOW_DATA_REQ, FLOW_DATA_RESP, FLOWS);
Simon Huntd2747a02015-04-30 22:41:16 -0700104 }
105
106 @Override
Simon Hunt3d1b0652015-05-05 17:27:24 -0700107 protected String[] getColumnIds() {
108 return COL_IDS;
Simon Hunt44aa2f82015-04-30 15:01:35 -0700109 }
Simon Hunt44aa2f82015-04-30 15:01:35 -0700110
Simon Hunt3d1b0652015-05-05 17:27:24 -0700111 @Override
Jian Li8baf4472016-01-15 15:08:09 -0800112 protected String noRowsMessage(ObjectNode payload) {
Jian Li69f66632016-01-15 12:27:42 -0800113 return NO_ROWS_MESSAGE;
114 }
115
116 @Override
Simon Hunt3d1b0652015-05-05 17:27:24 -0700117 protected TableModel createTableModel() {
118 TableModel tm = super.createTableModel();
Simon Hunt3e4ccaf2016-01-12 19:59:54 -0800119 tm.setFormatter(ID, HexLongFormatter.INSTANCE);
120 tm.setFormatter(GROUP_ID, HexFormatter.INSTANCE);
Simon Huntbe60dde2016-01-13 12:26:56 -0800121 tm.setFormatter(STATE, EnumFormatter.INSTANCE);
122 tm.setFormatter(PACKETS, NumberFormatter.INTEGER);
123 tm.setFormatter(BYTES, NumberFormatter.INTEGER);
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700124 tm.setFormatter(SELECTOR, new SelectorFormatter());
125 tm.setFormatter(TREATMENT, new TreatmentFormatter());
Simon Hunt3d1b0652015-05-05 17:27:24 -0700126 return tm;
127 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700128
Simon Hunt3d1b0652015-05-05 17:27:24 -0700129 @Override
130 protected void populateTable(TableModel tm, ObjectNode payload) {
131 String uri = string(payload, "devId");
132 if (!Strings.isNullOrEmpty(uri)) {
133 DeviceId deviceId = DeviceId.deviceId(uri);
134 FlowRuleService frs = get(FlowRuleService.class);
135 for (FlowEntry flow : frs.getFlowEntries(deviceId)) {
136 populateRow(tm.addRow(), flow);
137 }
138 }
139 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700140
Simon Hunt3d1b0652015-05-05 17:27:24 -0700141 private void populateRow(TableModel.Row row, FlowEntry flow) {
142 row.cell(ID, flow.id().value())
Simon Hunt8a0429a2017-01-06 16:52:47 -0800143 .cell(APP_ID, flow.appId())
144 .cell(GROUP_ID, flow.groupId().id())
145 .cell(TABLE_ID, flow.tableId())
146 .cell(PRIORITY, flow.priority())
147 .cell(TIMEOUT, flow.timeout())
148 .cell(PERMANENT, flow.isPermanent())
149 .cell(STATE, flow.state())
150 .cell(PACKETS, flow.packets())
151 .cell(BYTES, flow.bytes())
152 .cell(SELECTOR, flow)
153 .cell(TREATMENT, flow);
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700154 }
155
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700156 private final class SelectorFormatter implements CellFormatter {
157 @Override
158 public String format(Object value) {
159 FlowEntry flow = (FlowEntry) value;
160 Set<Criterion> criteria = flow.selector().criteria();
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700161
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700162 if (criteria.isEmpty()) {
163 return "(No traffic selector criteria for this flow)";
164 }
165 StringBuilder sb = new StringBuilder("Criteria: ");
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700166 for (Criterion c : criteria) {
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700167 sb.append(c).append(COMMA);
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700168 }
169 removeTrailingComma(sb);
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700170
171 return sb.toString();
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700172 }
173 }
174
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700175 private final class TreatmentFormatter implements CellFormatter {
176 @Override
177 public String format(Object value) {
178 FlowEntry flow = (FlowEntry) value;
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530179 TrafficTreatment treatment = flow.treatment();
180 List<Instruction> imm = treatment.immediate();
181 List<Instruction> def = treatment.deferred();
182 if (imm.isEmpty() &&
183 def.isEmpty() &&
184 treatment.metered() == null &&
185 treatment.tableTransition() == null) {
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700186 return "(No traffic treatment instructions for this flow)";
187 }
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530188
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700189 StringBuilder sb = new StringBuilder("Treatment Instructions: ");
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530190 formatInstructs(sb, imm, "immediate:");
191 formatInstructs(sb, def, "deferred:");
192
193 if (treatment.metered() != null) {
194 sb.append("metered:")
195 .append(treatment.metered())
196 .append(COMMA);
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700197 }
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530198
199 if (treatment.tableTransition() != null) {
200 sb.append("transition:")
201 .append(treatment.tableTransition())
202 .append(COMMA);
Konstantinos Kanonakis845c3282016-04-01 17:34:20 -0500203 }
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530204
205 if (treatment.writeMetadata() != null) {
206 sb.append("metadata:")
207 .append(treatment.writeMetadata())
208 .append(COMMA);
Konstantinos Kanonakis845c3282016-04-01 17:34:20 -0500209 }
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530210
211 sb.append("cleared:").append(treatment.clearedDeferred());
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700212
213 return sb.toString();
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700214 }
215 }
216
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530217 private void formatInstructs(StringBuilder sb,
218 List<Instruction> instructs,
219 String type) {
220 if (!instructs.isEmpty()) {
221 sb.append(type);
222 for (Instruction i : instructs) {
223 sb.append(i).append(COMMA);
224 }
225 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700226 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700227 }
Viswanath KSPd1212c72016-10-21 01:03:35 +0530228
229 private final class DetailRequestHandler extends RequestHandler {
230 private DetailRequestHandler() {
231 super(FLOW_DETAILS_REQ);
232 }
233
Bharath Thiruveedula99849dc2016-11-17 22:04:38 +0530234 private FlowEntry findFlowById(String appIdText, String flowId) {
Viswanath KSP70e0d142016-10-28 21:58:32 +0530235 String strippedFlowId = flowId.replaceAll(OX, EMPTY);
Viswanath KSPd1212c72016-10-21 01:03:35 +0530236 FlowRuleService fs = get(FlowRuleService.class);
237 int appIdInt = Integer.parseInt(appIdText);
Viswanath KSP70e0d142016-10-28 21:58:32 +0530238 ApplicationId appId = new DefaultApplicationId(appIdInt, DETAILS);
Bharath Thiruveedula99849dc2016-11-17 22:04:38 +0530239 Iterable<FlowEntry> entries = fs.getFlowEntriesById(appId);
Viswanath KSPd1212c72016-10-21 01:03:35 +0530240
Bharath Thiruveedula99849dc2016-11-17 22:04:38 +0530241 for (FlowEntry entry : entries) {
242 if (entry.id().toString().equals(strippedFlowId)) {
243 return entry;
Viswanath KSPd1212c72016-10-21 01:03:35 +0530244 }
245 }
246
247 return null;
248 }
249
Viswanath KSP70e0d142016-10-28 21:58:32 +0530250 private String decorateFlowId(FlowRule flow) {
251 return OX + flow.id();
252 }
253
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530254 private String decorateGroupId(FlowRule flow) {
255 return OX + flow.groupId().id();
256 }
257
258 private String getCriteriaString(FlowRule flow) {
259 Set<Criterion> criteria = flow.selector().criteria();
260 StringBuilder sb = new StringBuilder();
261 for (Criterion c : criteria) {
262 sb.append(c).append(COMMA);
263 }
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530264 removeTrailingComma(sb);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530265 return sb.toString();
266 }
267
268 private String getTreatmentString(FlowRule flow) {
269 List<Instruction> instructions = flow.treatment().allInstructions();
270 StringBuilder sb = new StringBuilder();
271 for (Instruction inst : instructions) {
272 sb.append(inst).append(COMMA);
273 }
274 if (flow.treatment().metered() != null) {
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530275 sb.append(flow.treatment().metered()).append(COMMA);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530276 }
277 if (flow.treatment().tableTransition() != null) {
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530278 sb.append(flow.treatment().tableTransition()).append(COMMA);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530279 }
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530280
Deepa Vaddireddyf3932c02017-02-09 17:32:28 +0530281 removeTrailingComma(sb);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530282 return sb.toString();
283 }
284
Viswanath KSPd1212c72016-10-21 01:03:35 +0530285 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800286 public void process(ObjectNode payload) {
Viswanath KSPd1212c72016-10-21 01:03:35 +0530287
288 String flowId = string(payload, FLOW_ID);
289 String appId = string(payload, APP_ID);
290 FlowRule flow = findFlowById(appId, flowId);
Viswanath KSP70e0d142016-10-28 21:58:32 +0530291 if (flow != null) {
292 ObjectNode data = objectNode();
Viswanath KSPd1212c72016-10-21 01:03:35 +0530293
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530294
Viswanath KSP70e0d142016-10-28 21:58:32 +0530295 data.put(FLOW_ID, decorateFlowId(flow));
296 data.put(FLOW_PRIORITY, flow.priority());
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530297 data.put(GROUP_ID, decorateGroupId(flow));
298 data.put(APP_ID, flow.appId());
299 data.put(TABLE_ID, flow.tableId());
300 data.put(TIMEOUT, flow.hardTimeout());
301 data.put(PERMANENT, Boolean.toString(flow.isPermanent()));
302 data.put(SELECTOR, getCriteriaString(flow));
303 data.put(TREATMENT, getTreatmentString(flow));
304
Viswanath KSPd1212c72016-10-21 01:03:35 +0530305
Viswanath KSP70e0d142016-10-28 21:58:32 +0530306 //TODO put more detail info to data
Viswanath KSPd1212c72016-10-21 01:03:35 +0530307
Viswanath KSP70e0d142016-10-28 21:58:32 +0530308 ObjectNode rootNode = objectNode();
309 rootNode.set(DETAILS, data);
310 sendMessage(FLOW_DETAILS_RESP, rootNode);
311 }
Viswanath KSPd1212c72016-10-21 01:03:35 +0530312 }
313 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700314}