blob: d34c9edb3e3ed0aaa9482cbd04dce79b7cb14a22 [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cli.net;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.incubator.net.dpi.DpiStatInfo;
import org.onosproject.incubator.net.dpi.DpiStatistics;
import org.onosproject.incubator.net.dpi.DpiStatisticsManagerService;
import org.onosproject.incubator.net.dpi.FlowStatInfo;
import org.onosproject.incubator.net.dpi.ProtocolStatInfo;
import org.onosproject.incubator.net.dpi.TrafficStatInfo;
import java.util.List;
import static java.lang.Thread.sleep;
/**
* Fetches DPI statistics list.
*/
@Command(scope = "onos", name = "dpis",
description = "Fetches the DPI result entries that is received from DPI engine server")
public class DpisListCommand extends AbstractShellCommand {
@Argument(index = 0, name = "receivedTime", description = "received time: format 'yyyy-MM-dd HH:mm:ss', "
+ "ex:'2016-08-30 10:31:20', default = null(latest time)",
required = false, multiValued = false)
String receivedTime = null; // default is latest time
@Option(name = "-l", aliases = "--latest",
description = "Show the latest dpi stats result entry",
required = false, multiValued = false)
boolean latest = true; // default
@Option(name = "-d", aliases = "--detectedProtocols",
description = "Show the detected protocols only for each statistic entry",
required = false, multiValued = false)
boolean dProtocols = false; // default
@Option(name = "-k", aliases = "--knownFlows",
description = "Show the known flows only for each statistic entry",
required = false, multiValued = false)
boolean kFlows = false; // default
@Option(name = "-u", aliases = "--unknownFlows",
description = "Show the unknown flows only for each statistic entry",
required = false, multiValued = false)
boolean uFlows = false; // default
@Option(name = "-a", aliases = "--all",
description = "Show the all statistics information in detail for each statistic entry",
required = false, multiValued = false)
boolean all = false; // default is traffic statistics only display
@Option(name = "-p", aliases = "--permanent",
description = "Show the latest dpi stats result entry permanently at 5 second, use Ctrl+C for quitting",
required = false, multiValued = false)
boolean permanent = false;
@Option(name = "-n", aliases = "--lastn",
description = "Show the last N Dpi stats result entries, MAX_REQUEST_ENTRY = 100",
required = false, multiValued = false)
String lastn = null;
@Option(name = "-P", aliases = "--topnProtocols",
description = "Show the topn detected Protocol result entries, MAX_PROTOCOLS_TOPN = 100",
required = false, multiValued = false)
String topnProtocols = null;
@Option(name = "-F", aliases = "--topnFlows",
description = "Show the topn known and unknown Flows result entries, MAX_FLOWS_TOPN = 100",
required = false, multiValued = false)
String topnFlows = null;
private static final int DEFAULT_LASTN = 100;
private static final int DEFAULT_TOPNP = -1;
private static final int DEFAULT_TOPNF = -1;
private static final String NO_DPI_ENTRY_ERROR_MSG = "No DPI statistic entry,"
+ " please check remote DPI engine is running";
private static final String RECEIVED_TIME_ERROR_MSG = NO_DPI_ENTRY_ERROR_MSG + "\n"
+ " or correct receivedTime format: 'yyyy-MM-dd HH:mm:ss', ex:'2016-08-30 10:31:20'";
@Override
protected void execute() {
DpiStatisticsManagerService dsms = get(DpiStatisticsManagerService.class);
DpiStatistics ds;
int topnP = DEFAULT_TOPNP;
int topnF = DEFAULT_TOPNF;
if (topnProtocols != null) {
topnP = parseIntWithDefault(topnProtocols, DEFAULT_TOPNP);
if (topnP <= 0) {
print("Invalid detected protocol topn number: 0 < valid number <= 100");
return;
}
}
if (topnFlows != null) {
topnF = parseIntWithDefault(topnFlows, DEFAULT_TOPNF);
if (topnF <= 0) {
print("Invalid known or unknown flows topn number: 0 < valid number <= 100");
return;
}
}
boolean isTopn = (topnP > 0 || topnF > 0);
if (all) {
dProtocols = true;
kFlows = true;
uFlows = true;
}
if (receivedTime != null) {
if (isTopn) {
ds = dsms.getDpiStatistics(receivedTime, topnP, topnF);
} else {
ds = dsms.getDpiStatistics(receivedTime);
}
if (ds == null) {
print(RECEIVED_TIME_ERROR_MSG);
return;
}
printDpiStatistics(0, ds);
} else if (lastn != null) {
int lastN = parseIntWithDefault(lastn, DEFAULT_LASTN);
List<DpiStatistics> dsList;
if (isTopn) {
dsList = dsms.getDpiStatistics(lastN, topnP, topnF);
} else {
dsList = dsms.getDpiStatistics(lastN);
}
printDpiStatisticsList(dsList);
} else if (permanent) {
int i = 0;
while (true) {
try {
if (isTopn) {
ds = dsms.getDpiStatisticsLatest(topnP, topnF);
} else {
ds = dsms.getDpiStatisticsLatest();
}
if (ds == null) {
print(NO_DPI_ENTRY_ERROR_MSG);
return;
}
printDpiStatistics(i++, ds);
sleep(5000);
} catch (Exception e) {
return;
}
}
} else { // latest == true
if (isTopn) {
ds = dsms.getDpiStatisticsLatest(topnP, topnF);
} else {
ds = dsms.getDpiStatisticsLatest();
}
if (ds == null) {
print(NO_DPI_ENTRY_ERROR_MSG);
return;
}
printDpiStatistics(0, ds);
}
}
/**
* Parse unsigned integer from input lastn string.
*
* @param lastN string lastn number
* @param defaultN integer default lastn number = 100
* @return integer lastN number, defaultN if input format is not a number
*/
private int parseIntWithDefault(String lastN, int defaultN) {
try {
lastN = lastN.trim();
return Integer.parseUnsignedInt(lastN);
} catch (NumberFormatException e) {
return defaultN;
}
}
private void printDpiStatistics(int number, DpiStatistics ds) {
if (outputJson()) {
printDpiStatisticsJson(number, ds);
} else {
printDpiStatisticsClass(number, ds);
}
}
private void printDpiStatisticsJson(int number, DpiStatistics ds) {
String index = number < 0 ? " - " : String.format("%5d", number);
if ("".equals(ds.receivedTime())) {
print("ReceivedTime is null, No valid DPI Statistics!");
return;
}
print("<--- (%s) DPI Statistics Time [%s] --->", index, ds.receivedTime());
print(" %s", ds.toString());
print("<--------------------------------------------------------->");
}
private void printDpiStatisticsClass(int number, DpiStatistics ds) {
String printLine = "";
String index = number < 0 ? " - " : String.format("%5d", number);
DpiStatInfo dsi = ds.dpiStatInfo();
if (dsi == null) {
return;
}
if ("".equals(ds.receivedTime())) {
print("ReceivedTime is null, No valid DPI Statistics!");
return;
}
print("<--- (%s) DPI Statistics Time [%s] --->", index, ds.receivedTime());
print("Traffic Statistics:");
TrafficStatInfo tsi = dsi.trafficStatistics();
printLine = String.format(" %-30s %-30s", "ethernet.bytes:" + ":", tsi.ethernetBytes());
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "discarded.bytes" + ":", tsi.discardedBytes());
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "ip.packets" + ":", tsi.ipPackets());
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "total.packets" + ":", tsi.totalPackets());
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "ip.bytes" + ":", tsi.ipBytes());
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "avg.pkt.size" + ":", tsi.avgPktSize());
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "unique.flows" + ":", tsi.uniqueFlows());
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "tcp.packets" + ":", tsi.tcpPackets());
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "udp.packets" + ":", tsi.tcpPackets());
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "dpi.throughput.pps" + ":",
tsi.dpiThroughputPps() + " pps");
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "dpi.throughput.bps" + ":",
tsi.dpiThroughputBps() + " bps");
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "traffic.throughput.pps" + ":",
tsi.trafficThroughputPps() + " pps");
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "traffic.throughput.bps" + ":",
tsi.trafficThroughputBps() + " bps");
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "traffic.duration.sec" + ":",
tsi.trafficDurationSec() + " sec");
print("%s", printLine);
printLine = String.format(" %-30s %-30s", "guessed.flow.protos" + ":", tsi.guessedFlowProtos());
print("%s", printLine);
if (dProtocols || topnProtocols != null) {
print("");
print("Detected Protocols:");
List<ProtocolStatInfo> psiList = dsi.detectedProtos();
if (psiList != null) {
psiList.forEach(psi -> print(makeProtocolString(psi)));
}
}
List<FlowStatInfo> fsiList;
if (kFlows || topnFlows != null) {
print("");
print("Known Flows:");
fsiList = dsi.knownFlows();
if (fsiList != null) {
for (int i = 0; i < fsiList.size(); i++) {
print(makeFlowString(fsiList.get(i), i));
}
}
}
if (uFlows || topnFlows != null) {
print("");
print("Unknown Flows:");
fsiList = dsi.unknownFlows();
if (fsiList != null) {
for (int i = 0; i < fsiList.size(); i++) {
print(makeFlowString(fsiList.get(i), i));
}
}
}
print("<--------------------------------------------------------->");
}
private void printDpiStatisticsList(List<DpiStatistics> dsList) {
if (outputJson()) {
printDpiStatisticsListJson(dsList);
} else {
printDpiStatisticsListClass(dsList);
}
}
private void printDpiStatisticsListJson(List<DpiStatistics> dsList) {
for (int i = 0; i < dsList.size(); i++) {
printDpiStatisticsJson(i, dsList.get(i));
}
}
private void printDpiStatisticsListClass(List<DpiStatistics> dsList) {
for (int i = 0; i < dsList.size(); i++) {
printDpiStatisticsClass(i, dsList.get(i));
}
}
private String makeProtocolString(ProtocolStatInfo psi) {
StringBuffer sb = new StringBuffer(" ");
sb.append(String.format("%-20s", psi.name()));
sb.append(String.format(" %s: %-20s", "packets", psi.packets()));
sb.append(String.format(" %s: %-20s", "bytes", psi.bytes()));
sb.append(String.format(" %s: %-20s", "flows", psi.flows()));
return sb.toString();
}
private String makeFlowString(FlowStatInfo fsi, int index) {
StringBuffer sb = new StringBuffer(" ");
sb.append(String.format("%-8d ", index));
sb.append(String.format("%s ", fsi.protocol()));
sb.append(String.format("%s", fsi.hostAName()));
sb.append(String.format(":%s", fsi.hostAPort()));
sb.append(String.format(" <-> %s", fsi.hostBName()));
sb.append(String.format(":%s", fsi.hostBPort()));
sb.append(String.format(" [proto: %d", fsi.detectedProtocol()));
sb.append(String.format("/%s]", fsi.detectedProtocolName()));
sb.append(String.format(" [%s pkts/", fsi.packets()));
sb.append(String.format("%s bytes]", fsi.bytes()));
String serverHostName = fsi.hostServerName();
if (serverHostName != null && !"".equals(serverHostName)) {
sb.append(String.format("[Host: %s]", serverHostName));
}
return sb.toString();
}
}