blob: 51d2eb686ddea332cbb30c6e2c657e0c40bca041 [file] [log] [blame]
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +09001/*
Thomas Vachuska52f2cd12018-11-08 21:20:04 -08002 * Copyright 2018-present Open Networking Foundation
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +09003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Thomas Vachuska52f2cd12018-11-08 21:20:04 -080017package org.onosproject.incubator.net.dpi.impl;
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +090018
19import com.fasterxml.jackson.databind.node.ObjectNode;
20import org.onosproject.incubator.net.dpi.DpiStatInfo;
21import org.onosproject.incubator.net.dpi.DpiStatistics;
22import org.onosproject.incubator.net.dpi.DpiStatisticsManagerService;
23import org.onosproject.incubator.net.dpi.FlowStatInfo;
24import org.onosproject.incubator.net.dpi.ProtocolStatInfo;
25import org.onosproject.rest.AbstractWebResource;
26import org.slf4j.Logger;
27
28import javax.ws.rs.Consumes;
29import javax.ws.rs.GET;
30import javax.ws.rs.POST;
31import javax.ws.rs.Path;
32import javax.ws.rs.Produces;
33import javax.ws.rs.QueryParam;
34import javax.ws.rs.core.MediaType;
35import javax.ws.rs.core.Response;
36
37import java.io.IOException;
38import java.io.InputStream;
39import java.util.Comparator;
40import java.util.List;
41import java.util.stream.Collectors;
42
Ray Milkey86ee5e82018-04-02 15:33:07 -070043import static org.onlab.util.Tools.readTreeFromStream;
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +090044import static org.slf4j.LoggerFactory.getLogger;
45
46/**
47 * Query the latest DPI statistics info.
48 */
49
50@Path("dpis")
51public class DpisWebResource extends AbstractWebResource {
52
53 private final Logger log = getLogger(getClass());
54
55 private static final int MAX_TOPN = 100;
56
57 private final DpiStatisticsManagerService service = get(DpiStatisticsManagerService.class);
58
59 public static final Comparator<ProtocolStatInfo> PROTOCOL_STAT_INFO_COMPARATOR =
60 new Comparator<ProtocolStatInfo>() {
61 @Override
62 public int compare(ProtocolStatInfo psi1, ProtocolStatInfo psi2) {
63 long delta = psi1.bytes() - psi2.bytes();
64 return delta == 0 ? 0 : (delta > 0 ? -1 : +1);
65 }
66 };
67
68 public static final Comparator<FlowStatInfo> FLOW_STAT_INFO_COMPARATOR =
69 new Comparator<FlowStatInfo>() {
70 @Override
71 public int compare(FlowStatInfo fsi1, FlowStatInfo fsi2) {
72 long delta = fsi1.bytes() - fsi2.bytes();
73 return delta == 0 ? 0 : (delta > 0 ? -1 : +1);
74 }
75 };
76
77 /**
78 * Gets the latest dpi statistics.
79 *
Ray Milkeyef794342016-11-09 16:20:29 -080080 * @param topn max size
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +090081 * @return 200 OK with a dpi statistics
82 * @onos.rsModel DpiStatistics
83 */
84 @GET
85 @Produces(MediaType.APPLICATION_JSON)
86 public Response getDpisLatest(@QueryParam("topn") int topn) {
87 log.debug("getDpisLatest request with topn={}", topn);
88
89 DpiStatistics ds = service.getDpiStatisticsLatest();
90 DpiStatistics retDs;
91
92 if (ds == null) {
93 retDs = new DpiStatistics("", new DpiStatInfo());
94 } else if (topn <= 0) {
95 retDs = ds;
96 } else {
97 if (topn > MAX_TOPN) {
98 topn = MAX_TOPN;
99 }
100 retDs = new DpiStatistics(ds.receivedTime(),
101 new DpiStatInfo(ds.dpiStatInfo().trafficStatistics()));
102 List<ProtocolStatInfo> psiList = ds.dpiStatInfo().detectedProtos();
103 if (psiList != null) {
104 // sorts protocol list with descending order based on bytes within topn
105 List<ProtocolStatInfo> psiListSorted =
106 psiList.stream().sorted(PROTOCOL_STAT_INFO_COMPARATOR).
107 limit(topn).collect(Collectors.toList());
108 retDs.dpiStatInfo().setDetectedProtos(psiListSorted);
109 }
110 List<FlowStatInfo> fsiList = ds.dpiStatInfo().knownFlows();
111 if (fsiList != null) {
112 // sorts known flow list with descending order based on bytes within topn
113 List<FlowStatInfo> fsiListSorted =
114 fsiList.stream().sorted(FLOW_STAT_INFO_COMPARATOR).
115 limit(topn).collect(Collectors.toList());
116 retDs.dpiStatInfo().setKnownFlows(fsiListSorted);
117 }
118 fsiList = ds.dpiStatInfo().unknownFlows();
119 if (fsiList != null) {
120 // sorts unknown flow list with descending order based on bytes within topn
121 List<FlowStatInfo> fsiListSorted =
122 fsiList.stream().sorted(FLOW_STAT_INFO_COMPARATOR).
123 limit(topn).collect(Collectors.toList());
124 retDs.dpiStatInfo().setUnknownFlows(fsiListSorted);
125 }
126 }
127
128 ObjectNode result = codec(DpiStatistics.class).encode(retDs, this);
129 return ok(result).build();
130
131 }
132
133 /**
134 * Gets the latest traffic statistics only.
135 *
136 * @return 200 OK with a traffic statistics
137 * @onos.rsModel TrafficStatistics
138 */
139 @GET
140 @Produces(MediaType.APPLICATION_JSON)
141 @Path("traffic")
142 public Response getTrafficStatistics() {
143 log.debug("getTrafficStatistics request");
144
145 DpiStatistics ds = service.getDpiStatisticsLatest();
146 if (ds == null) {
147 ds = new DpiStatistics("", new DpiStatInfo());
148 }
149
150 DpiStatInfo dsi = new DpiStatInfo();
151 dsi.setTrafficStatistics(ds.dpiStatInfo().trafficStatistics());
152 DpiStatistics dsTraffic = new DpiStatistics(ds.receivedTime(), dsi);
153
154 ObjectNode result = codec(DpiStatistics.class).encode(dsTraffic, this);
155 return ok(result).build();
156 }
157
158 /**
159 * Gets the latest detected protocol statistics only.
160 *
Ray Milkeyef794342016-11-09 16:20:29 -0800161 * @param topn max size
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +0900162 * @return 200 OK with a protocol statistics
163 * @onos.rsModel ProtocolStatistics
164 */
165 @GET
166 @Produces(MediaType.APPLICATION_JSON)
167 @Path("protocols")
168 public Response getDetectedProtocols(@QueryParam("topn") int topn) {
169 log.debug("getDetectedProtocols request with topn={}", topn);
170
171 DpiStatistics ds = service.getDpiStatisticsLatest();
172 DpiStatistics dsProtocol;
173
174 if (ds == null) {
175 dsProtocol = new DpiStatistics("", new DpiStatInfo());
176 } else if (topn <= 0) {
177 DpiStatInfo dsi = new DpiStatInfo();
178 dsi.setDetectedProtos(ds.dpiStatInfo().detectedProtos());
179 dsProtocol = new DpiStatistics(ds.receivedTime(), dsi);
180 } else {
181 if (topn > MAX_TOPN) {
182 topn = MAX_TOPN;
183 }
184 dsProtocol = new DpiStatistics(ds.receivedTime(), new DpiStatInfo());
185 List<ProtocolStatInfo> psiList = ds.dpiStatInfo().detectedProtos();
186 if (psiList != null) {
187 // sorts protocol list with descending order based on bytes within topn
188 List<ProtocolStatInfo> psiListSorted =
189 psiList.stream().sorted(PROTOCOL_STAT_INFO_COMPARATOR).
190 limit(topn).collect(Collectors.toList());
191 dsProtocol.dpiStatInfo().setDetectedProtos(psiListSorted);
192 }
193 }
194
195 ObjectNode result = codec(DpiStatistics.class).encode(dsProtocol, this);
196 return ok(result).build();
197 }
198
199 /**
200 * Gets the latest known flows statistics only.
201 *
Ray Milkeyef794342016-11-09 16:20:29 -0800202 * @param topn max size
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +0900203 * @return 200 OK with a known flow statistics
204 * @onos.rsModel KnownFlowStatistics
205 */
206 @GET
207 @Produces(MediaType.APPLICATION_JSON)
208 @Path("knownFlows")
209 public Response getKnownFlows(@QueryParam("topn") int topn) {
210 log.debug("getKnownFlows request with topn={}", topn);
211
212 DpiStatistics ds = service.getDpiStatisticsLatest();
213 DpiStatistics dsKnownFlows;
214
215 if (ds == null) {
216 dsKnownFlows = new DpiStatistics("", new DpiStatInfo());
217 } else if (topn <= 0) {
218 DpiStatInfo dsi = new DpiStatInfo();
219 dsi.setKnownFlows(ds.dpiStatInfo().knownFlows());
220 dsKnownFlows = new DpiStatistics(ds.receivedTime(), dsi);
221 } else {
222 if (topn > MAX_TOPN) {
223 topn = MAX_TOPN;
224 }
225 dsKnownFlows = new DpiStatistics(ds.receivedTime(), new DpiStatInfo());
226 List<FlowStatInfo> fsiList = ds.dpiStatInfo().knownFlows();
227 if (fsiList != null) {
228 // sorts known flow list with descending order based on bytes within topn
229 List<FlowStatInfo> fsiListSorted =
230 fsiList.stream().sorted(FLOW_STAT_INFO_COMPARATOR).
231 limit(topn).collect(Collectors.toList());
232 dsKnownFlows.dpiStatInfo().setKnownFlows(fsiListSorted);
233 }
234 }
235
236 ObjectNode result = codec(DpiStatistics.class).encode(dsKnownFlows, this);
237 return ok(result).build();
238 }
239
240 /**
241 * Gets the latest unknown flows statistics only.
242 *
Ray Milkeyef794342016-11-09 16:20:29 -0800243 * @param topn max size
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +0900244 * @return 200 OK with an unknown flow statistics
245 * @onos.rsModel UnknownFlowStatistics
246 */
247 @GET
248 @Produces(MediaType.APPLICATION_JSON)
249 @Path("unknownFlows")
250 public Response getUnknownFlows(@QueryParam("topn") int topn) {
251 log.debug("getUnknownFlows request with topn={}", topn);
252
253 DpiStatistics ds = service.getDpiStatisticsLatest();
254 DpiStatistics dsUnknownFlows;
255
256 if (ds == null) {
257 dsUnknownFlows = new DpiStatistics("", new DpiStatInfo());
258 } else if (topn <= 0) {
259 DpiStatInfo dsi = new DpiStatInfo();
260 dsi.setUnknownFlows(ds.dpiStatInfo().unknownFlows());
261 dsUnknownFlows = new DpiStatistics(ds.receivedTime(), dsi);
262 } else {
263 if (topn > 100) {
264 topn = 100;
265 }
266 dsUnknownFlows = new DpiStatistics(ds.receivedTime(), new DpiStatInfo());
267 List<FlowStatInfo> fsiList = ds.dpiStatInfo().unknownFlows();
268 if (fsiList != null) {
269 // sorts unknown flow list with descending order based on bytes within topn
270 List<FlowStatInfo> fsiListSorted =
271 fsiList.stream().sorted(FLOW_STAT_INFO_COMPARATOR).
272 limit(topn).collect(Collectors.toList());
273 dsUnknownFlows.dpiStatInfo().setUnknownFlows(fsiListSorted);
274 }
275 }
276
277 ObjectNode result = codec(DpiStatistics.class).encode(dsUnknownFlows, this);
278 return ok(result).build();
279 }
280
281 /**
282 * Add new dpi statistics entry at the end of list.
283 *
284 * @param stream dpi statistics JSON
285 * @return status of the request - CREATED if the JSON is correct,
286 * BAD_REQUEST if the JSON is invalid
287 * @onos.rsModel DpiStatisticsPost
288 */
289 @POST
290 @Consumes(MediaType.APPLICATION_JSON)
291 @Produces(MediaType.APPLICATION_JSON)
292 public Response addDpiStatistics(InputStream stream) {
293 ObjectNode result;
294
295 try {
Ray Milkey86ee5e82018-04-02 15:33:07 -0700296 ObjectNode jsonTree = readTreeFromStream(mapper(), stream);
Sangsik Yoonf0b3ad82016-08-19 18:47:59 +0900297 log.debug("jsonTree={}", jsonTree);
298
299 DpiStatistics ds = codec(DpiStatistics.class).decode(jsonTree, this);
300 if (ds == null) {
301 log.error("Wrong DpiStatistics json format error");
302 }
303
304 // TODO: check the validity of dpi statistics values, specially receivedTime format
305 DpiStatistics added = service.addDpiStatistics(ds);
306
307 result = codec(DpiStatistics.class).encode(added, this);
308 } catch (IOException ex) {
309 throw new IllegalArgumentException(ex);
310 }
311 return ok(result).build();
312 }
313}