blob: 9d3ec6933cb0d83f10bc834de86e6ce762d9173d [file] [log] [blame]
Srikanth Vavilapalli95810f52015-09-14 15:49:56 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Srikanth Vavilapalli95810f52015-09-14 15:49:56 -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 */
16package org.onosproject.cli.net;
17
18import static com.google.common.collect.Lists.newArrayList;
19
20import java.util.Collections;
21import java.util.List;
22import java.util.Map;
23import java.util.SortedMap;
24import java.util.TreeMap;
25
Ray Milkeyd84f89b2018-08-17 14:54:17 -070026import org.apache.karaf.shell.api.action.Argument;
27import org.apache.karaf.shell.api.action.Command;
28import org.apache.karaf.shell.api.action.lifecycle.Service;
29import org.apache.karaf.shell.api.action.Option;
Srikanth Vavilapalli95810f52015-09-14 15:49:56 -070030import org.onosproject.cli.AbstractShellCommand;
Ray Milkeyc7477292016-03-11 10:53:43 -080031import org.onosproject.utils.Comparators;
Srikanth Vavilapalli95810f52015-09-14 15:49:56 -070032import org.onosproject.net.Device;
33import org.onosproject.net.DeviceId;
34import org.onosproject.net.device.DeviceService;
35import org.onosproject.net.flow.FlowRuleService;
36import org.onosproject.net.flow.TableStatisticsEntry;
37
38import com.fasterxml.jackson.databind.JsonNode;
39import com.fasterxml.jackson.databind.ObjectMapper;
40import com.fasterxml.jackson.databind.node.ArrayNode;
41import com.fasterxml.jackson.databind.node.ObjectNode;
42
43/**
44 * Lists port statistic of all ports in the system.
45 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070046@Service
Srikanth Vavilapalli95810f52015-09-14 15:49:56 -070047@Command(scope = "onos", name = "tablestats",
48 description = "Lists statistics of all tables in the device")
49public class TableStatisticsCommand extends AbstractShellCommand {
50
51 @Option(name = "-t", aliases = "--table", description = "Show human readable table format for statistics",
52 required = false, multiValued = false)
53 private boolean table = false;
54
55 @Argument(index = 0, name = "uri", description = "Device ID",
56 required = false, multiValued = false)
57 String uri = null;
58
59 private static final String FORMAT =
60 " table=%s, active=%s, lookedup=%s, matched=%s";
61
62 @Override
Ray Milkeyd84f89b2018-08-17 14:54:17 -070063 protected void doExecute() {
Srikanth Vavilapalli95810f52015-09-14 15:49:56 -070064 FlowRuleService flowService = get(FlowRuleService.class);
65 DeviceService deviceService = get(DeviceService.class);
66
67 SortedMap<Device, List<TableStatisticsEntry>> deviceTableStats =
68 getSortedTableStats(deviceService, flowService);
69
70 if (outputJson()) {
71 print("%s", json(deviceTableStats.keySet(), deviceTableStats));
72 } else {
73 deviceTableStats.forEach((device, tableStats) -> printTableStats(device, tableStats));
74 }
75 }
76
77 /**
78 * Produces a JSON array of table statistics grouped by the each device.
79 *
80 * @param devices collection of devices
81 * @param deviceTableStats collection of table statistics per each device
82 * @return JSON array
83 */
84 private JsonNode json(Iterable<Device> devices,
85 Map<Device, List<TableStatisticsEntry>> deviceTableStats) {
86 ObjectMapper mapper = new ObjectMapper();
87 ArrayNode result = mapper.createArrayNode();
88 for (Device device : devices) {
89 result.add(json(mapper, device, deviceTableStats.get(device)));
90 }
91 return result;
92 }
93
94 // Produces JSON object with the table statistics of the given device.
95 private ObjectNode json(ObjectMapper mapper,
96 Device device, List<TableStatisticsEntry> tableStats) {
97 ObjectNode result = mapper.createObjectNode();
98 ArrayNode array = mapper.createArrayNode();
99
100 tableStats.forEach(tableStat -> array.add(jsonForEntity(tableStat, TableStatisticsEntry.class)));
101
102 result.put("device", device.id().toString())
103 .put("tableCount", tableStats.size())
104 .set("tables", array);
105 return result;
106 }
107
108 /**
109 * Prints flow table statistics.
110 *
111 * @param d the device
112 * @param tableStats the set of flow table statistics for that device
113 */
114 protected void printTableStats(Device d,
115 List<TableStatisticsEntry> tableStats) {
116 boolean empty = tableStats == null || tableStats.isEmpty();
117 print("deviceId=%s, tableCount=%d", d.id(), empty ? 0 : tableStats.size());
118 if (!empty) {
119 for (TableStatisticsEntry t : tableStats) {
120 print(FORMAT, t.tableId(), t.activeFlowEntries(),
121 t.packetsLookedup(), t.packetsMatched());
122 }
123 }
124 }
125
126 /**
127 * Returns the list of table statistics sorted using the device ID URIs and table IDs.
128 *
129 * @param deviceService device service
130 * @param flowService flow rule service
131 * @return sorted table statistics list
132 */
133 protected SortedMap<Device, List<TableStatisticsEntry>> getSortedTableStats(DeviceService deviceService,
134 FlowRuleService flowService) {
135 SortedMap<Device, List<TableStatisticsEntry>> deviceTableStats = new TreeMap<>(Comparators.ELEMENT_COMPARATOR);
136 List<TableStatisticsEntry> tableStatsList;
137 Iterable<Device> devices = uri == null ? deviceService.getDevices() :
138 Collections.singletonList(deviceService.getDevice(DeviceId.deviceId(uri)));
139 for (Device d : devices) {
140 tableStatsList = newArrayList(flowService.getFlowTableStatistics(d.id()));
141 tableStatsList.sort((p1, p2) -> Integer.valueOf(p1.tableId()).compareTo(Integer.valueOf(p2.tableId())));
142 deviceTableStats.put(d, tableStatsList);
143 }
144 return deviceTableStats;
145 }
146
147}