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