TS GUI does not show ToS field in flow stats
[controller.git] / opendaylight / web / troubleshoot / src / main / java / org / opendaylight / controller / troubleshoot / web / Troubleshoot.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.troubleshoot.web;
10
11 import java.net.InetAddress;
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.Date;
15 import java.util.HashMap;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19
20 import javax.servlet.http.HttpServletRequest;
21
22 import org.opendaylight.controller.sal.action.Action;
23 import org.opendaylight.controller.sal.action.Output;
24 import org.opendaylight.controller.sal.action.SetDlDst;
25 import org.opendaylight.controller.sal.action.SetDlSrc;
26 import org.opendaylight.controller.sal.action.SetNwDst;
27 import org.opendaylight.controller.sal.action.SetNwSrc;
28 import org.opendaylight.controller.sal.action.SetNwTos;
29 import org.opendaylight.controller.sal.action.SetTpDst;
30 import org.opendaylight.controller.sal.action.SetTpSrc;
31 import org.opendaylight.controller.sal.action.SetVlanId;
32 import org.opendaylight.controller.sal.action.SetVlanPcp;
33 import org.opendaylight.controller.sal.authorization.Privilege;
34 import org.opendaylight.controller.sal.authorization.UserLevel;
35 import org.opendaylight.controller.sal.core.Description;
36 import org.opendaylight.controller.sal.core.Node;
37 import org.opendaylight.controller.sal.core.NodeConnector;
38 import org.opendaylight.controller.sal.core.TimeStamp;
39 import org.opendaylight.controller.sal.flowprogrammer.Flow;
40 import org.opendaylight.controller.sal.match.Match;
41 import org.opendaylight.controller.sal.match.MatchType;
42 import org.opendaylight.controller.sal.reader.FlowOnNode;
43 import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
44 import org.opendaylight.controller.sal.utils.EtherTypes;
45 import org.opendaylight.controller.sal.utils.GlobalConstants;
46 import org.opendaylight.controller.sal.utils.HexEncode;
47 import org.opendaylight.controller.sal.utils.IPProtocols;
48 import org.opendaylight.controller.sal.utils.NetUtils;
49 import org.opendaylight.controller.sal.utils.ServiceHelper;
50 import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
51 import org.opendaylight.controller.switchmanager.ISwitchManager;
52 import org.opendaylight.controller.web.DaylightWebUtil;
53 import org.opendaylight.controller.web.IDaylightWeb;
54 import org.springframework.stereotype.Controller;
55 import org.springframework.web.bind.annotation.RequestMapping;
56 import org.springframework.web.bind.annotation.RequestMethod;
57 import org.springframework.web.bind.annotation.RequestParam;
58 import org.springframework.web.bind.annotation.ResponseBody;
59
60 @Controller
61 @RequestMapping("/")
62 public class Troubleshoot implements IDaylightWeb {
63     private static final UserLevel AUTH_LEVEL = UserLevel.CONTAINERUSER;
64     private static final List<String> flowStatsColumnNames = Arrays.asList("Node", "In Port",
65             "DL Src", "DL Dst", "DL Type", "DL Vlan", "NW Src", "NW Dst","ToS Bits",
66             "NW Proto", "TP Src", "TP Dst", "Actions", "Bytes", "Packets",
67             "Time (s)", "Timeout (s)",
68             "Priority");
69     private static final List<String> portStatsColumnNames = Arrays.asList("Node Connector",
70             "Rx Pkts", "Tx Pkts", "Rx Bytes", "Tx Bytes", "Rx Drops",
71             "Tx Drops", "Rx Errs", "Tx Errs", "Rx Frame Errs",
72             "Rx OverRun Errs", "Rx CRC Errs", "Collisions");
73     private static final List<String> nodesColumnNames = Arrays.asList("Node", "Node ID", "Statistics");
74     private static final List<String> nodeStatsColumnNames = Arrays.asList("Node", "Node ID", "Statistics");
75     private final String WEB_NAME = "Troubleshoot";
76     private final String WEB_ID = "troubleshoot";
77     private final short WEB_ORDER = 4;
78
79
80     public Troubleshoot() {
81         ServiceHelper.registerGlobalService(IDaylightWeb.class, this, null);
82     }
83
84     @Override
85     public String getWebName() {
86         return WEB_NAME;
87     }
88
89     @Override
90     public String getWebId() {
91         return WEB_ID;
92     }
93
94     @Override
95     public short getWebOrder() {
96         return WEB_ORDER;
97     }
98
99     @Override
100     public boolean isAuthorized(UserLevel userLevel) {
101         return userLevel.ordinal() <= AUTH_LEVEL.ordinal();
102     }
103
104     @RequestMapping(value = "/existingNodes", method = RequestMethod.GET)
105     @ResponseBody
106     public TroubleshootingJsonBean getExistingNodes(HttpServletRequest request, @RequestParam(required = false) String container) {
107         List<Map<String, String>> lines = new ArrayList<Map<String, String>>();
108         String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
109
110         // Derive the privilege this user has on the current container
111         String userName = request.getUserPrincipal().getName();
112         Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
113
114         if (privilege != Privilege.NONE) {
115             ISwitchManager switchManager = (ISwitchManager) ServiceHelper
116                     .getInstance(ISwitchManager.class, containerName, this);
117             Set<Node> nodeSet = (switchManager != null) ? switchManager.getNodes() : null;
118             if (nodeSet != null) {
119                 for (Node node : nodeSet) {
120                     Map<String, String> device = new HashMap<String, String>();
121                     device.put("nodeName", getNodeDesc(node, switchManager));
122                     device.put("nodeId", node.toString());
123                     lines.add(device);
124                 }
125             }
126         }
127
128         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
129         result.setColumnNames(nodesColumnNames);
130         result.setNodeData(lines);
131         return result;
132     }
133
134     @RequestMapping(value = "/uptime", method = RequestMethod.GET)
135     @ResponseBody
136     public TroubleshootingJsonBean getUptime(HttpServletRequest request, @RequestParam(required = false) String container) {
137         List<Map<String, String>> lines = new ArrayList<Map<String, String>>();
138         String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
139
140         // Derive the privilege this user has on the current container
141         String userName = request.getUserPrincipal().getName();
142         Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
143
144         if (privilege != Privilege.NONE) {
145             ISwitchManager switchManager = (ISwitchManager) ServiceHelper
146                     .getInstance(ISwitchManager.class, containerName, this);
147             Set<Node> nodeSet = (switchManager != null) ? switchManager.getNodes() : null;
148             if (nodeSet != null) {
149                 for (Node node : nodeSet) {
150                     Map<String, String> device = new HashMap<String, String>();
151                     device.put("nodeName", getNodeDesc(node, switchManager));
152                     device.put("nodeId", node.toString());
153                     TimeStamp timeStamp = (TimeStamp) switchManager.getNodeProp(
154                             node, TimeStamp.TimeStampPropName);
155                     Long time = (timeStamp == null) ? 0 : timeStamp.getValue();
156                     String date = (time == 0) ? "" : (new Date(time)).toString();
157                     device.put("connectedSince", date);
158                     lines.add(device);
159                 }
160             }
161         }
162
163         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
164         result.setColumnNames(nodeStatsColumnNames);
165         result.setNodeData(lines);
166         return result;
167     }
168
169     @RequestMapping(value = "/flowStats", method = RequestMethod.GET)
170     @ResponseBody
171     public TroubleshootingJsonBean getFlowStats(
172             @RequestParam("nodeId") String nodeId,
173             HttpServletRequest request, @RequestParam(required = false) String container) {
174         List<Map<String, String>> cells = new ArrayList<Map<String, String>>();
175         String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
176
177         // Derive the privilege this user has on the current container
178         String userName = request.getUserPrincipal().getName();
179         Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
180
181         if (privilege != Privilege.NONE) {
182             IStatisticsManager statisticsManager = (IStatisticsManager) ServiceHelper
183                     .getInstance(IStatisticsManager.class, containerName, this);
184             if (statisticsManager != null) {
185                 Node node = Node.fromString(nodeId);
186                 List<FlowOnNode> statistics = statisticsManager.getFlows(node);
187                 for (FlowOnNode stats : statistics) {
188                     cells.add(this.convertFlowStatistics(node, stats, containerName));
189                 }
190             }
191         }
192
193         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
194         result.setColumnNames(flowStatsColumnNames);
195         result.setNodeData(cells);
196         return result;
197     }
198
199     @RequestMapping(value = "/portStats", method = RequestMethod.GET)
200     @ResponseBody
201     public TroubleshootingJsonBean getPortStats(
202             @RequestParam("nodeId") String nodeId,
203             HttpServletRequest request, @RequestParam(required = false) String container) {
204         List<Map<String, String>> cells = new ArrayList<Map<String, String>>();
205         String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
206
207         // Derive the privilege this user has on the current container
208         String userName = request.getUserPrincipal().getName();
209         Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
210
211         if (privilege != Privilege.NONE) {
212             IStatisticsManager statisticsManager = (IStatisticsManager) ServiceHelper
213                     .getInstance(IStatisticsManager.class, containerName, this);
214             if (statisticsManager != null) {
215                 Node node = Node.fromString(nodeId);
216                 List<NodeConnectorStatistics> statistics = statisticsManager
217                         .getNodeConnectorStatistics(node);
218                 for (NodeConnectorStatistics stats : statistics) {
219                     cells.add(this.convertPortsStatistics(stats, containerName));
220                 }
221             }
222         }
223
224         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
225         result.setColumnNames(portStatsColumnNames);
226         result.setNodeData(cells);
227         return result;
228     }
229
230     private Map<String, String> convertPortsStatistics(
231             NodeConnectorStatistics ncStats, String containerName) {
232
233         Map<String, String> row = new HashMap<String, String>();
234
235         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
236                 .getInstance(ISwitchManager.class, containerName, this);
237         NodeConnector nodeConnector = ncStats.getNodeConnector();
238         Description description = (Description) switchManager.getNodeProp(nodeConnector.getNode(), Description.propertyName);
239         String desc = (description == null) ? "" : description.getValue();
240         String nodeName = desc.equalsIgnoreCase("none") ? nodeConnector.getNode().getNodeIDString() : desc;
241         String nodeConnectorDisplayName = nodeConnector.getType() + "|" + nodeConnector.getID() + "@" + nodeName;
242         row.put("nodeConnector",
243                 String.valueOf(nodeConnectorDisplayName));
244
245         row.put("rxPkts", String.valueOf(ncStats.getReceivePacketCount()));
246         row.put("txPkts", String.valueOf(ncStats.getTransmitPacketCount()));
247         row.put("rxBytes", String.valueOf(ncStats.getReceiveByteCount()));
248         row.put("txBytes", String.valueOf(ncStats.getTransmitByteCount()));
249         row.put("rxDrops", String.valueOf(ncStats.getReceiveDropCount()));
250         row.put("txDrops", String.valueOf(ncStats.getTransmitDropCount()));
251         row.put("rxErrors", String.valueOf(ncStats.getReceiveErrorCount()));
252         row.put("txErrors", String.valueOf(ncStats.getTransmitErrorCount()));
253         row.put("rxFrameErrors",
254                 String.valueOf(ncStats.getReceiveFrameErrorCount()));
255         row.put("rxOverRunErrors",
256                 String.valueOf(ncStats.getReceiveOverRunErrorCount()));
257         row.put("rxCRCErrors",
258                 String.valueOf(ncStats.getReceiveCRCErrorCount()));
259         row.put("collisions", String.valueOf(ncStats.getCollisionCount()));
260
261         return row;
262     }
263
264     private Map<String, String> convertFlowStatistics(Node node,
265             FlowOnNode flowOnNode,
266             String containerName) {
267         Map<String, String> row = new HashMap<String, String>();
268         Flow flow = flowOnNode.getFlow();
269         Match match = flow.getMatch();
270         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
271                 .getInstance(ISwitchManager.class, containerName, this);
272         String desc = getNodeDesc(node, switchManager);
273         desc = (desc == null || desc.isEmpty() || desc.equalsIgnoreCase("none"))?
274                         node.toString() : desc;
275         row.put("nodeName", desc);
276         if (match.isPresent(MatchType.IN_PORT)) {
277             row.put(MatchType.IN_PORT.id(), ((NodeConnector) flow.getMatch()
278                     .getField(MatchType.IN_PORT).getValue())
279                     .getNodeConnectorIdAsString());
280         } else {
281             row.put(MatchType.IN_PORT.id(), "*");
282         }
283         if (match.isPresent(MatchType.DL_SRC)) {
284             row.put(MatchType.DL_SRC.id(),
285                     (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
286                             .getField(MatchType.DL_SRC).getValue()))));
287         } else {
288             row.put(MatchType.DL_SRC.id(), "*");
289         }
290         if (match.isPresent(MatchType.DL_DST)) {
291             row.put(MatchType.DL_DST.id(),
292                     (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
293                             .getField(MatchType.DL_DST).getValue()))));
294         } else {
295             row.put(MatchType.DL_DST.id(), "*");
296         }
297         if (match.isPresent(MatchType.DL_TYPE)) {
298             row.put(MatchType.DL_TYPE.id(),
299                     EtherTypes.getEtherTypeName(((Short) flow.getMatch()
300                             .getField(MatchType.DL_TYPE).getValue())));
301         } else {
302             row.put(MatchType.DL_TYPE.id(), "*");
303         }
304
305         // Some physical switch has vlan as ffff to show "any" vlan
306         if (match.isPresent(MatchType.DL_VLAN)) {
307             if (((Short) flow.getMatch().getField(MatchType.DL_VLAN).getValue())
308                     .shortValue() < 0) {
309                 row.put(MatchType.DL_VLAN.id(), "0");
310             } else {
311                 row.put(MatchType.DL_VLAN.id(), ((Short) flow.getMatch()
312                         .getField(MatchType.DL_VLAN).getValue()).toString());
313             }
314         } else {
315             row.put(MatchType.DL_VLAN.id(), "*");
316         }
317         if (match.isPresent(MatchType.NW_SRC)) {
318             row.put(MatchType.NW_SRC.id(), ((InetAddress) flow.getMatch()
319                     .getField(MatchType.NW_SRC).getValue()).getHostAddress());
320         } else {
321             row.put(MatchType.NW_SRC.id(), "*");
322         }
323         if (match.isPresent(MatchType.NW_DST)) {
324             row.put(MatchType.NW_DST.id(), ((InetAddress) flow.getMatch()
325                     .getField(MatchType.NW_DST).getValue()).getHostAddress());
326         } else {
327             row.put(MatchType.NW_DST.id(), "*");
328         }
329         if (match.isPresent(MatchType.NW_TOS)) {
330             row.put(MatchType.NW_TOS.id(), ((Byte) flow.getMatch()
331                         .getField(MatchType.NW_TOS).getValue()).toString());
332         } else {
333             row.put(MatchType.NW_TOS.id(), "*");
334         }
335         if (match.isPresent(MatchType.NW_PROTO)) {
336             row.put(MatchType.NW_PROTO.id(),
337                     IPProtocols.getProtocolName(((Byte) flow.getMatch()
338                             .getField(MatchType.NW_PROTO).getValue())));
339         } else {
340             row.put(MatchType.NW_PROTO.id(), "*");
341         }
342         if (match.isPresent(MatchType.TP_SRC)) {
343             Short tpSrc = (Short) (flow.getMatch().getField(MatchType.TP_SRC)
344                     .getValue());
345             row.put(MatchType.TP_SRC.id(),
346                         String.valueOf(NetUtils.getUnsignedShort(tpSrc)));
347         } else {
348             row.put(MatchType.TP_SRC.id(), "*");
349         }
350         if (match.isPresent(MatchType.TP_DST)) {
351             Short tpDst = (Short) (flow.getMatch().getField(MatchType.TP_DST)
352                     .getValue());
353             row.put(MatchType.TP_DST.id(),
354                         String.valueOf(NetUtils.getUnsignedShort(tpDst)));
355         } else {
356             row.put(MatchType.TP_DST.id(), "*");
357         }
358
359         row.put("byteCount", ((Long) flowOnNode.getByteCount()).toString());
360         row.put("packetCount", ((Long) flowOnNode.getPacketCount()).toString());
361
362         StringBuffer actions = new StringBuffer();
363         StringBuffer outPorts = new StringBuffer();
364         for (Action action : flow.getActions()) {
365
366             if (action instanceof Output) {
367                 Output ao = (Output) action;
368                 if (outPorts.length() > 0) {
369                     outPorts.append(" ");
370                 }
371                 actions.append(action.getType().toString()).append(" = ").append(ao.getPort().getNodeConnectorIdAsString()).append("<br>");
372             } else if (action instanceof SetVlanId) {
373                 SetVlanId av = (SetVlanId) action;
374                 String outVlanId = String.valueOf(av.getVlanId());
375                 actions.append(action.getType().toString()).append(" = ").append(outVlanId).append("<br>");
376             } else if (action instanceof SetDlSrc) {
377                 SetDlSrc ads = (SetDlSrc) action;
378                 actions.append(action.getType().toString()).append(" = ").append(HexEncode.bytesToHexStringFormat(ads.getDlAddress())).append("<br>");
379             } else if (action instanceof SetDlDst) {
380                 SetDlDst add = (SetDlDst) action;
381                 actions.append(action.getType().toString()).append(" = ").append(HexEncode.bytesToHexStringFormat(add.getDlAddress())).append("<br>");
382             } else if (action instanceof SetNwSrc) {
383                 SetNwSrc ans = (SetNwSrc) action;
384                 actions.append(action.getType().toString()).append(" = ").append(ans.getAddressAsString()).append("<br>");
385             } else if (action instanceof SetNwDst) {
386                 SetNwDst and = (SetNwDst) action;
387                 actions.append(action.getType().toString()).append(" = ").append(and.getAddressAsString()).append("<br>");
388             } else if (action instanceof SetNwTos) {
389                 SetNwTos ant = (SetNwTos) action;
390                 actions.append(action.getType().toString()).append(" = ").append(ant.getNwTos()).append("<br>");
391             } else if (action instanceof SetTpSrc) {
392                 SetTpSrc ads = (SetTpSrc) action;
393                 actions.append(action.getType().toString()).append(" = ").append(ads.getPort()).append("<br>");
394             } else if (action instanceof SetTpDst) {
395                 SetTpDst atd = (SetTpDst) action;
396                 actions.append(action.getType().toString()).append(" = ").append(atd.getPort()).append("<br>");
397             } else if (action instanceof SetVlanPcp) {
398                 SetVlanPcp avp = (SetVlanPcp) action;
399                 actions.append(action.getType().toString()).append(" = ").append(avp.getPcp()).append("<br>");
400                 // } else if (action instanceof SetDlSrc) {
401                 // SetDlSrc ads = (SetDlSrc) action;
402             } else {
403                 actions.append(action.getType().toString()).append("<br>");
404             }
405         }
406         row.put("actions", actions.toString());
407         row.put("durationSeconds",
408                 ((Integer) flowOnNode.getDurationSeconds()).toString());
409         row.put("idleTimeout", ((Short) flow.getIdleTimeout()).toString());
410         row.put("priority", String.valueOf(flow.getPriority()));
411         return row;
412     }
413
414     private String getNodeDesc(Node node, ISwitchManager switchManager) {
415         if (switchManager == null) {
416             return null;
417         }
418         Description desc = (Description) switchManager.getNodeProp(node, Description.propertyName);
419         return (desc == null) ? "" : desc.getValue();
420     }
421 }