blob: 88e51c41faa22f99e7b48be3f570dd164275f682 [file] [log] [blame]
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +09003 *
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.cli.net;
18
Ray Milkeyd84f89b2018-08-17 14:54:17 -070019import org.apache.karaf.shell.api.action.Argument;
20import org.apache.karaf.shell.api.action.Command;
21import org.apache.karaf.shell.api.action.lifecycle.Service;
22import org.apache.karaf.shell.api.action.Option;
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +090023import org.onosproject.cli.AbstractShellCommand;
24import org.onosproject.incubator.net.dpi.DpiStatInfo;
25import org.onosproject.incubator.net.dpi.DpiStatistics;
26import org.onosproject.incubator.net.dpi.DpiStatisticsManagerService;
27import org.onosproject.incubator.net.dpi.FlowStatInfo;
28import org.onosproject.incubator.net.dpi.ProtocolStatInfo;
29import org.onosproject.incubator.net.dpi.TrafficStatInfo;
30
31import java.util.List;
32
33import static java.lang.Thread.sleep;
34
35/**
36 * Fetches DPI statistics list.
37 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070038@Service
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +090039@Command(scope = "onos", name = "dpis",
40 description = "Fetches the DPI result entries that is received from DPI engine server")
41public class DpisListCommand extends AbstractShellCommand {
42 @Argument(index = 0, name = "receivedTime", description = "received time: format 'yyyy-MM-dd HH:mm:ss', "
43 + "ex:'2016-08-30 10:31:20', default = null(latest time)",
44 required = false, multiValued = false)
45 String receivedTime = null; // default is latest time
46
47 @Option(name = "-l", aliases = "--latest",
48 description = "Show the latest dpi stats result entry",
49 required = false, multiValued = false)
50 boolean latest = true; // default
51
52 @Option(name = "-d", aliases = "--detectedProtocols",
53 description = "Show the detected protocols only for each statistic entry",
54 required = false, multiValued = false)
55 boolean dProtocols = false; // default
56
57 @Option(name = "-k", aliases = "--knownFlows",
58 description = "Show the known flows only for each statistic entry",
59 required = false, multiValued = false)
60 boolean kFlows = false; // default
61
62 @Option(name = "-u", aliases = "--unknownFlows",
63 description = "Show the unknown flows only for each statistic entry",
64 required = false, multiValued = false)
65 boolean uFlows = false; // default
66
67 @Option(name = "-a", aliases = "--all",
68 description = "Show the all statistics information in detail for each statistic entry",
69 required = false, multiValued = false)
70 boolean all = false; // default is traffic statistics only display
71
72 @Option(name = "-p", aliases = "--permanent",
73 description = "Show the latest dpi stats result entry permanently at 5 second, use Ctrl+C for quitting",
74 required = false, multiValued = false)
75 boolean permanent = false;
76
77 @Option(name = "-n", aliases = "--lastn",
78 description = "Show the last N Dpi stats result entries, MAX_REQUEST_ENTRY = 100",
79 required = false, multiValued = false)
80 String lastn = null;
81
82 @Option(name = "-P", aliases = "--topnProtocols",
83 description = "Show the topn detected Protocol result entries, MAX_PROTOCOLS_TOPN = 100",
84 required = false, multiValued = false)
85 String topnProtocols = null;
86
87 @Option(name = "-F", aliases = "--topnFlows",
88 description = "Show the topn known and unknown Flows result entries, MAX_FLOWS_TOPN = 100",
89 required = false, multiValued = false)
90 String topnFlows = null;
91
92 private static final int DEFAULT_LASTN = 100;
93 private static final int DEFAULT_TOPNP = -1;
94 private static final int DEFAULT_TOPNF = -1;
95 private static final String NO_DPI_ENTRY_ERROR_MSG = "No DPI statistic entry,"
96 + " please check remote DPI engine is running";
97 private static final String RECEIVED_TIME_ERROR_MSG = NO_DPI_ENTRY_ERROR_MSG + "\n"
98 + " or correct receivedTime format: 'yyyy-MM-dd HH:mm:ss', ex:'2016-08-30 10:31:20'";
99
100 @Override
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700101 protected void doExecute() {
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +0900102 DpiStatisticsManagerService dsms = get(DpiStatisticsManagerService.class);
103
104 DpiStatistics ds;
105
106 int topnP = DEFAULT_TOPNP;
107 int topnF = DEFAULT_TOPNF;
108
109 if (topnProtocols != null) {
110 topnP = parseIntWithDefault(topnProtocols, DEFAULT_TOPNP);
111 if (topnP <= 0) {
112 print("Invalid detected protocol topn number: 0 < valid number <= 100");
113 return;
114 }
115 }
116
117 if (topnFlows != null) {
118 topnF = parseIntWithDefault(topnFlows, DEFAULT_TOPNF);
119 if (topnF <= 0) {
120 print("Invalid known or unknown flows topn number: 0 < valid number <= 100");
121 return;
122 }
123 }
124
125 boolean isTopn = (topnP > 0 || topnF > 0);
126
127 if (all) {
128 dProtocols = true;
129 kFlows = true;
130 uFlows = true;
131 }
132
133 if (receivedTime != null) {
134 if (isTopn) {
135 ds = dsms.getDpiStatistics(receivedTime, topnP, topnF);
136 } else {
137 ds = dsms.getDpiStatistics(receivedTime);
138 }
139 if (ds == null) {
140 print(RECEIVED_TIME_ERROR_MSG);
141 return;
142 }
143
144 printDpiStatistics(0, ds);
145 } else if (lastn != null) {
146 int lastN = parseIntWithDefault(lastn, DEFAULT_LASTN);
147
148 List<DpiStatistics> dsList;
149 if (isTopn) {
150 dsList = dsms.getDpiStatistics(lastN, topnP, topnF);
151
152 } else {
153 dsList = dsms.getDpiStatistics(lastN);
154 }
155
156 printDpiStatisticsList(dsList);
157 } else if (permanent) {
158 int i = 0;
159 while (true) {
160 try {
161 if (isTopn) {
162 ds = dsms.getDpiStatisticsLatest(topnP, topnF);
163 } else {
164 ds = dsms.getDpiStatisticsLatest();
165 }
166 if (ds == null) {
167 print(NO_DPI_ENTRY_ERROR_MSG);
168 return;
169 }
170
171 printDpiStatistics(i++, ds);
172 sleep(5000);
173 } catch (Exception e) {
174 return;
175 }
176 }
177 } else { // latest == true
178 if (isTopn) {
179 ds = dsms.getDpiStatisticsLatest(topnP, topnF);
180 } else {
181 ds = dsms.getDpiStatisticsLatest();
182 }
183 if (ds == null) {
184 print(NO_DPI_ENTRY_ERROR_MSG);
185 return;
186 }
187
188 printDpiStatistics(0, ds);
189 }
190 }
191
192
193 /**
194 * Parse unsigned integer from input lastn string.
195 *
196 * @param lastN string lastn number
197 * @param defaultN integer default lastn number = 100
198 * @return integer lastN number, defaultN if input format is not a number
199 */
200 private int parseIntWithDefault(String lastN, int defaultN) {
201 try {
202 lastN = lastN.trim();
203 return Integer.parseUnsignedInt(lastN);
204 } catch (NumberFormatException e) {
205 return defaultN;
206 }
207 }
208
209 private void printDpiStatistics(int number, DpiStatistics ds) {
210 if (outputJson()) {
211 printDpiStatisticsJson(number, ds);
212 } else {
213 printDpiStatisticsClass(number, ds);
214 }
215 }
216
217 private void printDpiStatisticsJson(int number, DpiStatistics ds) {
Ray Milkey42b62032018-02-01 11:15:31 -0800218 String index = number < 0 ? " - " : String.format("%5d", number);
Jon Halla3fcf672017-03-28 16:53:22 -0700219 if ("".equals(ds.receivedTime())) {
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +0900220 print("ReceivedTime is null, No valid DPI Statistics!");
221 return;
222 }
223
224 print("<--- (%s) DPI Statistics Time [%s] --->", index, ds.receivedTime());
225 print(" %s", ds.toString());
226 print("<--------------------------------------------------------->");
227 }
228
229 private void printDpiStatisticsClass(int number, DpiStatistics ds) {
230 String printLine = "";
Ray Milkey42b62032018-02-01 11:15:31 -0800231 String index = number < 0 ? " - " : String.format("%5d", number);
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +0900232
233 DpiStatInfo dsi = ds.dpiStatInfo();
234 if (dsi == null) {
235 return;
236 }
237
Jon Halla3fcf672017-03-28 16:53:22 -0700238 if ("".equals(ds.receivedTime())) {
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +0900239 print("ReceivedTime is null, No valid DPI Statistics!");
240 return;
241 }
242
243 print("<--- (%s) DPI Statistics Time [%s] --->", index, ds.receivedTime());
244
245 print("Traffic Statistics:");
246 TrafficStatInfo tsi = dsi.trafficStatistics();
247
248 printLine = String.format(" %-30s %-30s", "ethernet.bytes:" + ":", tsi.ethernetBytes());
249 print("%s", printLine);
250 printLine = String.format(" %-30s %-30s", "discarded.bytes" + ":", tsi.discardedBytes());
251 print("%s", printLine);
252 printLine = String.format(" %-30s %-30s", "ip.packets" + ":", tsi.ipPackets());
253 print("%s", printLine);
254 printLine = String.format(" %-30s %-30s", "total.packets" + ":", tsi.totalPackets());
255 print("%s", printLine);
256 printLine = String.format(" %-30s %-30s", "ip.bytes" + ":", tsi.ipBytes());
257 print("%s", printLine);
258 printLine = String.format(" %-30s %-30s", "avg.pkt.size" + ":", tsi.avgPktSize());
259 print("%s", printLine);
260 printLine = String.format(" %-30s %-30s", "unique.flows" + ":", tsi.uniqueFlows());
261 print("%s", printLine);
262 printLine = String.format(" %-30s %-30s", "tcp.packets" + ":", tsi.tcpPackets());
263 print("%s", printLine);
264 printLine = String.format(" %-30s %-30s", "udp.packets" + ":", tsi.tcpPackets());
265 print("%s", printLine);
266 printLine = String.format(" %-30s %-30s", "dpi.throughput.pps" + ":",
267 tsi.dpiThroughputPps() + " pps");
268 print("%s", printLine);
269 printLine = String.format(" %-30s %-30s", "dpi.throughput.bps" + ":",
270 tsi.dpiThroughputBps() + " bps");
271 print("%s", printLine);
272 printLine = String.format(" %-30s %-30s", "traffic.throughput.pps" + ":",
273 tsi.trafficThroughputPps() + " pps");
274 print("%s", printLine);
275 printLine = String.format(" %-30s %-30s", "traffic.throughput.bps" + ":",
276 tsi.trafficThroughputBps() + " bps");
277 print("%s", printLine);
278 printLine = String.format(" %-30s %-30s", "traffic.duration.sec" + ":",
279 tsi.trafficDurationSec() + " sec");
280 print("%s", printLine);
281 printLine = String.format(" %-30s %-30s", "guessed.flow.protos" + ":", tsi.guessedFlowProtos());
282 print("%s", printLine);
283
284 if (dProtocols || topnProtocols != null) {
285 print("");
286 print("Detected Protocols:");
287 List<ProtocolStatInfo> psiList = dsi.detectedProtos();
288 if (psiList != null) {
289 psiList.forEach(psi -> print(makeProtocolString(psi)));
290 }
291 }
292
293 List<FlowStatInfo> fsiList;
294 if (kFlows || topnFlows != null) {
295 print("");
296 print("Known Flows:");
297 fsiList = dsi.knownFlows();
298 if (fsiList != null) {
299 for (int i = 0; i < fsiList.size(); i++) {
300 print(makeFlowString(fsiList.get(i), i));
301 }
302 }
303 }
304
305 if (uFlows || topnFlows != null) {
306 print("");
307 print("Unknown Flows:");
308 fsiList = dsi.unknownFlows();
309 if (fsiList != null) {
310 for (int i = 0; i < fsiList.size(); i++) {
311 print(makeFlowString(fsiList.get(i), i));
312 }
313 }
314 }
315
316 print("<--------------------------------------------------------->");
317 }
318
319 private void printDpiStatisticsList(List<DpiStatistics> dsList) {
320 if (outputJson()) {
321 printDpiStatisticsListJson(dsList);
322 } else {
323 printDpiStatisticsListClass(dsList);
324 }
325 }
326
327 private void printDpiStatisticsListJson(List<DpiStatistics> dsList) {
328 for (int i = 0; i < dsList.size(); i++) {
329 printDpiStatisticsJson(i, dsList.get(i));
330 }
331 }
332
333 private void printDpiStatisticsListClass(List<DpiStatistics> dsList) {
334 for (int i = 0; i < dsList.size(); i++) {
335 printDpiStatisticsClass(i, dsList.get(i));
336 }
337 }
338
339 private String makeProtocolString(ProtocolStatInfo psi) {
340 StringBuffer sb = new StringBuffer(" ");
341
342 sb.append(String.format("%-20s", psi.name()));
343 sb.append(String.format(" %s: %-20s", "packets", psi.packets()));
344 sb.append(String.format(" %s: %-20s", "bytes", psi.bytes()));
345 sb.append(String.format(" %s: %-20s", "flows", psi.flows()));
346
347 return sb.toString();
348 }
349
350 private String makeFlowString(FlowStatInfo fsi, int index) {
351 StringBuffer sb = new StringBuffer(" ");
352
353 sb.append(String.format("%-8d ", index));
354 sb.append(String.format("%s ", fsi.protocol()));
355 sb.append(String.format("%s", fsi.hostAName()));
356 sb.append(String.format(":%s", fsi.hostAPort()));
357 sb.append(String.format(" <-> %s", fsi.hostBName()));
358 sb.append(String.format(":%s", fsi.hostBPort()));
359 sb.append(String.format(" [proto: %d", fsi.detectedProtocol()));
360 sb.append(String.format("/%s]", fsi.detectedProtocolName()));
361 sb.append(String.format(" [%s pkts/", fsi.packets()));
362 sb.append(String.format("%s bytes]", fsi.bytes()));
363 String serverHostName = fsi.hostServerName();
Jon Halla3fcf672017-03-28 16:53:22 -0700364 if (serverHostName != null && !"".equals(serverHostName)) {
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +0900365 sb.append(String.format("[Host: %s]", serverHostName));
366 }
367
368 return sb.toString();
369 }
370}