blob: 9a1c085e9cd5674dbf48f8ce2cd049fe1d46c70d [file] [log] [blame]
Thomas Vachuska7d693f52014-10-21 19:17:57 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
alshabib9290eea2014-09-22 11:58:17 -070019package org.onlab.onos.cli.net;
20
Thomas Vachuskabb0272e2014-10-16 09:32:04 -070021import com.fasterxml.jackson.databind.JsonNode;
22import com.fasterxml.jackson.databind.ObjectMapper;
23import com.fasterxml.jackson.databind.node.ArrayNode;
24import com.fasterxml.jackson.databind.node.ObjectNode;
toma6897792014-10-08 22:21:05 -070025import com.google.common.collect.Maps;
alshabib99b8fdc2014-09-25 14:30:22 -070026import org.apache.karaf.shell.commands.Argument;
27import org.apache.karaf.shell.commands.Command;
toma6897792014-10-08 22:21:05 -070028import org.onlab.onos.CoreService;
alshabib99b8fdc2014-09-25 14:30:22 -070029import org.onlab.onos.cli.AbstractShellCommand;
tom91c7bd02014-09-25 22:50:44 -070030import org.onlab.onos.cli.Comparators;
alshabib99b8fdc2014-09-25 14:30:22 -070031import org.onlab.onos.net.Device;
32import org.onlab.onos.net.DeviceId;
33import org.onlab.onos.net.device.DeviceService;
alshabib1c319ff2014-10-04 20:29:09 -070034import org.onlab.onos.net.flow.FlowEntry;
35import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
alshabib99b8fdc2014-09-25 14:30:22 -070036import org.onlab.onos.net.flow.FlowRuleService;
Thomas Vachuskabb0272e2014-10-16 09:32:04 -070037import org.onlab.onos.net.flow.criteria.Criterion;
38import org.onlab.onos.net.flow.instructions.Instruction;
alshabib99b8fdc2014-09-25 14:30:22 -070039
toma6897792014-10-08 22:21:05 -070040import java.util.Collections;
41import java.util.List;
42import java.util.Map;
43
44import static com.google.common.collect.Lists.newArrayList;
45import static org.onlab.onos.cli.net.DevicesListCommand.getSortedDevices;
alshabib9290eea2014-09-22 11:58:17 -070046
47/**
48 * Lists all currently-known hosts.
49 */
50@Command(scope = "onos", name = "flows",
toma6897792014-10-08 22:21:05 -070051 description = "Lists all currently-known flows.")
alshabib9290eea2014-09-22 11:58:17 -070052public class FlowsListCommand extends AbstractShellCommand {
53
alshabib144a2942014-09-25 18:44:02 -070054 public static final String ANY = "any";
55
alshabib9290eea2014-09-22 11:58:17 -070056 private static final String FMT =
toma6897792014-10-08 22:21:05 -070057 " id=%s, state=%s, bytes=%s, packets=%s, duration=%s, priority=%s, appId=%s";
alshabib99b8fdc2014-09-25 14:30:22 -070058 private static final String TFMT = " treatment=%s";
59 private static final String SFMT = " selector=%s";
60
alshabib144a2942014-09-25 18:44:02 -070061 @Argument(index = 1, name = "uri", description = "Device ID",
toma6897792014-10-08 22:21:05 -070062 required = false, multiValued = false)
alshabib99b8fdc2014-09-25 14:30:22 -070063 String uri = null;
alshabib9290eea2014-09-22 11:58:17 -070064
alshabib144a2942014-09-25 18:44:02 -070065 @Argument(index = 0, name = "state", description = "Flow Rule state",
toma6897792014-10-08 22:21:05 -070066 required = false, multiValued = false)
alshabib144a2942014-09-25 18:44:02 -070067 String state = null;
alshabib64231d82014-09-25 18:25:31 -070068
alshabib9290eea2014-09-22 11:58:17 -070069 @Override
tom0872a172014-09-23 11:24:26 -070070 protected void execute() {
toma6897792014-10-08 22:21:05 -070071 CoreService coreService = get(CoreService.class);
tomcaf3bf72014-09-23 13:20:53 -070072 DeviceService deviceService = get(DeviceService.class);
73 FlowRuleService service = get(FlowRuleService.class);
alshabib1c319ff2014-10-04 20:29:09 -070074 Map<Device, List<FlowEntry>> flows = getSortedFlows(deviceService, service);
Thomas Vachuskabb0272e2014-10-16 09:32:04 -070075
76 if (outputJson()) {
77 print("%s", json(coreService, getSortedDevices(deviceService), flows));
78 } else {
79 for (Device d : getSortedDevices(deviceService)) {
80 printFlows(d, flows.get(d), coreService);
81 }
alshabib9290eea2014-09-22 11:58:17 -070082 }
alshabib9290eea2014-09-22 11:58:17 -070083 }
84
alshabib9290eea2014-09-22 11:58:17 -070085 /**
Thomas Vachuskabb0272e2014-10-16 09:32:04 -070086 * Produces a JSON array of flows grouped by the each device.
87 *
88 * @param coreService core service
89 * @param devices collection of devices to group flow by
90 * @param flows collection of flows per each device
91 * @return JSON array
92 */
93 private JsonNode json(CoreService coreService, Iterable<Device> devices,
94 Map<Device, List<FlowEntry>> flows) {
95 ObjectMapper mapper = new ObjectMapper();
96 ArrayNode result = mapper.createArrayNode();
97 for (Device device : devices) {
98 result.add(json(coreService, mapper, device, flows.get(device)));
99 }
100 return result;
101 }
102
103 // Produces JSON object with the flows of the given device.
104 private ObjectNode json(CoreService coreService, ObjectMapper mapper,
105 Device device, List<FlowEntry> flows) {
106 ObjectNode result = mapper.createObjectNode();
107 ArrayNode array = mapper.createArrayNode();
108
109 for (FlowEntry flow : flows) {
110 array.add(json(coreService, mapper, flow));
111 }
112
113 result.put("device", device.id().toString())
114 .put("flowCount", flows.size())
Thomas Vachuskadfe48a72014-10-16 10:32:08 -0700115 .set("flows", array);
Thomas Vachuskabb0272e2014-10-16 09:32:04 -0700116 return result;
117 }
118
119 // Produces JSON structure with the specified flow data.
120 private ObjectNode json(CoreService coreService, ObjectMapper mapper,
121 FlowEntry flow) {
122 ObjectNode result = mapper.createObjectNode();
123 ArrayNode crit = mapper.createArrayNode();
124 for (Criterion c : flow.selector().criteria()) {
125 crit.add(c.toString());
126 }
127
128 ArrayNode instr = mapper.createArrayNode();
129 for (Instruction i : flow.treatment().instructions()) {
130 instr.add(i.toString());
131 }
132
133 result.put("flowId", Long.toHexString(flow.id().value()))
134 .put("state", flow.state().toString())
135 .put("bytes", flow.bytes())
136 .put("packets", flow.packets())
137 .put("life", flow.life())
138 .put("appId", coreService.getAppId(flow.appId()).name());
139 result.set("selector", crit);
140 result.set("treatment", instr);
141 return result;
142 }
143
144 /**
alshabib9290eea2014-09-22 11:58:17 -0700145 * Returns the list of devices sorted using the device ID URIs.
146 *
147 * @param service device service
148 * @return sorted device list
149 */
tom1dd08e42014-10-07 11:40:00 -0700150 protected Map<Device, List<FlowEntry>> getSortedFlows(DeviceService deviceService,
151 FlowRuleService service) {
alshabib1c319ff2014-10-04 20:29:09 -0700152 Map<Device, List<FlowEntry>> flows = Maps.newHashMap();
153 List<FlowEntry> rules;
154 FlowEntryState s = null;
alshabib144a2942014-09-25 18:44:02 -0700155 if (state != null && !state.equals("any")) {
alshabib1c319ff2014-10-04 20:29:09 -0700156 s = FlowEntryState.valueOf(state.toUpperCase());
alshabib144a2942014-09-25 18:44:02 -0700157 }
tom1dd08e42014-10-07 11:40:00 -0700158 Iterable<Device> devices = uri == null ? deviceService.getDevices() :
toma6897792014-10-08 22:21:05 -0700159 Collections.singletonList(deviceService.getDevice(DeviceId.deviceId(uri)));
alshabib99b8fdc2014-09-25 14:30:22 -0700160 for (Device d : devices) {
alshabib144a2942014-09-25 18:44:02 -0700161 if (s == null) {
162 rules = newArrayList(service.getFlowEntries(d.id()));
163 } else {
164 rules = newArrayList();
alshabib1c319ff2014-10-04 20:29:09 -0700165 for (FlowEntry f : service.getFlowEntries(d.id())) {
alshabib144a2942014-09-25 18:44:02 -0700166 if (f.state().equals(s)) {
167 rules.add(f);
168 }
169 }
170 }
tom1380eee2014-09-24 09:22:02 -0700171 Collections.sort(rules, Comparators.FLOW_RULE_COMPARATOR);
alshabib9290eea2014-09-22 11:58:17 -0700172 flows.put(d, rules);
173 }
174 return flows;
175 }
176
177 /**
178 * Prints flows.
toma6897792014-10-08 22:21:05 -0700179 *
180 * @param d the device
alshabib9290eea2014-09-22 11:58:17 -0700181 * @param flows the set of flows for that device.
182 */
toma6897792014-10-08 22:21:05 -0700183 protected void printFlows(Device d, List<FlowEntry> flows,
184 CoreService coreService) {
tom1dd08e42014-10-07 11:40:00 -0700185 boolean empty = flows == null || flows.isEmpty();
186 print("deviceId=%s, flowRuleCount=%d", d.id(), empty ? 0 : flows.size());
187 if (!empty) {
188 for (FlowEntry f : flows) {
toma6897792014-10-08 22:21:05 -0700189 print(FMT, Long.toHexString(f.id().value()), f.state(),
190 f.bytes(), f.packets(), f.life(), f.priority(),
191 coreService.getAppId(f.appId()).name());
tom1dd08e42014-10-07 11:40:00 -0700192 print(SFMT, f.selector().criteria());
193 print(TFMT, f.treatment().instructions());
194 }
alshabib99b8fdc2014-09-25 14:30:22 -0700195 }
alshabib9290eea2014-09-22 11:58:17 -0700196 }
197
Yuta HIGUCHIe76a24d2014-09-27 00:48:34 -0700198}