diff --git a/cli/src/main/java/org/onosproject/cli/net/DpisListCommand.java b/cli/src/main/java/org/onosproject/cli/net/DpisListCommand.java new file mode 100644 index 0000000000..85c2dda291 --- /dev/null +++ b/cli/src/main/java/org/onosproject/cli/net/DpisListCommand.java @@ -0,0 +1,368 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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 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(" - ") : String.format("%5d", number); + if (ds.receivedTime().equals("")) { + 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(" - ") : String.format("%5d", number); + + DpiStatInfo dsi = ds.dpiStatInfo(); + if (dsi == null) { + return; + } + + if (ds.receivedTime().equals("")) { + 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 psiList = dsi.detectedProtos(); + if (psiList != null) { + psiList.forEach(psi -> print(makeProtocolString(psi))); + } + } + + List 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 dsList) { + if (outputJson()) { + printDpiStatisticsListJson(dsList); + } else { + printDpiStatisticsListClass(dsList); + } + } + + private void printDpiStatisticsListJson(List dsList) { + for (int i = 0; i < dsList.size(); i++) { + printDpiStatisticsJson(i, dsList.get(i)); + } + } + + private void printDpiStatisticsListClass(List 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 && !serverHostName.equals("")) { + sb.append(String.format("[Host: %s]", serverHostName)); + } + + return sb.toString(); + } +} diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml index 69c52fea2c..f3c660ff24 100644 --- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml +++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml @@ -714,6 +714,9 @@ + + + diff --git a/core/common/src/main/java/org/onosproject/codec/impl/CodecManager.java b/core/common/src/main/java/org/onosproject/codec/impl/CodecManager.java index 090727fe59..3f305b69de 100644 --- a/core/common/src/main/java/org/onosproject/codec/impl/CodecManager.java +++ b/core/common/src/main/java/org/onosproject/codec/impl/CodecManager.java @@ -28,6 +28,16 @@ import org.onosproject.codec.CodecService; import org.onosproject.codec.JsonCodec; import org.onosproject.core.Application; import org.onosproject.core.ApplicationId; +import org.onosproject.incubator.net.dpi.DpiStatInfo; +import org.onosproject.incubator.net.dpi.DpiStatInfoCodec; +import org.onosproject.incubator.net.dpi.DpiStatistics; +import org.onosproject.incubator.net.dpi.DpiStatisticsCodec; +import org.onosproject.incubator.net.dpi.FlowStatInfo; +import org.onosproject.incubator.net.dpi.FlowStatInfoCodec; +import org.onosproject.incubator.net.dpi.ProtocolStatInfo; +import org.onosproject.incubator.net.dpi.ProtocolStatInfoCodec; +import org.onosproject.incubator.net.dpi.TrafficStatInfo; +import org.onosproject.incubator.net.dpi.TrafficStatInfoCodec; import org.onosproject.incubator.net.virtual.TenantId; import org.onosproject.incubator.net.virtual.VirtualDevice; import org.onosproject.incubator.net.virtual.VirtualHost; @@ -150,6 +160,11 @@ public class CodecManager implements CodecService { registerCodec(MastershipTerm.class, new MastershipTermCodec()); registerCodec(MastershipRole.class, new MastershipRoleCodec()); registerCodec(RoleInfo.class, new RoleInfoCodec()); + registerCodec(DpiStatistics.class, new DpiStatisticsCodec()); + registerCodec(DpiStatInfo.class, new DpiStatInfoCodec()); + registerCodec(TrafficStatInfo.class, new TrafficStatInfoCodec()); + registerCodec(ProtocolStatInfo.class, new ProtocolStatInfoCodec()); + registerCodec(FlowStatInfo.class, new FlowStatInfoCodec()); log.info("Started"); } diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatInfo.java b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatInfo.java new file mode 100644 index 0000000000..6d99c0cfaf --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatInfo.java @@ -0,0 +1,174 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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.incubator.net.dpi; + +import java.util.List; +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * DPI statistic information. + */ +public class DpiStatInfo { + TrafficStatInfo trafficStatistics; + List detectedProtos; + List knownFlows; + List unknownFlows; + + /** + * Constructor for default DpiStatInfo class. + */ + public DpiStatInfo() { + this.trafficStatistics = null; + this.detectedProtos = null; + this.knownFlows = null; + this.unknownFlows = null; + } + + /** + * Constructor for DpiStatistics class specified with trafficStatInfo. + * + * @param trafficStatistics traffic statistic information + */ + public DpiStatInfo(TrafficStatInfo trafficStatistics) { + this.trafficStatistics = trafficStatistics; + this.detectedProtos = null; + this.knownFlows = null; + this.unknownFlows = null; + } + + /** + * Constructor for DpiStatistics class specified with trafficStatInfo and detectedProtos. + * + * @param trafficStatistics traffic statistic information + * @param detectedProtos detected protocols statistic information + */ + public DpiStatInfo(TrafficStatInfo trafficStatistics, + List detectedProtos) { + this.trafficStatistics = trafficStatistics; + this.detectedProtos = detectedProtos; + this.knownFlows = null; + this.unknownFlows = null; + } + + /** + * Constructor for DpiStatistics class specified with trafficStatInfo, detectedProtos and knownFlows. + * + * @param trafficStatistics traffic statistic information + * @param detectedProtos detected protocols statistic information + * @param knownFlows known flows + */ + public DpiStatInfo(TrafficStatInfo trafficStatistics, + List detectedProtos, + List knownFlows) { + this.trafficStatistics = trafficStatistics; + this.detectedProtos = detectedProtos; + this.knownFlows = knownFlows; + this.unknownFlows = null; + } + + /** + * Constructor for DpiStatistics class specified with trafficStatInfo, detectedProtos, knownFlows and unknownFlows. + * + * @param trafficStatistics traffic statistic information + * @param detectedProtos detected protocols statistic information + * @param knownFlows known flows + * @param unknownFlows unknown flows + */ + public DpiStatInfo(TrafficStatInfo trafficStatistics, + List detectedProtos, + List knownFlows, + List unknownFlows) { + this.trafficStatistics = trafficStatistics; + this.detectedProtos = detectedProtos; + this.knownFlows = knownFlows; + this.unknownFlows = unknownFlows; + } + + /** + * Returns DPI traffic statistic information. + * + * @return trafficStatistics + */ + public TrafficStatInfo trafficStatistics() { + return trafficStatistics; + } + + /** + * Returns DPI detected protocols statistic information. + * + * @return detectedProtos + */ + public List detectedProtos() { + return detectedProtos; + } + + /** + * Returns DPI known flows. + * + * @return knownFlows + */ + public List knownFlows() { + return knownFlows; + } + + /** + * Returns DPI unknown flows. + * + * @return unknownFlows + */ + public List unknownFlows() { + return unknownFlows; + } + + /** + * Sets the traffic statistic information. + */ + public void setTrafficStatistics(TrafficStatInfo trafficStatistics) { + this.trafficStatistics = trafficStatistics; + } + + /** + * Sets the detected protocols statistic information. + */ + public void setDetectedProtos(List detectedProtos) { + this.detectedProtos = detectedProtos; + } + + /** + * Sets the known flows information. + */ + public void setKnownFlows(List knownFlows) { + this.knownFlows = knownFlows; + } + + /** + * Sets the unknown flows information. + */ + public void setUnknownFlows(List unknownFlows) { + this.unknownFlows = unknownFlows; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("trafficStatistics", trafficStatistics) + .add("detectedProtos", detectedProtos) + .add("knownFlows", knownFlows) + .add("unknownFlows", unknownFlows) + .toString(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatInfoCodec.java b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatInfoCodec.java new file mode 100644 index 0000000000..d7d3473d9b --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatInfoCodec.java @@ -0,0 +1,151 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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.incubator.net.dpi; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.slf4j.Logger; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.IntStream; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Implementation of encoder for DpiStatInfo codec. + */ +public final class DpiStatInfoCodec extends JsonCodec { + + private static final String TRAFFIC_STATISTICS = "trafficStatistics"; + private static final String DETECTED_PROTOS = "detectedProtos"; + private static final String KNOWN_FLOWS = "knownFlows"; + private static final String UNKNOWN_FLOWS = "unknownFlows"; + + private final Logger log = getLogger(getClass()); + + @Override + public ObjectNode encode(DpiStatInfo dsi, CodecContext context) { + checkNotNull(dsi, "DpiStatInfo cannot be null"); + + final ObjectNode result = context.mapper().createObjectNode(); + + final JsonCodec trafficStatInfoCodec = + context.codec(TrafficStatInfo.class); + + + final TrafficStatInfo tsi = dsi.trafficStatistics(); + if (tsi != null) { + final ObjectNode jsonTrafficStatistics = trafficStatInfoCodec.encode(tsi, context); + result.set(TRAFFIC_STATISTICS, jsonTrafficStatistics); + } + + + final List psi = dsi.detectedProtos(); + if (psi != null) { + final ArrayNode jsonDetectedProtos = result.putArray(DETECTED_PROTOS); + final JsonCodec protocolStatInfoCodec = + context.codec(ProtocolStatInfo.class); + + for (final ProtocolStatInfo protocolStatInfo : psi) { + jsonDetectedProtos.add(protocolStatInfoCodec.encode(protocolStatInfo, context)); + } + } + + List fsi = dsi.knownFlows(); + if (fsi != null) { + final ArrayNode jsonKnownFlows = result.putArray(KNOWN_FLOWS); + final JsonCodec flowStatInfoCodec = + context.codec(FlowStatInfo.class); + + for (final FlowStatInfo flowStatInfo : fsi) { + jsonKnownFlows.add(flowStatInfoCodec.encode(flowStatInfo, context)); + } + } + + fsi = dsi.unknownFlows(); + if (fsi != null) { + final ArrayNode jsonUnknownFlows = result.putArray(UNKNOWN_FLOWS); + final JsonCodec flowStatInfoCodec = + context.codec(FlowStatInfo.class); + + for (final FlowStatInfo flowStatInfo : fsi) { + jsonUnknownFlows.add(flowStatInfoCodec.encode(flowStatInfo, context)); + } + } + + return result; + } + + @Override + public DpiStatInfo decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + log.debug("trafficStatistics={}, full json={} ", json.get("trafficStatistics"), json); + TrafficStatInfo trafficStatInfo = null; + ObjectNode tsJson = get(json, TRAFFIC_STATISTICS); + if (tsJson != null) { + JsonCodec trafficStatInfoJsonCodec = + context.codec(TrafficStatInfo.class); + trafficStatInfo = trafficStatInfoJsonCodec.decode(tsJson, context); + } + + final JsonCodec protocolStatInfoCodec = + context.codec(ProtocolStatInfo.class); + + List detectedProtos = new ArrayList<>(); + JsonNode dpJson = json.get(DETECTED_PROTOS); + if (dpJson != null) { + IntStream.range(0, dpJson.size()) + .forEach(i -> detectedProtos.add( + protocolStatInfoCodec.decode(get(dpJson, i), + context))); + } + + final JsonCodec flowStatInfoCodec = + context.codec(FlowStatInfo.class); + + List knownFlows = new ArrayList<>(); + JsonNode kfJson = json.get(KNOWN_FLOWS); + if (kfJson != null) { + IntStream.range(0, kfJson.size()) + .forEach(i -> knownFlows.add( + flowStatInfoCodec.decode(get(kfJson, i), + context))); + } + + List unknownFlows = new ArrayList<>(); + JsonNode ufJson = json.get(UNKNOWN_FLOWS); + if (ufJson != null) { + IntStream.range(0, ufJson.size()) + .forEach(i -> unknownFlows.add( + flowStatInfoCodec.decode(get(ufJson, i), + context))); + } + + return new DpiStatInfo(trafficStatInfo, + detectedProtos, + knownFlows, + unknownFlows); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatistics.java b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatistics.java new file mode 100644 index 0000000000..6e7d199b46 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatistics.java @@ -0,0 +1,94 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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.incubator.net.dpi; + +import java.util.Objects; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * DPI statistics with received time. + */ +public class DpiStatistics { + private final String receivedTime; + private final DpiStatInfo dpiStatInfo; + + /** + * Constructor for DpiStatistics class. + * + * @param receivedTime dpiStatInfo received time + * @param dpiStatInfo the dpi statistics info + */ + public DpiStatistics(final String receivedTime, final DpiStatInfo dpiStatInfo) { + checkNotNull(receivedTime, "Must specify receivedTime"); + checkNotNull(dpiStatInfo, "Must specify DpiStatInfo"); + + this.receivedTime = receivedTime; + this.dpiStatInfo = dpiStatInfo; + } + + /** + * Returns DPI statistics received time. + * + * @return receivedTime + */ + public String receivedTime() { + return receivedTime; + } + + /** + * Returns DPI statistics information. + * + * @return dpiStatInfo + */ + public DpiStatInfo dpiStatInfo() { + return dpiStatInfo; + } + + @Override + public int hashCode() { + return Objects.hash(receivedTime, dpiStatInfo); + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final DpiStatistics other = (DpiStatistics) obj; + if (!Objects.equals(this.receivedTime, other.receivedTime)) { + return false; + } + if (!Objects.equals(this.dpiStatInfo, other.dpiStatInfo)) { + return false; + } + + return true; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("receivedTime", receivedTime) + .add("dpiStatInfo", dpiStatInfo) + .toString(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatisticsCodec.java b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatisticsCodec.java new file mode 100644 index 0000000000..1e1d1f75d4 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatisticsCodec.java @@ -0,0 +1,73 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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.incubator.net.dpi; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.slf4j.Logger; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Implementation of encoder for DpiStatistics codec. + */ +public final class DpiStatisticsCodec extends JsonCodec { + + private static final String RECEIVED_TIME = "receivedTime"; + private static final String DPI_STATISTICS = "dpiStatistics"; + + private final Logger log = getLogger(getClass()); + + @Override + public ObjectNode encode(DpiStatistics ds, CodecContext context) { + checkNotNull(ds, "DpiStatistics cannot be null"); + + final ObjectNode result = context.mapper().createObjectNode(); + + result.put(RECEIVED_TIME, ds.receivedTime()); + + final JsonCodec dpiStatInfoCodec = + context.codec(DpiStatInfo.class); + + final ObjectNode jsonDpiStatInfo = dpiStatInfoCodec.encode(ds.dpiStatInfo(), context); + result.set(DPI_STATISTICS, jsonDpiStatInfo); + + return result; + } + + @Override + public DpiStatistics decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + log.debug("receivedTime={}, full json={} ", json.get("receivedTime"), json); + JsonNode receivedTimeJson = json.get(RECEIVED_TIME); + String receivedTime = receivedTimeJson == null ? "" : receivedTimeJson.asText(); + + final JsonCodec dpiStatInfoCodec = + context.codec(DpiStatInfo.class); + + DpiStatInfo dpiStatInfo = + dpiStatInfoCodec.decode(get(json, DPI_STATISTICS), context); + + return new DpiStatistics(receivedTime, dpiStatInfo); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatisticsManagerService.java b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatisticsManagerService.java new file mode 100644 index 0000000000..792c293671 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/DpiStatisticsManagerService.java @@ -0,0 +1,84 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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.incubator.net.dpi; + +import java.util.List; + +/** + * Service for DPI Statistics Service Manager. + */ +public interface DpiStatisticsManagerService { + /** + * Get the latest DpiStatistics in the Store list. + * + * @return the DpiStatistics object class or null if not exist + */ + DpiStatistics getDpiStatisticsLatest(); + + /** + * Get the latest DpiStatistics in the Store list. + * + * @param topnProtocols detected topn protocols, default = 100 + * @param topnFlows detected topn known and unknown flows , default = 100 + * + * @return the DpiStatistics object class or null if not exist + */ + DpiStatistics getDpiStatisticsLatest(int topnProtocols, int topnFlows); + + /** + * Gets the last N(Max = 100) DpiStatistics in the Store list. + * + * @return the List of DpiStatistics object class + */ + List getDpiStatistics(int lastN); + + /** + * Gets the last N(Max = 100) DpiStatistics in the Store list. + * + * @param lastN latest N entries + * @param topnProtocols detected topn protocols, default = 100 + * @param topnFlows detected topn known and unknown flows , default = 100 + * @return the List of DpiStatistics object class + */ + List getDpiStatistics(int lastN, int topnProtocols, int topnFlows); + + /** + * Get the specified receivedTime DpiStatistics in the Store list. + * + * @param receivedTime receivedTime string with format "yyyy-MM-dd HH:mm:ss" + * @return the DpiStatistics object class or null if not exist + */ + DpiStatistics getDpiStatistics(String receivedTime); + + /** + * Get the specified receivedTime DpiStatistics in the Store list. + * + * @param receivedTime receivedTime string with format "yyyy-MM-dd HH:mm:ss" + * @param topnProtocols detected topn protocols, default = 100 + * @param topnFlows detected topn known and unknown flows , default = 100 + * @return the DpiStatistics object class or null if not exist + */ + DpiStatistics getDpiStatistics(String receivedTime, int topnProtocols, int topnFlows); + + /** + * Adds DpiStatistics at the end of the Store list. + * + * @return the added DpiStatistics object class + */ + DpiStatistics addDpiStatistics(DpiStatistics ds); + +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/FlowStatInfo.java b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/FlowStatInfo.java new file mode 100644 index 0000000000..591df78d41 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/FlowStatInfo.java @@ -0,0 +1,230 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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.incubator.net.dpi; + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * Flow statistic information. + */ +public class FlowStatInfo { + String protocol; + String hostAName; + int hostAPort; + String hostBName; + int hostBPort; + int detectedProtocol; + String detectedProtocolName; + long packets; + long bytes; + String hostServerName; + + /** + * Constructor for default FlowStatInfo class. + */ + public FlowStatInfo() { + protocol = ""; + hostAName = "::"; + hostAPort = 0; + hostBName = ""; + hostBPort = 0; + detectedProtocol = 0; + detectedProtocolName = ""; + packets = 0; + bytes = 0; + + hostServerName = ""; + } + + /** + * Constructor for FlowStatInfo class specified with flow statistic parameters. + */ + public FlowStatInfo(String protocol, String hostAName, int hostAPort, String hostBName, int hostBPort, + int detectedProtocol, String detectedProtocolName, long packets, long bytes) { + this.protocol = protocol; + this.hostAName = hostAName; + this.hostAPort = hostAPort; + this.hostBName = hostBName; + this.hostBPort = hostBPort; + this.detectedProtocol = detectedProtocol; + this.detectedProtocolName = detectedProtocolName; + this.packets = packets; + this.bytes = bytes; + + hostServerName = ""; + } + + /** + * Constructor for FlowStatInfo class specified with flow statistic parameters and hostServerName. + */ + public FlowStatInfo(String protocol, String hostAName, int hostAPort, String hostBName, int hostBPort, + int detectedProtocol, String detectedProtocolName, long packets, long bytes, + String hostServerName) { + this(protocol, hostAName, hostAPort, hostBName, hostBPort, detectedProtocol, detectedProtocolName, + packets, bytes); + + this.hostServerName = hostServerName; + } + + /** + * Returns DPI flow protocol. + * + * @return protocol + */ + public String protocol() { + return protocol; + } + + /** + * Returns DPI flow host A name. + * + * @return hostAName + */ + public String hostAName() { + return hostAName; + } + + /** + * Returns DPI flow host A port. + * + * @return hostAPort + */ + public int hostAPort() { + return hostAPort; + } + + + /** + * Returns DPI flow host B name. + * + * @return hostBName + */ + public String hostBName() { + return hostBName; + } + + /** + * Returns DPI flow host B Port. + * + * @return hostBPort + */ + public int hostBPort() { + return hostBPort; + } + + /** + * Returns DPI flow detected protocol. + * + * @return detectedProtocol + */ + public int detectedProtocol() { + return detectedProtocol; + } + + /** + * Returns DPI flow detected protocol name. + * + * @return detectedProtocolName + */ + public String detectedProtocolName() { + return detectedProtocolName; + } + + /** + * Returns DPI flow packets. + * + * @return packets + */ + public long packets() { + return packets; + } + + /** + * Returns DPI flow bytes. + * + * @return bytes + */ + public long bytes() { + return bytes; + } + + /** + * Returns DPI flow host server name. + * + * @return hostServerName + */ + public String hostServerName() { + return hostServerName; + } + + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public void setHostAName(String hostAName) { + this.hostAName = hostAName; + } + + public void setHostAPort(int hostAPort) { + this.hostAPort = hostAPort; + } + + public void setHostBName(String hostBName) { + this.hostBName = hostBName; + } + + public void setHostBPort(int hostBPort) { + this.hostBPort = hostBPort; + } + + public void setDetectedProtocol(int detectedProtocol) { + this.detectedProtocol = detectedProtocol; + } + + public void setDetectedProtocolName(String detectedProtocolName) { + this.detectedProtocolName = detectedProtocolName; + } + + public void setPackets(long packets) { + this.packets = packets; + } + + public void setBytes(long bytes) { + this.bytes = bytes; + } + + public void setHostServerName(String hostServerName) { + this.hostServerName = hostServerName; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("protocol", protocol) + .add("hostAName", hostAName) + .add("hostAPort", hostAPort) + .add("hostBName", hostBName) + .add("hostBPort", hostBPort) + .add("detectedProtocol", detectedProtocol) + .add("detectedProtocolName", detectedProtocolName) + .add("packets", packets) + .add("bytes", bytes) + .add("hostServerName", hostServerName) + .toString(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/FlowStatInfoCodec.java b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/FlowStatInfoCodec.java new file mode 100644 index 0000000000..d32ff6c7d9 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/FlowStatInfoCodec.java @@ -0,0 +1,74 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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.incubator.net.dpi; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.slf4j.Logger; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Implementation of encoder for FlowStatInfo codec. + */ +public final class FlowStatInfoCodec extends JsonCodec { + + private final Logger log = getLogger(getClass()); + + @Override + public ObjectNode encode(FlowStatInfo fsi, CodecContext context) { + checkNotNull(fsi, "FlowStatInfo cannot be null"); + + return context.mapper().createObjectNode() + .put("protocol", fsi.protocol()) + .put("hostAName", fsi.hostAName()) + .put("hostAPort", fsi.hostAPort()) + .put("hostBName", fsi.hostBName()) + .put("hostBPort", fsi.hostBPort()) + .put("detectedProtocol", fsi.detectedProtocol()) + .put("detectedProtocolName", fsi.detectedProtocolName()) + .put("packets", fsi.packets()) + .put("bytes", fsi.bytes()) + .put("hostServerName", fsi.hostServerName()); + } + + @Override + public FlowStatInfo decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + log.debug("protocol={}, full json={} ", json.get("protocol"), json); + final String protocol = json.get("protocol").asText(); + final String hostAName = json.get("hostAName").asText(); + final int hostAPort = json.get("hostAPort").asInt(); + final String hostBName = json.get("hostBName").asText(); + final int hostBPort = json.get("hostBPort").asInt(); + final int detectedProtocol = json.get("detectedProtocol").asInt(); + final String detectedProtocolName = json.get("detectedProtocolName").asText(); + final long packets = json.get("packets").asLong(); + final long bytes = json.get("bytes").asLong(); + final String hostServerName = json.get("hostServerName").asText(); + + return new FlowStatInfo(protocol, + hostAName, hostAPort, hostBName, hostBPort, + detectedProtocol, detectedProtocolName, + packets, bytes, hostServerName); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/ProtocolStatInfo.java b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/ProtocolStatInfo.java new file mode 100644 index 0000000000..372deff99c --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/ProtocolStatInfo.java @@ -0,0 +1,135 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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.incubator.net.dpi; + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * Protocol statistic information. + */ +public class ProtocolStatInfo { + String name; + String breed; + long packets; + long bytes; + int flows; + + /** + * Constructor for default ProtocolStatInfo class. + */ + public ProtocolStatInfo() { + name = ""; + breed = ""; + packets = 0; + bytes = 0; + flows = 0; + } + + /** + * Constructor for ProtocolStatInfo class specified with protocol statistic parameters. + * + * @param name protocol name + * @param breed protocol breed + * @param packets protocol packets + * @param bytes protocol bytes + * @param flows protocol flows + */ + public ProtocolStatInfo(String name, String breed, long packets, long bytes, int flows) { + this.name = name; + this.breed = breed; + this.packets = packets; + this.bytes = bytes; + this.flows = flows; + } + + /** + * Returns DPI protocol name. + * + * @return name + */ + public String name() { + return name; + } + + /** + * Returns DPI protocol breed. + * + * @return breed + */ + public String breed() { + return breed; + } + + /** + * Returns DPI protocol packets. + * + * @return packets + */ + public long packets() { + return packets; + } + + /** + * Returns DPI protocol bytes. + * + * @return bytes + */ + public long bytes() { + return bytes; + } + + /** + * Returns DPI protocol flows. + * + * @return flows + */ + public int flows() { + return flows; + } + + + public void setName(String name) { + this.name = name; + } + + public void setBreed(String breed) { + this.breed = breed; + } + + public void setPackets(long packets) { + this.packets = packets; + } + + public void setBytes(long bytes) { + this.bytes = bytes; + } + + public void setFlows(int flows) { + this.flows = flows; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("name", name) + .add("breed", breed) + .add("packets", packets) + .add("bytes", bytes) + .add("flows", flows) + .toString(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/ProtocolStatInfoCodec.java b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/ProtocolStatInfoCodec.java new file mode 100644 index 0000000000..24ef9fc2e9 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/ProtocolStatInfoCodec.java @@ -0,0 +1,61 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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.incubator.net.dpi; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.slf4j.Logger; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Implementation of encoder for ProtocolStatInfo codec. + */ +public final class ProtocolStatInfoCodec extends JsonCodec { + + private final Logger log = getLogger(getClass()); + + @Override + public ObjectNode encode(ProtocolStatInfo psi, CodecContext context) { + checkNotNull(psi, "ProtocolStatInfo cannot be null"); + + return context.mapper().createObjectNode() + .put("name", psi.name()) + .put("breed", psi.breed()) + .put("packets", psi.packets()) + .put("bytes", psi.bytes()) + .put("flows", psi.flows()); + } + + @Override + public ProtocolStatInfo decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + log.debug("name={}, full json={} ", json.get("name"), json); + final String name = json.get("name").asText(); + final String breed = json.get("breed").asText(); + final long packets = json.get("packets").asLong(); + final long bytes = json.get("bytes").asLong(); + final int flows = json.get("flows").asInt(); + + return new ProtocolStatInfo(name, breed, packets, bytes, flows); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/TrafficStatInfo.java b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/TrafficStatInfo.java new file mode 100644 index 0000000000..e7e4ecec57 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/TrafficStatInfo.java @@ -0,0 +1,308 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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.incubator.net.dpi; + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * Traffic statistic information. + */ +public class TrafficStatInfo { + long ethernetBytes; + long discardedBytes; + long ipPackets; + long totalPackets; + long ipBytes; + int avgPktSize; + int uniqueFlows; + long tcpPackets; + long udpPackets; + + double dpiThroughputPps; + double dpiThroughputBps; + double trafficThroughputPps; + double trafficThroughputBps; + double trafficDurationSec; + int guessedFlowProtos; + + static final String PPS_STRING = "pps"; + static final String BPS_STRING = "bps"; + static final String SEC_STRING = "sec"; + + /** + * Constructor for default TrafficStatInfo class. + */ + public TrafficStatInfo() { + ethernetBytes = 0; + discardedBytes = 0; + ipPackets = 0; + totalPackets = 0; + ipBytes = 0; + avgPktSize = 0; + uniqueFlows = 0; + tcpPackets = 0; + udpPackets = 0; + dpiThroughputPps = 0; + dpiThroughputBps = 0; + trafficThroughputPps = 0; + trafficThroughputBps = 0; + trafficDurationSec = 0; + guessedFlowProtos = 0; + } + + /** + * Constructor for TrafficStatInfo class specified with traffic statistic parameters. + */ + public TrafficStatInfo(long ethernetBytes, long discardedBytes, long ipPackets, long totalPackets, + long ipBytes, int avgPktSize, int uniqueFlows, long tcpPackets, long udpPackets, + double dpiThroughputPps, double dpiThroughputBps, + double trafficThroughputPps, double trafficThroughputBps, + double trafficDurationSec, int guessedFlowProtos) { + this.ethernetBytes = ethernetBytes; + this.discardedBytes = discardedBytes; + this.ipPackets = ipPackets; + this.totalPackets = totalPackets; + this.ipBytes = ipBytes; + this.avgPktSize = avgPktSize; + this.uniqueFlows = uniqueFlows; + this.tcpPackets = tcpPackets; + this.udpPackets = udpPackets; + this.dpiThroughputPps = dpiThroughputPps; + this.dpiThroughputBps = dpiThroughputBps; + this.trafficThroughputPps = trafficThroughputPps; + this.trafficThroughputBps = trafficThroughputBps; + this.trafficDurationSec = trafficDurationSec; + this.guessedFlowProtos = guessedFlowProtos; + } + + /** + * Returns DPI traffic ethernet bytes. + * + * @return ethernetBytes + */ + public long ethernetBytes() { + return ethernetBytes; + } + + /** + * Returns DPI traffic discarded bytes. + * + * @return discardedBytes + */ + public long discardedBytes() { + return discardedBytes; + } + + /** + * Returns DPI traffic ip packets. + * + * @return ipPackets + */ + public long ipPackets() { + return ipPackets; + } + + /** + * Returns DPI traffic total packets. + * + * @return totalPackets + */ + public long totalPackets() { + return totalPackets; + } + + /** + * Returns DPI traffic ip bytes. + * + * @return ipBytes + */ + public long ipBytes() { + return ipBytes; + } + + /** + * Returns DPI traffic average packet size. + * + * @return avgPktSize + */ + public int avgPktSize() { + return avgPktSize; + } + + /** + * Returns DPI traffic the number of unique flows. + * + * @return uniqueFlows + */ + public int uniqueFlows() { + return uniqueFlows; + } + + /** + * Returns DPI traffic TCP packets. + * + * @return tcpPackets + */ + public long tcpPackets() { + return tcpPackets; + } + + /** + * Returns DPI traffic UDP packets. + * + * @return udpPackets + */ + public long udpPackets() { + return udpPackets; + } + + /** + * Returns DPI traffic throughput Pps(Packet per second). + * + * @return dpiThroughputPps + */ + public double dpiThroughputPps() { + return dpiThroughputPps; + } + + /** + * Returns DPI traffic throughput Bps(Byte per second). + * + * @return dpiThroughputBps + */ + public double dpiThroughputBps() { + return dpiThroughputBps; + } + + /** + * Returns total traffic throughput Pps(Packet per second). + * + * @return trafficThroughputPps + */ + public double trafficThroughputPps() { + return trafficThroughputPps; + } + + /** + * Returns total traffic throughput Bps(Byte per second). + * + * @return trafficThroughputBps + */ + public double trafficThroughputBps() { + return trafficThroughputBps; + } + + /** + * Returns DPI traffic duration second. + * + * @return trafficDurationSec + */ + public double trafficDurationSec() { + return trafficDurationSec; + } + + /** + * Returns DPI traffic the number of guessed flow protocols. + * + * @return guessedFlowProtos + */ + public int guessedFlowProtos() { + return guessedFlowProtos; + } + + + public void setEthernetBytes(long ethernetBytes) { + this.ethernetBytes = ethernetBytes; + } + + public void setDiscardedBytes(long discardedBytes) { + this.discardedBytes = discardedBytes; + } + + public void setIpPackets(long ipPackets) { + this.ipPackets = ipPackets; + } + + public void setTotalPackets(long totalPackets) { + this.totalPackets = totalPackets; + } + + public void setIpBytes(long ipBytes) { + this.ipBytes = ipBytes; + } + + public void setAvgPktSize(int avgPktSize) { + this.avgPktSize = avgPktSize; + } + + public void setUniqueFlows(int uniqueFlows) { + this.uniqueFlows = uniqueFlows; + } + + public void setTcpPackets(long tcpPackets) { + this.tcpPackets = tcpPackets; + } + + public void setUdpPackets(long udpPackets) { + this.udpPackets = udpPackets; + } + + public void setDpiThroughputPps(double dpiThroughputPps) { + this.dpiThroughputPps = dpiThroughputPps; + } + + public void setDpiThroughputBps(double dpiThroughputBps) { + this.dpiThroughputBps = dpiThroughputBps; + } + + public void setTrafficThroughputPps(double trafficThroughputPps) { + this.trafficThroughputPps = trafficThroughputPps; + } + + public void setTrafficThroughputBps(double trafficThroughputBps) { + this.trafficThroughputBps = trafficThroughputBps; + } + + public void setTrafficDurationSec(double trafficDurationSec) { + this.trafficDurationSec = trafficDurationSec; + } + + public void setGuessedFlowProtos(int guessedFlowProtos) { + this.guessedFlowProtos = guessedFlowProtos; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("ethernetBytes", ethernetBytes) + .add("discardedBytes", discardedBytes) + .add("ipPackets", ipPackets) + .add("totalPackets", totalPackets) + .add("ipBytes", ipBytes) + .add("avgPktSize", avgPktSize) + .add("uniqueFlows", uniqueFlows) + .add("tcpPackets", tcpPackets) + .add("udpPackets", udpPackets) + .add("dpiThroughputPps", dpiThroughputPps + " " + PPS_STRING) + .add("dpiThroughputBps", dpiThroughputBps + " " + BPS_STRING) + .add("trafficThroughputPps", trafficThroughputPps + " " + PPS_STRING) + .add("trafficThroughputBps", trafficThroughputBps + " " + BPS_STRING) + .add("trafficDurationSec", trafficDurationSec + " " + SEC_STRING) + .add("guessedFlowProtos", guessedFlowProtos) + .toString(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/TrafficStatInfoCodec.java b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/TrafficStatInfoCodec.java new file mode 100644 index 0000000000..7f9ace8b6e --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/TrafficStatInfoCodec.java @@ -0,0 +1,90 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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.incubator.net.dpi; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.slf4j.Logger; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Implementation of encoder for TrafficStatInfo codec. + */ +public final class TrafficStatInfoCodec extends JsonCodec { + + private final Logger log = getLogger(getClass()); + + @Override + public ObjectNode encode(TrafficStatInfo tsi, CodecContext context) { + checkNotNull(tsi, "TrafficStatInfo cannot be null"); + + return context.mapper().createObjectNode() + .put("ethernetBytes", tsi.ethernetBytes()) + .put("discardedBytes", tsi.discardedBytes()) + .put("ipPackets", tsi.ipPackets()) + .put("totalPackets", tsi.totalPackets()) + .put("ipBytes", tsi.ipBytes()) + .put("avgPktSize", tsi.avgPktSize()) + .put("uniqueFlows", tsi.uniqueFlows()) + .put("tcpPackets", tsi.tcpPackets()) + .put("udpPackets", tsi.udpPackets()) + .put("dpiThroughputPps", tsi.dpiThroughputPps()) + .put("dpiThroughputBps", tsi.dpiThroughputBps()) + .put("trafficThroughputPps", tsi.trafficThroughputPps()) + .put("trafficThroughputBps", tsi.trafficThroughputBps()) + .put("trafficDurationSec", tsi.trafficDurationSec()) + .put("guessedFlowProtos", tsi.guessedFlowProtos()); + } + + @Override + public TrafficStatInfo decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + log.debug("ethernetBytes={}, full json={} ", json.get("ethernetBytes"), json); + final Long ethernetBytes = json.get("ethernetBytes").asLong(); + final Long discardedBytes = json.get("discardedBytes").asLong(); + final Long ipPackets = json.get("ipPackets").asLong(); + final Long totalPackets = json.get("totalPackets").asLong(); + final Long ipBytes = json.get("ipBytes").asLong(); + final int avgPktSize = json.get("avgPktSize").asInt(); + final int uniqueFlows = json.get("uniqueFlows").asInt(); + final Long tcpPackets = json.get("tcpPackets").asLong(); + final Long udpPackets = json.get("udpPackets").asLong(); + final double dpiThroughputPps = json.get("dpiThroughputPps").asDouble(); + final double dpiThroughputBps = json.get("dpiThroughputBps").asDouble(); + final double trafficThroughputPps = json.get("trafficThroughputPps").asDouble(); + final double trafficThroughputBps = json.get("trafficThroughputBps").asDouble(); + final double trafficDurationSec = json.get("trafficDurationSec").asDouble(); + final int guessedFlowProtos = json.get("guessedFlowProtos").asInt(); + + return new TrafficStatInfo(ethernetBytes, + discardedBytes, + ipPackets, totalPackets, + ipBytes, avgPktSize, + uniqueFlows, + tcpPackets, udpPackets, + dpiThroughputPps, dpiThroughputBps, + trafficThroughputPps, trafficThroughputBps, + trafficDurationSec, + guessedFlowProtos); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/package-info.java b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/package-info.java new file mode 100644 index 0000000000..6ee300cff6 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/dpi/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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. + */ + +/** + * Subsystem for dpi statistics service. + */ +package org.onosproject.incubator.net.dpi; \ No newline at end of file diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/dpi/impl/DpiStatisticsManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/dpi/impl/DpiStatisticsManager.java new file mode 100644 index 0000000000..23cb8b838e --- /dev/null +++ b/incubator/net/src/main/java/org/onosproject/incubator/net/dpi/impl/DpiStatisticsManager.java @@ -0,0 +1,478 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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.incubator.net.dpi.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; + +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +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 org.osgi.service.component.ComponentContext; +import org.slf4j.Logger; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.ServerSocket; +import java.net.Socket; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.SortedMap; +import java.util.TimeZone; +import java.util.TreeMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static java.lang.Thread.sleep; +import static org.onlab.util.Tools.groupedThreads; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * DPI Statistics Manager. + */ +@Component(immediate = true) +@Service +public class DpiStatisticsManager implements DpiStatisticsManagerService { + + private static ServerSocket serverSocket; + private static int port = 11990; // socket server listening port + + private final Logger log = getLogger(getClass()); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + private ApplicationId appId; + + private final ExecutorService dpiListenerThread = + Executors.newSingleThreadExecutor(groupedThreads("onos/apps/dpi", "dpi-listener")); + + DpiStatisticsListener dpiStatisticsListener = null; + + // 31*2(month)*24(hour)*3600(second)/5(second) + private static final int MAX_DPI_STATISTICS_ENTRY = 1071360; + + private SortedMap dpiStatisticsMap = + new TreeMap<>(new MapComparator()); + + private long convertTimeToLong(String timeString) { + long timeLong = 0; + + try { + // Time format: yyyy-MM-dd HH:mm:ss, Time Zone: GMT + SimpleDateFormat df = new SimpleDateFormat(DATE_FMT, Locale.KOREA); + df.setTimeZone(TimeZone.getTimeZone(TIME_ZONE)); + + timeLong = df.parse(timeString).getTime(); + } catch (ParseException e) { + log.error("Time parse error! Exception={}", e.toString()); + } + + return timeLong; + } + + private static final String DATE_FMT = "yyyy-MM-dd HH:mm:ss"; + private static final String TIME_ZONE = "GMT"; + + public static final int MAX_DPI_STATISTICS_REQUEST = 100; + public static final int MAX_DPI_STATISTICS_TOPN = 100; + + @Activate + public void activate(ComponentContext context) { + appId = coreService.registerApplication("org.onosproject.dpi"); + + dpiStatisticsListener = new DpiStatisticsListener(); + dpiListenerThread.execute(dpiStatisticsListener); + + log.info("Started", appId.id()); + } + + @Deactivate + public void deactivate() { + log.info("Deactivated..."); + dpiStatisticsListener.stop(); + dpiListenerThread.shutdown(); + log.info("Stopped"); + } + + @Override + public DpiStatistics getDpiStatisticsLatest() { + if (dpiStatisticsMap.size() > 0) { + return dpiStatisticsMap.get(dpiStatisticsMap.firstKey()); + } else { + return null; + } + } + + @Override + public DpiStatistics getDpiStatisticsLatest(int topnProtocols, int topnFlows) { + DpiStatistics ds, topnDs; + + ds = getDpiStatisticsLatest(); + topnDs = processTopn(ds, topnProtocols, topnFlows); + + return topnDs; + } + + @Override + public List getDpiStatistics(int lastN) { + List dsList = new ArrayList<>(); + DpiStatistics ds; + + if (lastN > MAX_DPI_STATISTICS_REQUEST) { + lastN = MAX_DPI_STATISTICS_REQUEST; + } + + SortedMap tempMap = new TreeMap(new MapComparator()); + tempMap.putAll(dpiStatisticsMap); + + for (int i = 0; i < lastN && i < tempMap.size(); i++) { + ds = (DpiStatistics) tempMap.get(tempMap.firstKey()); + dsList.add(i, new DpiStatistics(ds.receivedTime(), ds.dpiStatInfo())); + + tempMap.remove(tempMap.firstKey()); + } + + return dsList; + } + + @Override + public List getDpiStatistics(int lastN, int topnProtocols, int topnFlows) { + List dsList; + List topnDsList = new ArrayList<>(); + DpiStatistics ds, topnDs; + + dsList = getDpiStatistics(lastN); + for (int i = 0; i < dsList.size(); i++) { + ds = dsList.get(i); + topnDs = processTopn(ds, topnProtocols, topnFlows); + topnDsList.add(i, topnDs); + } + + return topnDsList; + } + + @Override + public DpiStatistics getDpiStatistics(String receivedTime) { + DpiStatistics ds; + + if (receivedTime == null) { + return null; + } + + if (!dpiStatisticsMap.containsKey(receivedTime)) { + return null; + } + + ds = dpiStatisticsMap.get(receivedTime); + + return ds; + } + + @Override + public DpiStatistics getDpiStatistics(String receivedTime, int topnProtocols, int topnFlows) { + DpiStatistics ds, topnDs; + + ds = getDpiStatistics(receivedTime); + + topnDs = processTopn(ds, topnProtocols, topnFlows); + + return topnDs; + } + + @Override + public DpiStatistics addDpiStatistics(DpiStatistics ds) { + if (ds == null) { + return ds; + } + + // check the time. The firstKey is lastTime because of descending sorted order + if (dpiStatisticsMap.size() > 0) { + String lastTime = dpiStatisticsMap.get(dpiStatisticsMap.firstKey()).receivedTime(); + String inputTime = ds.receivedTime(); + + long lastTimeLong = convertTimeToLong(lastTime); + long inputTimeLong = convertTimeToLong(inputTime); + + if (lastTimeLong >= inputTimeLong) { + return null; + } + } + + if (dpiStatisticsMap.size() >= MAX_DPI_STATISTICS_ENTRY) { + // remove the last (oldest) entry + dpiStatisticsMap.remove(dpiStatisticsMap.lastKey()); + } + + if (dpiStatisticsMap.containsKey(ds.receivedTime())) { + log.warn("addDpiStatistics(), {} dpiStatistics is already existing!", + ds.receivedTime()); + return null; + } + + dpiStatisticsMap.put(ds.receivedTime(), ds); + log.debug("addDpiStatistics: dpiResultJson data[time={}] is added " + + "into DpiStatisticsMap size={}.", + ds.receivedTime(), dpiStatisticsMap.size()); + + return ds; + } + + private class MapComparator implements Comparator { + @Override + public int compare(String rt1, String rt2) { + long rt1Long = convertTimeToLong(rt1); + long rt2Long = convertTimeToLong(rt2); + + // Descending order + if (rt1Long > rt2Long) { + return -1; + } else if (rt1Long < rt2Long) { + return 1; + } else { + return 0; + } + } + } + + private class ProtocolComparator implements Comparator { + @Override + public int compare(ProtocolStatInfo p1, ProtocolStatInfo p2) { + //Descending order + if (p1.bytes() > p2.bytes()) { + return -1; + } else if (p1.bytes() < p2.bytes()) { + return 1; + } else { + return 0; + } + } + } + + private class FlowComparator implements Comparator { + @Override + public int compare(FlowStatInfo f1, FlowStatInfo f2) { + // Descending order + if (f1.bytes() > f2.bytes()) { + return -1; + } else if (f1.bytes() < f2.bytes()) { + return 1; + } else { + return 0; + } + } + } + private DpiStatistics processTopn(DpiStatistics ds, int topnProtocols, int topnFlows) { + if (ds == null) { + return null; + } + + if (topnProtocols <= 0) { + // displays all entries + topnProtocols = 0; + } else if (topnProtocols > MAX_DPI_STATISTICS_TOPN) { + topnProtocols = MAX_DPI_STATISTICS_TOPN; + } + + if (topnFlows <= 0) { + // displays all entries + topnFlows = 0; + } else if (topnFlows > MAX_DPI_STATISTICS_TOPN) { + topnFlows = MAX_DPI_STATISTICS_TOPN; + } + + if (topnProtocols == 0 && topnFlows == 0) { + return ds; + } + + TrafficStatInfo tsi = ds.dpiStatInfo().trafficStatistics(); + List psiList; + List kfList; + List ufList; + + List pList = ds.dpiStatInfo().detectedProtos(); + Collections.sort(pList, new ProtocolComparator()); + if (topnProtocols > 0 && topnProtocols < pList.size()) { + psiList = pList.subList(0, topnProtocols); + } else { + psiList = pList; + } + + + List fList = ds.dpiStatInfo().knownFlows(); + Collections.sort(fList, new FlowComparator()); + if (topnFlows > 0 && topnFlows < fList.size()) { + kfList = fList.subList(0, topnFlows); + } else { + kfList = fList; + } + + fList = ds.dpiStatInfo().unknownFlows(); + Collections.sort(fList, new FlowComparator()); + if (topnFlows > 0 && topnFlows < fList.size()) { + ufList = fList.subList(0, topnFlows); + } else { + ufList = fList; + } + + DpiStatInfo dsi = new DpiStatInfo(); + dsi.setTrafficStatistics(tsi); + dsi.setDetectedProtos(psiList); + dsi.setKnownFlows(kfList); + dsi.setUnknownFlows(ufList); + + DpiStatistics retDs = new DpiStatistics(ds.receivedTime(), dsi); + return retDs; + } + + /** + * Receiving DPI Statistics result thread. + */ + private class DpiStatisticsListener implements Runnable { + Socket clientSocket = null; + BufferedReader in = null; + PrintWriter out = null; + + String resultJsonString = null; + + static final int MAX_SLEEP_COUNT = 10; + int sleepCount = 0; + + @Override + public void run() { + log.info("DpiStatisticsListener: Receiving thread started..."); + receiveDpiResult(); + } + + public void stop() { + try { + if (serverSocket != null) { + if (clientSocket != null) { + if (in != null) { + in.close(); + } + if (out != null) { + out.close(); + } + clientSocket.close(); + //log.debug("DpiResultListener: stop(): Socket close() is done..."); + } + serverSocket.close(); + //log.debug("DpiResultListener: stop(): Server close() is done..."); + } + } catch (Exception e) { + log.error("DpiStatisticsListener: stop(): Server Socket closing error, exception={}", + e.toString()); + } + log.debug("DpiStatisticsListener: stop(): stopped..."); + } + + private void receiveDpiResult() { + try { + serverSocket = new ServerSocket(port); + } catch (Exception e) { + log.error("DpiStatisticsListener: ServerSocket listening error from port={} in localhost, exception={}", + port, e.toString()); + return; + } + + try { + while (true) { + if (clientSocket == null) { + log.info("DpiStatisticsListener: Waiting for accepting from dpi client..."); + clientSocket = serverSocket.accept(); + log.info("DpiStatisticsListener: Accepted from dpi client={}", + clientSocket.getRemoteSocketAddress().toString()); + + in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + out = new PrintWriter(clientSocket.getOutputStream(), true); // For disconnecting check! + + resultJsonString = null; + } + + sleepCount = 0; + while (!in.ready()) { + sleep(1000); // sleep one second. + if (out.checkError() || ++sleepCount >= MAX_SLEEP_COUNT) { + log.debug("DpiStatisticsListener: server and socket connect is lost..."); + in.close(); + in = null; + out.close(); + out = null; + clientSocket.close(); + clientSocket = null; + + break; + } + } + + if (in != null) { + resultJsonString = in.readLine(); + + // process the result + log.trace("DpiStatisticsListener: resultJsonString={}", resultJsonString); + processResultJson(resultJsonString); + } + } + } catch (Exception e) { + log.error("DpiStatisticsListener: Exception = {}", e.toString()); + return; + } + } + + private void processResultJson(String resultJsonString) { + Date tr = new Date(System.currentTimeMillis()); + SimpleDateFormat df = new SimpleDateFormat(DATE_FMT, Locale.KOREA); + df.setTimeZone(TimeZone.getTimeZone(TIME_ZONE)); + + String curReceivedTime = new String(df.format(tr)); + String curResultJson = new String(resultJsonString); + + DpiStatInfo dpiStatInfo; + ObjectMapper mapper = new ObjectMapper(); + try { + dpiStatInfo = mapper.readValue(curResultJson, DpiStatInfo.class); + } catch (IOException e) { + log.error("DpiStatisticsListener: ObjectMapper Exception = {}", e.toString()); + return; + } + + DpiStatistics dpiStatistics = new DpiStatistics(curReceivedTime, dpiStatInfo); + + addDpiStatistics(dpiStatistics); + } + } +} diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/dpi/impl/package-info.java b/incubator/net/src/main/java/org/onosproject/incubator/net/dpi/impl/package-info.java new file mode 100644 index 0000000000..afc6313dc5 --- /dev/null +++ b/incubator/net/src/main/java/org/onosproject/incubator/net/dpi/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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. + */ + +/** + * Implementation of the dpi statistics service. + */ +package org.onosproject.incubator.net.dpi.impl; \ No newline at end of file diff --git a/web/api/src/main/java/org/onosproject/rest/resources/CoreWebApplication.java b/web/api/src/main/java/org/onosproject/rest/resources/CoreWebApplication.java index b8597fa578..b92038b866 100644 --- a/web/api/src/main/java/org/onosproject/rest/resources/CoreWebApplication.java +++ b/web/api/src/main/java/org/onosproject/rest/resources/CoreWebApplication.java @@ -51,7 +51,8 @@ public class CoreWebApplication extends AbstractWebApplication { TenantWebResource.class, VirtualNetworkWebResource.class, MastershipWebResource.class, - InvalidConfigExceptionMapper.class + InvalidConfigExceptionMapper.class, + DpisWebResource.class ); } } diff --git a/web/api/src/main/java/org/onosproject/rest/resources/DpisWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/DpisWebResource.java new file mode 100644 index 0000000000..6b01b13153 --- /dev/null +++ b/web/api/src/main/java/org/onosproject/rest/resources/DpisWebResource.java @@ -0,0 +1,308 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * 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.rest.resources; + +import com.fasterxml.jackson.databind.node.ObjectNode; +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.rest.AbstractWebResource; +import org.slf4j.Logger; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Query the latest DPI statistics info. + */ + +@Path("dpis") +public class DpisWebResource extends AbstractWebResource { + + private final Logger log = getLogger(getClass()); + + private static final int MAX_TOPN = 100; + + private final DpiStatisticsManagerService service = get(DpiStatisticsManagerService.class); + + public static final Comparator PROTOCOL_STAT_INFO_COMPARATOR = + new Comparator() { + @Override + public int compare(ProtocolStatInfo psi1, ProtocolStatInfo psi2) { + long delta = psi1.bytes() - psi2.bytes(); + return delta == 0 ? 0 : (delta > 0 ? -1 : +1); + } + }; + + public static final Comparator FLOW_STAT_INFO_COMPARATOR = + new Comparator() { + @Override + public int compare(FlowStatInfo fsi1, FlowStatInfo fsi2) { + long delta = fsi1.bytes() - fsi2.bytes(); + return delta == 0 ? 0 : (delta > 0 ? -1 : +1); + } + }; + + /** + * Gets the latest dpi statistics. + * + * @return 200 OK with a dpi statistics + * @onos.rsModel DpiStatistics + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getDpisLatest(@QueryParam("topn") int topn) { + log.debug("getDpisLatest request with topn={}", topn); + + DpiStatistics ds = service.getDpiStatisticsLatest(); + DpiStatistics retDs; + + if (ds == null) { + retDs = new DpiStatistics("", new DpiStatInfo()); + } else if (topn <= 0) { + retDs = ds; + } else { + if (topn > MAX_TOPN) { + topn = MAX_TOPN; + } + retDs = new DpiStatistics(ds.receivedTime(), + new DpiStatInfo(ds.dpiStatInfo().trafficStatistics())); + List psiList = ds.dpiStatInfo().detectedProtos(); + if (psiList != null) { + // sorts protocol list with descending order based on bytes within topn + List psiListSorted = + psiList.stream().sorted(PROTOCOL_STAT_INFO_COMPARATOR). + limit(topn).collect(Collectors.toList()); + retDs.dpiStatInfo().setDetectedProtos(psiListSorted); + } + List fsiList = ds.dpiStatInfo().knownFlows(); + if (fsiList != null) { + // sorts known flow list with descending order based on bytes within topn + List fsiListSorted = + fsiList.stream().sorted(FLOW_STAT_INFO_COMPARATOR). + limit(topn).collect(Collectors.toList()); + retDs.dpiStatInfo().setKnownFlows(fsiListSorted); + } + fsiList = ds.dpiStatInfo().unknownFlows(); + if (fsiList != null) { + // sorts unknown flow list with descending order based on bytes within topn + List fsiListSorted = + fsiList.stream().sorted(FLOW_STAT_INFO_COMPARATOR). + limit(topn).collect(Collectors.toList()); + retDs.dpiStatInfo().setUnknownFlows(fsiListSorted); + } + } + + ObjectNode result = codec(DpiStatistics.class).encode(retDs, this); + return ok(result).build(); + + } + + /** + * Gets the latest traffic statistics only. + * + * @return 200 OK with a traffic statistics + * @onos.rsModel TrafficStatistics + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("traffic") + public Response getTrafficStatistics() { + log.debug("getTrafficStatistics request"); + + DpiStatistics ds = service.getDpiStatisticsLatest(); + if (ds == null) { + ds = new DpiStatistics("", new DpiStatInfo()); + } + + DpiStatInfo dsi = new DpiStatInfo(); + dsi.setTrafficStatistics(ds.dpiStatInfo().trafficStatistics()); + DpiStatistics dsTraffic = new DpiStatistics(ds.receivedTime(), dsi); + + ObjectNode result = codec(DpiStatistics.class).encode(dsTraffic, this); + return ok(result).build(); + } + + /** + * Gets the latest detected protocol statistics only. + * + * @return 200 OK with a protocol statistics + * @onos.rsModel ProtocolStatistics + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("protocols") + public Response getDetectedProtocols(@QueryParam("topn") int topn) { + log.debug("getDetectedProtocols request with topn={}", topn); + + DpiStatistics ds = service.getDpiStatisticsLatest(); + DpiStatistics dsProtocol; + + if (ds == null) { + dsProtocol = new DpiStatistics("", new DpiStatInfo()); + } else if (topn <= 0) { + DpiStatInfo dsi = new DpiStatInfo(); + dsi.setDetectedProtos(ds.dpiStatInfo().detectedProtos()); + dsProtocol = new DpiStatistics(ds.receivedTime(), dsi); + } else { + if (topn > MAX_TOPN) { + topn = MAX_TOPN; + } + dsProtocol = new DpiStatistics(ds.receivedTime(), new DpiStatInfo()); + List psiList = ds.dpiStatInfo().detectedProtos(); + if (psiList != null) { + // sorts protocol list with descending order based on bytes within topn + List psiListSorted = + psiList.stream().sorted(PROTOCOL_STAT_INFO_COMPARATOR). + limit(topn).collect(Collectors.toList()); + dsProtocol.dpiStatInfo().setDetectedProtos(psiListSorted); + } + } + + ObjectNode result = codec(DpiStatistics.class).encode(dsProtocol, this); + return ok(result).build(); + } + + /** + * Gets the latest known flows statistics only. + * + * @return 200 OK with a known flow statistics + * @onos.rsModel KnownFlowStatistics + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("knownFlows") + public Response getKnownFlows(@QueryParam("topn") int topn) { + log.debug("getKnownFlows request with topn={}", topn); + + DpiStatistics ds = service.getDpiStatisticsLatest(); + DpiStatistics dsKnownFlows; + + if (ds == null) { + dsKnownFlows = new DpiStatistics("", new DpiStatInfo()); + } else if (topn <= 0) { + DpiStatInfo dsi = new DpiStatInfo(); + dsi.setKnownFlows(ds.dpiStatInfo().knownFlows()); + dsKnownFlows = new DpiStatistics(ds.receivedTime(), dsi); + } else { + if (topn > MAX_TOPN) { + topn = MAX_TOPN; + } + dsKnownFlows = new DpiStatistics(ds.receivedTime(), new DpiStatInfo()); + List fsiList = ds.dpiStatInfo().knownFlows(); + if (fsiList != null) { + // sorts known flow list with descending order based on bytes within topn + List fsiListSorted = + fsiList.stream().sorted(FLOW_STAT_INFO_COMPARATOR). + limit(topn).collect(Collectors.toList()); + dsKnownFlows.dpiStatInfo().setKnownFlows(fsiListSorted); + } + } + + ObjectNode result = codec(DpiStatistics.class).encode(dsKnownFlows, this); + return ok(result).build(); + } + + /** + * Gets the latest unknown flows statistics only. + * + * @return 200 OK with an unknown flow statistics + * @onos.rsModel UnknownFlowStatistics + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("unknownFlows") + public Response getUnknownFlows(@QueryParam("topn") int topn) { + log.debug("getUnknownFlows request with topn={}", topn); + + DpiStatistics ds = service.getDpiStatisticsLatest(); + DpiStatistics dsUnknownFlows; + + if (ds == null) { + dsUnknownFlows = new DpiStatistics("", new DpiStatInfo()); + } else if (topn <= 0) { + DpiStatInfo dsi = new DpiStatInfo(); + dsi.setUnknownFlows(ds.dpiStatInfo().unknownFlows()); + dsUnknownFlows = new DpiStatistics(ds.receivedTime(), dsi); + } else { + if (topn > 100) { + topn = 100; + } + dsUnknownFlows = new DpiStatistics(ds.receivedTime(), new DpiStatInfo()); + List fsiList = ds.dpiStatInfo().unknownFlows(); + if (fsiList != null) { + // sorts unknown flow list with descending order based on bytes within topn + List fsiListSorted = + fsiList.stream().sorted(FLOW_STAT_INFO_COMPARATOR). + limit(topn).collect(Collectors.toList()); + dsUnknownFlows.dpiStatInfo().setUnknownFlows(fsiListSorted); + } + } + + ObjectNode result = codec(DpiStatistics.class).encode(dsUnknownFlows, this); + return ok(result).build(); + } + + /** + * Add new dpi statistics entry at the end of list. + * + * @param stream dpi statistics JSON + * @return status of the request - CREATED if the JSON is correct, + * BAD_REQUEST if the JSON is invalid + * @onos.rsModel DpiStatisticsPost + */ + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response addDpiStatistics(InputStream stream) { + ObjectNode result; + + try { + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); + log.debug("jsonTree={}", jsonTree); + + DpiStatistics ds = codec(DpiStatistics.class).decode(jsonTree, this); + if (ds == null) { + log.error("Wrong DpiStatistics json format error"); + } + + // TODO: check the validity of dpi statistics values, specially receivedTime format + DpiStatistics added = service.addDpiStatistics(ds); + + result = codec(DpiStatistics.class).encode(added, this); + } catch (IOException ex) { + throw new IllegalArgumentException(ex); + } + return ok(result).build(); + } +} diff --git a/web/api/src/main/resources/definitions/DpiStatistics.json b/web/api/src/main/resources/definitions/DpiStatistics.json new file mode 100644 index 0000000000..43f4679a01 --- /dev/null +++ b/web/api/src/main/resources/definitions/DpiStatistics.json @@ -0,0 +1,307 @@ +{ + "type": "object", + "title": "dpiStatistics", + "required": [ + "receivedTime", + "dpiStatInfo" + ], + "properties": { + "receivedTime": { + "type": "string", + "example": "2016-06-12 04:05:05" + }, + "dpiStatInfo": { + "type": "object", + "title": "dpiStatInfo", + "required": [ + "trafficStatistics", + "detectedProtos", + "knownFlows", + "unknownFlow" + ], + "properties": { + "trafficStatistics": { + "type": "object", + "title": "trafficStatistics", + "required": [ + "ethernetBytes", + "discardedBytes", + "ipPackets", + "totalPackets", + "ipBytes", + "avgPktSize", + "uniqueFlows", + "tcpPackets", + "udpPackets", + "dpiThroughputPps", + "dpiThroughputBps", + "trafficThroughputPps", + "trafficThroughputBps", + "trafficDurationSec", + "guessedFlowProtos" + ], + "properties": { + "ethernetBytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "discardedBytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "ipPackets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "totalPackets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "ipBytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "avgPktSize": { + "type": "integer", + "format": "int32", + "example": 9889 + }, + "uniqueFlows": { + "type": "integer", + "format": "int32", + "example": 9889 + }, + "tcpPackets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "udpPackets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "dpiThroughputPps": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "dpiThroughputBps": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "trafficThroughputPps": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "trafficThroughputBps": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "trafficDurationSec": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "guessedFlowProtos": { + "type": "integer", + "format": "int32", + "example": 9889 + } + }, + "detectedProtos": { + "type": "array", + "xml": { + "name": "detectedProtos", + "wrapped": true + }, + "items": { + "type": "object", + "title": "protos", + "required": [ + "name", + "breed", + "packets", + "bytes", + "flows" + ], + "properties": { + "name": { + "type": "string", + "example": "TCP" + }, + "breed": { + "type": "string", + "example": "Acceptable" + }, + "packets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "bytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "flows": { + "type": "integer", + "format": "int32", + "example": 9889 + } + } + } + }, + "knownFlows": { + "type": "array", + "xml": { + "name": "knownFlows", + "wrapped": true + }, + "items": { + "type": "object", + "title": "knownFlows", + "required": [ + "protocol", + "hostAName", + "hostAPort", + "hostBName", + "hostBPort", + "detectedProtocol", + "detectedProtocolName", + "packets", + "bytes", + "hostServerName" + ], + "properties": { + "protocol": { + "type": "string", + "example": "TCP" + }, + "hostAName": { + "type": "string", + "example": "10.0.20.50" + }, + "hostAPort": { + "type": "integer", + "format": "int32", + "example": 9889 + }, + "hostBName": { + "type": "string", + "example": "10.0.20.10" + }, + "hostBPort": { + "type": "integer", + "format": "int32", + "example": 8181 + }, + "detectedProtocol": { + "type": "integer", + "format": "int32", + "example": 80 + }, + "detectedProtocolName": { + "type": "string", + "example": "HTTP" + }, + "packets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "bytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "hostSeverName": { + "type": "string", + "example": "raptor" + } + } + } + }, + "unknownFlows": { + "type": "array", + "xml": { + "name": "unknownFlows", + "wrapped": true + }, + "items": { + "type": "object", + "title": "unknownFlows", + "required": [ + "protocol", + "hostAName", + "hostAPort", + "hostBName", + "hostBPort", + "detectedProtocol", + "detectedProtocolName", + "packets", + "bytes", + "hostServerName" + ], + "properties": { + "protocol": { + "type": "string", + "example": "TCP" + }, + "hostAName": { + "type": "string", + "example": "10.0.20.50" + }, + "hostAPort": { + "type": "integer", + "format": "int32", + "example": 9889 + }, + "hostBName": { + "type": "string", + "example": "10.0.20.10" + }, + "hostBPort": { + "type": "integer", + "format": "int32", + "example": 8181 + }, + "detectedProtocol": { + "type": "integer", + "format": "int32", + "example": 80 + }, + "detectedProtocolName": { + "type": "string", + "example": "HTTP" + }, + "packets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "bytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "hostSeverName": { + "type": "string", + "example": "raptor" + } + } + } + } + } + } + } + } +} diff --git a/web/api/src/main/resources/definitions/DpiStatisticsPost.json b/web/api/src/main/resources/definitions/DpiStatisticsPost.json new file mode 100644 index 0000000000..43f4679a01 --- /dev/null +++ b/web/api/src/main/resources/definitions/DpiStatisticsPost.json @@ -0,0 +1,307 @@ +{ + "type": "object", + "title": "dpiStatistics", + "required": [ + "receivedTime", + "dpiStatInfo" + ], + "properties": { + "receivedTime": { + "type": "string", + "example": "2016-06-12 04:05:05" + }, + "dpiStatInfo": { + "type": "object", + "title": "dpiStatInfo", + "required": [ + "trafficStatistics", + "detectedProtos", + "knownFlows", + "unknownFlow" + ], + "properties": { + "trafficStatistics": { + "type": "object", + "title": "trafficStatistics", + "required": [ + "ethernetBytes", + "discardedBytes", + "ipPackets", + "totalPackets", + "ipBytes", + "avgPktSize", + "uniqueFlows", + "tcpPackets", + "udpPackets", + "dpiThroughputPps", + "dpiThroughputBps", + "trafficThroughputPps", + "trafficThroughputBps", + "trafficDurationSec", + "guessedFlowProtos" + ], + "properties": { + "ethernetBytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "discardedBytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "ipPackets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "totalPackets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "ipBytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "avgPktSize": { + "type": "integer", + "format": "int32", + "example": 9889 + }, + "uniqueFlows": { + "type": "integer", + "format": "int32", + "example": 9889 + }, + "tcpPackets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "udpPackets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "dpiThroughputPps": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "dpiThroughputBps": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "trafficThroughputPps": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "trafficThroughputBps": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "trafficDurationSec": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "guessedFlowProtos": { + "type": "integer", + "format": "int32", + "example": 9889 + } + }, + "detectedProtos": { + "type": "array", + "xml": { + "name": "detectedProtos", + "wrapped": true + }, + "items": { + "type": "object", + "title": "protos", + "required": [ + "name", + "breed", + "packets", + "bytes", + "flows" + ], + "properties": { + "name": { + "type": "string", + "example": "TCP" + }, + "breed": { + "type": "string", + "example": "Acceptable" + }, + "packets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "bytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "flows": { + "type": "integer", + "format": "int32", + "example": 9889 + } + } + } + }, + "knownFlows": { + "type": "array", + "xml": { + "name": "knownFlows", + "wrapped": true + }, + "items": { + "type": "object", + "title": "knownFlows", + "required": [ + "protocol", + "hostAName", + "hostAPort", + "hostBName", + "hostBPort", + "detectedProtocol", + "detectedProtocolName", + "packets", + "bytes", + "hostServerName" + ], + "properties": { + "protocol": { + "type": "string", + "example": "TCP" + }, + "hostAName": { + "type": "string", + "example": "10.0.20.50" + }, + "hostAPort": { + "type": "integer", + "format": "int32", + "example": 9889 + }, + "hostBName": { + "type": "string", + "example": "10.0.20.10" + }, + "hostBPort": { + "type": "integer", + "format": "int32", + "example": 8181 + }, + "detectedProtocol": { + "type": "integer", + "format": "int32", + "example": 80 + }, + "detectedProtocolName": { + "type": "string", + "example": "HTTP" + }, + "packets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "bytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "hostSeverName": { + "type": "string", + "example": "raptor" + } + } + } + }, + "unknownFlows": { + "type": "array", + "xml": { + "name": "unknownFlows", + "wrapped": true + }, + "items": { + "type": "object", + "title": "unknownFlows", + "required": [ + "protocol", + "hostAName", + "hostAPort", + "hostBName", + "hostBPort", + "detectedProtocol", + "detectedProtocolName", + "packets", + "bytes", + "hostServerName" + ], + "properties": { + "protocol": { + "type": "string", + "example": "TCP" + }, + "hostAName": { + "type": "string", + "example": "10.0.20.50" + }, + "hostAPort": { + "type": "integer", + "format": "int32", + "example": 9889 + }, + "hostBName": { + "type": "string", + "example": "10.0.20.10" + }, + "hostBPort": { + "type": "integer", + "format": "int32", + "example": 8181 + }, + "detectedProtocol": { + "type": "integer", + "format": "int32", + "example": 80 + }, + "detectedProtocolName": { + "type": "string", + "example": "HTTP" + }, + "packets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "bytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "hostSeverName": { + "type": "string", + "example": "raptor" + } + } + } + } + } + } + } + } +} diff --git a/web/api/src/main/resources/definitions/KnownFlowStatistics.json b/web/api/src/main/resources/definitions/KnownFlowStatistics.json new file mode 100644 index 0000000000..0342b915de --- /dev/null +++ b/web/api/src/main/resources/definitions/KnownFlowStatistics.json @@ -0,0 +1,93 @@ +{ + "type": "object", + "title": "dpiStatistics", + "required": [ + "receivedTime", + "dpiStatInfo" + ], + "properties": { + "receivedTime": { + "type": "string", + "example": "2016-06-12 04:05:05" + }, + "dpiStatInfo": { + "type": "object", + "title": "dpiStatInfo", + "required": [ + "knownFlows" + ], + "properties": { + "knownFlows": { + "type": "array", + "xml": { + "name": "knownFlows", + "wrapped": true + }, + "items": { + "type": "object", + "title": "knownFlows", + "required": [ + "protocol", + "hostAName", + "hostAPort", + "hostBName", + "hostBPort", + "detectedProtocol", + "detectedProtocolName", + "packets", + "bytes", + "hostServerName" + ], + "properties": { + "protocol": { + "type": "string", + "example": "TCP" + }, + "hostAName": { + "type": "string", + "example": "10.0.20.50" + }, + "hostAPort": { + "type": "integer", + "format": "int32", + "example": 9889 + }, + "hostBName": { + "type": "string", + "example": "10.0.20.10" + }, + "hostBPort": { + "type": "integer", + "format": "int32", + "example": 8181 + }, + "detectedProtocol": { + "type": "integer", + "format": "int32", + "example": 80 + }, + "detectedProtocolName": { + "type": "string", + "example": "HTTP" + }, + "packets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "bytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "hostSeverName": { + "type": "string", + "example": "raptor" + } + } + } + } + } + } + } +} diff --git a/web/api/src/main/resources/definitions/ProtocolStatistics.json b/web/api/src/main/resources/definitions/ProtocolStatistics.json new file mode 100644 index 0000000000..9eb010ef53 --- /dev/null +++ b/web/api/src/main/resources/definitions/ProtocolStatistics.json @@ -0,0 +1,66 @@ +{ + "type": "object", + "title": "protocolStatistics", + "required": [ + "receivedTime", + "dpiStatInfo" + ], + "properties": { + "receivedTime": { + "type": "string", + "example": "2016-06-12 04:05:05" + }, + "dpiStatInfo": { + "type": "object", + "title": "dpiStatInfo", + "required": [ + "detectedProtos" + ], + "properties": { + "detectedProtos": { + "type": "array", + "xml": { + "name": "detectedProtos", + "wrapped": true + }, + "items": { + "type": "object", + "title": "protos", + "required": [ + "name", + "breed", + "packets", + "bytes", + "flows" + ], + "properties": { + "name": { + "type": "string", + "example": "TCP" + }, + "breed": { + "type": "string", + "example": "Acceptable" + }, + "packets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "bytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "flows": { + "type": "integer", + "format": "int32", + "example": 9889 + } + } + } + } + } + } + } +} diff --git a/web/api/src/main/resources/definitions/TrafficStatistics.json b/web/api/src/main/resources/definitions/TrafficStatistics.json new file mode 100644 index 0000000000..4749be8722 --- /dev/null +++ b/web/api/src/main/resources/definitions/TrafficStatistics.json @@ -0,0 +1,121 @@ +{ + "type": "object", + "title": "TrafficStatistics", + "required": [ + "receivedTime", + "dpiStatInfo" + ], + "properties": { + "receivedTime": { + "type": "string", + "example": "2016-06-12 04:05:05" + }, + "dpiStatInfo": { + "type": "object", + "title": "dpiStatInfo", + "required": [ + "trafficStatistics" + ], + "properties": { + "trafficStatistics": { + "type": "object", + "title": "trafficStatistics", + "required": [ + "ethernetBytes", + "discardedBytes", + "ipPackets", + "totalPackets", + "ipBytes", + "avgPktSize", + "uniqueFlows", + "tcpPackets", + "udpPackets", + "dpiThroughputPps", + "dpiThroughputBps", + "trafficThroughputPps", + "trafficThroughputBps", + "trafficDurationSec", + "guessedFlowProtos" + ], + "properties": { + "ethernetBytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "discardedBytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "ipPackets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "totalPackets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "ipBytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "avgPktSize": { + "type": "integer", + "format": "int32", + "example": 9889 + }, + "uniqueFlows": { + "type": "integer", + "format": "int32", + "example": 9889 + }, + "tcpPackets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "udpPackets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "dpiThroughputPps": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "dpiThroughputBps": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "trafficThroughputPps": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "trafficThroughputBps": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "trafficDurationSec": { + "type": "number", + "format": "double", + "example": 69889.12 + }, + "guessedFlowProtos": { + "type": "integer", + "format": "int32", + "example": 9889 + } + } + } + } + } + } +} diff --git a/web/api/src/main/resources/definitions/UnknownFlowStatistics.json b/web/api/src/main/resources/definitions/UnknownFlowStatistics.json new file mode 100644 index 0000000000..0d9dc5330a --- /dev/null +++ b/web/api/src/main/resources/definitions/UnknownFlowStatistics.json @@ -0,0 +1,93 @@ +{ + "type": "object", + "title": "unknownFlowStatistics", + "required": [ + "receivedTime", + "dpiStatInfo" + ], + "properties": { + "receivedTime": { + "type": "string", + "example": "2016-06-12 04:05:05" + }, + "dpiStatInfo": { + "type": "object", + "title": "dpiStatInfo", + "required": [ + "unknownFlow" + ], + "properties": { + "unknownFlows": { + "type": "array", + "xml": { + "name": "unknownFlows", + "wrapped": true + }, + "items": { + "type": "object", + "title": "unknownFlows", + "required": [ + "protocol", + "hostAName", + "hostAPort", + "hostBName", + "hostBPort", + "detectedProtocol", + "detectedProtocolName", + "packets", + "bytes", + "hostServerName" + ], + "properties": { + "protocol": { + "type": "string", + "example": "TCP" + }, + "hostAName": { + "type": "string", + "example": "10.0.20.50" + }, + "hostAPort": { + "type": "integer", + "format": "int32", + "example": 9889 + }, + "hostBName": { + "type": "string", + "example": "10.0.20.10" + }, + "hostBPort": { + "type": "integer", + "format": "int32", + "example": 8181 + }, + "detectedProtocol": { + "type": "integer", + "format": "int32", + "example": 80 + }, + "detectedProtocolName": { + "type": "string", + "example": "HTTP" + }, + "packets": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "bytes": { + "type": "integer", + "format": "int64", + "example": 69889 + }, + "hostSeverName": { + "type": "string", + "example": "raptor" + } + } + } + } + } + } + } +}