ISSUE
[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.Set;
18
19 import org.opendaylight.controller.sal.action.Action;
20 import org.opendaylight.controller.sal.action.Output;
21 import org.opendaylight.controller.sal.action.SetVlanId;
22 import org.opendaylight.controller.sal.authorization.UserLevel;
23 import org.opendaylight.controller.sal.core.Node;
24 import org.opendaylight.controller.sal.core.NodeConnector;
25 import org.opendaylight.controller.sal.core.TimeStamp;
26 import org.opendaylight.controller.sal.flowprogrammer.Flow;
27 import org.opendaylight.controller.sal.match.Match;
28 import org.opendaylight.controller.sal.match.MatchType;
29 import org.opendaylight.controller.sal.reader.FlowOnNode;
30 import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
31 import org.opendaylight.controller.sal.utils.EtherTypes;
32 import org.opendaylight.controller.sal.utils.GlobalConstants;
33 import org.opendaylight.controller.sal.utils.HexEncode;
34 import org.opendaylight.controller.sal.utils.IPProtocols;
35 import org.opendaylight.controller.sal.utils.ServiceHelper;
36 import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
37 import org.opendaylight.controller.switchmanager.ISwitchManager;
38 import org.opendaylight.controller.web.IOneWeb;
39 import org.springframework.stereotype.Controller;
40 import org.springframework.web.bind.annotation.RequestMapping;
41 import org.springframework.web.bind.annotation.RequestMethod;
42 import org.springframework.web.bind.annotation.RequestParam;
43 import org.springframework.web.bind.annotation.ResponseBody;
44
45 @Controller
46 @RequestMapping("/")
47 public class Troubleshoot implements IOneWeb {
48     private static final UserLevel AUTH_LEVEL = UserLevel.CONTAINERUSER;
49     private final String WEB_NAME = "Troubleshoot";
50     private final String WEB_ID = "troubleshoot";
51     private final short WEB_ORDER = 4;
52     private final String containerName = GlobalConstants.DEFAULT.toString();
53
54     public Troubleshoot() {
55         ServiceHelper.registerGlobalService(IOneWeb.class, this, null);
56     }
57
58     @Override
59     public String getWebName() {
60         return WEB_NAME;
61     }
62
63     @Override
64     public String getWebId() {
65         return WEB_ID;
66     }
67
68     @Override
69     public short getWebOrder() {
70         return WEB_ORDER;
71     }
72
73     @Override
74     public boolean isAuthorized(UserLevel userLevel) {
75         return userLevel.ordinal() <= AUTH_LEVEL.ordinal();
76     }
77
78     @RequestMapping(value = "/existingNodes", method = RequestMethod.GET)
79     @ResponseBody
80     public TroubleshootingJsonBean getExistingNodes() {
81         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
82                 .getInstance(ISwitchManager.class, containerName, this);
83         List<HashMap<String, String>> lines = new ArrayList<HashMap<String, String>>();
84         Set<Node> nodeSet = null;
85         if (switchManager != null) {
86             nodeSet = switchManager.getNodes();
87         }
88         if (nodeSet != null) {
89             for (Node node : nodeSet) {
90                 HashMap<String, String> device = new HashMap<String, String>();
91                 device.put("nodeName", switchManager.getNodeDescription(node));
92                 device.put("nodeId", node.toString());
93                 lines.add(device);
94             }
95         }
96         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
97
98         List<String> guiFieldNames = new ArrayList<String>();
99         guiFieldNames.add("Node");
100         guiFieldNames.add("Node ID");
101         guiFieldNames.add("Statistics");
102
103         result.setColumnNames(guiFieldNames);
104         result.setNodeData(lines);
105         return result;
106     }
107
108     @RequestMapping(value = "/uptime", method = RequestMethod.GET)
109     @ResponseBody
110     public TroubleshootingJsonBean getUptime() {
111         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
112                 .getInstance(ISwitchManager.class, containerName, this);
113         List<HashMap<String, String>> lines = new ArrayList<HashMap<String, String>>();
114         Set<Node> nodeSet = null;
115         if (switchManager != null) {
116             nodeSet = switchManager.getNodes();
117         }
118         if (nodeSet != null) {
119             for (Node node : nodeSet) {
120                 HashMap<String, String> device = new HashMap<String, String>();
121                 device.put("nodeName", switchManager.getNodeDescription(node));
122                 device.put("nodeId", node.toString());
123                 TimeStamp timeStamp = (TimeStamp) switchManager.getNodeProp(
124                         node, TimeStamp.TimeStampPropName);
125                 Long time = (timeStamp == null) ? 0 : timeStamp.getValue();
126                 String date = (time == 0) ? "" : (new Date(time)).toString();
127                 device.put("connectedSince", date);
128                 lines.add(device);
129             }
130         }
131         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
132
133         List<String> guiFieldNames = new ArrayList<String>();
134         guiFieldNames.add("Node");
135         guiFieldNames.add("Node ID");
136         guiFieldNames.add("Connected");
137
138         result.setColumnNames(guiFieldNames);
139         result.setNodeData(lines);
140         return result;
141     }
142
143     @RequestMapping(value = "/flowStats", method = RequestMethod.GET)
144     @ResponseBody
145     public TroubleshootingJsonBean getFlowStats(
146             @RequestParam("nodeId") String nodeId) {
147         Node node = Node.fromString(nodeId);
148         List<HashMap<String, String>> cells = new ArrayList<HashMap<String, String>>();
149         IStatisticsManager statisticsManager = (IStatisticsManager) ServiceHelper
150                 .getInstance(IStatisticsManager.class, containerName, this);
151
152         List<FlowOnNode> statistics = statisticsManager.getFlows(node);
153         for (FlowOnNode stats : statistics) {
154             cells.add(this.convertFlowStatistics(node, stats));
155         }
156         List<String> columnNames = new ArrayList<String>();
157         columnNames.addAll(Arrays.asList(new String[] { "Node", "In Port",
158                 "DL Src", "DL Dst", "DL Type", "DL Vlan", "NW Src", "NW Dst",
159                 "NW Proto", "TP Src", "TP Dst", "Actions", "Bytes", "Packets",
160                 "Time (s)", "Timeout (s)", "Out Port(s)", "Out Vlan",
161                 "Priority" }));
162         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
163         result.setColumnNames(columnNames);
164         result.setNodeData(cells);
165         return result;
166     }
167
168     @RequestMapping(value = "/portStats", method = RequestMethod.GET)
169     @ResponseBody
170     public TroubleshootingJsonBean getPortStats(
171             @RequestParam("nodeId") String nodeId) {
172         Node node = Node.fromString(nodeId);
173         List<HashMap<String, String>> cells = new ArrayList<HashMap<String, String>>();
174         IStatisticsManager statisticsManager = (IStatisticsManager) ServiceHelper
175                 .getInstance(IStatisticsManager.class, containerName, this);
176         List<NodeConnectorStatistics> statistics = statisticsManager
177                 .getNodeConnectorStatistics(node);
178         for (NodeConnectorStatistics stats : statistics) {
179             cells.add(this.convertPortsStatistics(stats));
180         }
181         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
182         List<String> columnNames = new ArrayList<String>();
183         columnNames.addAll(Arrays.asList(new String[] { "Node Connector",
184                 "Rx Pkts", "Tx Pkts", "Rx Bytes", "Tx Bytes", "Rx Drops",
185                 "Tx Drops", "Rx Errs", "Tx Errs", "Rx Frame Errs",
186                 "Rx OverRun Errs", "Rx CRC Errs", "Collisions" }));
187         result.setColumnNames(columnNames);
188         result.setNodeData(cells);
189         return result;
190     }
191
192     private HashMap<String, String> convertPortsStatistics(
193             NodeConnectorStatistics ncStats) {
194         HashMap<String, String> row = new HashMap<String, String>();
195
196         row.put("nodeConnector",
197                 String.valueOf(ncStats.getNodeConnector().toString()));
198         row.put("rxPkts", String.valueOf(ncStats.getReceivePacketCount()));
199         row.put("txPkts", String.valueOf(ncStats.getTransmitPacketCount()));
200         row.put("rxBytes", String.valueOf(ncStats.getReceiveByteCount()));
201         row.put("txBytes", String.valueOf(ncStats.getTransmitByteCount()));
202         row.put("rxDrops", String.valueOf(ncStats.getReceiveDropCount()));
203         row.put("txDrops", String.valueOf(ncStats.getTransmitDropCount()));
204         row.put("rxErrors", String.valueOf(ncStats.getReceiveErrorCount()));
205         row.put("txErrors", String.valueOf(ncStats.getTransmitErrorCount()));
206         row.put("rxFrameErrors",
207                 String.valueOf(ncStats.getReceiveFrameErrorCount()));
208         row.put("rxOverRunErrors",
209                 String.valueOf(ncStats.getReceiveOverRunErrorCount()));
210         row.put("rxCRCErrors",
211                 String.valueOf(ncStats.getReceiveCRCErrorCount()));
212         row.put("collisions", String.valueOf(ncStats.getCollisionCount()));
213
214         return row;
215     }
216
217     private HashMap<String, String> convertFlowStatistics(Node node,
218             FlowOnNode flowOnNode) {
219         HashMap<String, String> row = new HashMap<String, String>();
220         Flow flow = flowOnNode.getFlow();
221         Match match = flow.getMatch();
222         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
223                 .getInstance(ISwitchManager.class, containerName, this);
224         String desc = (switchManager == null)? 
225                         "" : switchManager.getNodeDescription(node);
226         desc = (desc.isEmpty() || desc.equalsIgnoreCase("none"))? 
227                         node.toString(): desc;
228         row.put("nodeName", desc);
229         if (match.isPresent(MatchType.IN_PORT)) {
230             row.put(MatchType.IN_PORT.id(), ((NodeConnector) flow.getMatch()
231                     .getField(MatchType.IN_PORT).getValue()).getID().toString());
232         } else {
233             row.put(MatchType.IN_PORT.id(), "*");
234         }
235         if (match.isPresent(MatchType.DL_SRC)) {
236             row.put(MatchType.DL_SRC.id(),
237                     (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
238                             .getField(MatchType.DL_SRC).getValue()))));
239         } else {
240             row.put(MatchType.DL_SRC.id(), "*");
241         }
242         if (match.isPresent(MatchType.DL_DST)) {
243             row.put(MatchType.DL_DST.id(),
244                     (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
245                             .getField(MatchType.DL_DST).getValue()))));
246         } else {
247             row.put(MatchType.DL_DST.id(), "*");
248         }
249         if (match.isPresent(MatchType.DL_TYPE)) {
250             row.put(MatchType.DL_TYPE.id(),
251                     EtherTypes.getEtherTypeName(((Short) flow.getMatch()
252                             .getField(MatchType.DL_TYPE).getValue())));
253         } else {
254             row.put(MatchType.DL_TYPE.id(), "*");
255         }
256
257         // Some physical switch has vlan as ffff to show "any" vlan
258         if (match.isPresent(MatchType.DL_VLAN)) {
259             if (((Short) flow.getMatch().getField(MatchType.DL_VLAN).getValue())
260                     .shortValue() < 0) {
261                 row.put(MatchType.DL_VLAN.id(), "0");
262             } else {
263                 row.put(MatchType.DL_VLAN.id(), ((Short) flow.getMatch()
264                         .getField(MatchType.DL_VLAN).getValue()).toString());
265             }
266         } else {
267             row.put(MatchType.DL_VLAN.id(), "*");
268         }
269         if (match.isPresent(MatchType.NW_SRC)) {
270             row.put(MatchType.NW_SRC.id(), ((InetAddress) flow.getMatch()
271                     .getField(MatchType.NW_SRC).getValue()).getHostAddress());
272         } else {
273             row.put(MatchType.NW_SRC.id(), "*");
274         }
275         if (match.isPresent(MatchType.NW_DST)) {
276             row.put(MatchType.NW_DST.id(), ((InetAddress) flow.getMatch()
277                     .getField(MatchType.NW_DST).getValue()).getHostAddress());
278         } else {
279             row.put(MatchType.NW_DST.id(), "*");
280         }
281         if (match.isPresent(MatchType.NW_PROTO)) {
282             row.put(MatchType.NW_PROTO.id(),
283                     IPProtocols.getProtocolName(((Byte) flow.getMatch()
284                             .getField(MatchType.NW_PROTO).getValue())));
285         } else {
286             row.put(MatchType.NW_PROTO.id(), "*");
287         }
288         if (match.isPresent(MatchType.TP_SRC)) {
289             Short tpSrc = (Short) (flow.getMatch().getField(MatchType.TP_SRC)
290                     .getValue());
291             if (tpSrc < 0) {
292                 row.put(MatchType.TP_SRC.id(),
293                         ((Integer) (tpSrc.intValue() & 0x7FFF | 0x8000))
294                                 .toString());
295             } else {
296                 row.put(MatchType.TP_SRC.id(), tpSrc.toString());
297             }
298         } else {
299             row.put(MatchType.TP_SRC.id(), "*");
300         }
301         if (match.isPresent(MatchType.TP_DST)) {
302             Short tpDst = (Short) (flow.getMatch().getField(MatchType.TP_DST)
303                     .getValue());
304             if (tpDst < 0) {
305                 row.put(MatchType.TP_DST.id(),
306                         ((Integer) (tpDst.intValue() & 0x7FFF | 0x8000))
307                                 .toString());
308             } else {
309                 row.put(MatchType.TP_DST.id(), tpDst.toString());
310             }
311         } else {
312             row.put(MatchType.TP_DST.id(), "*");
313         }
314
315         row.put("byteCount", ((Long) flowOnNode.getByteCount()).toString());
316         row.put("packetCount", ((Long) flowOnNode.getPacketCount()).toString());
317
318         StringBuffer actions = new StringBuffer();
319         StringBuffer outPorts = new StringBuffer();
320         String outVlanId = null;
321         for (Action action : flow.getActions()) {
322             actions.append(action.getType().toString() + "\n");
323             if (action instanceof Output) {
324                 Output ao = (Output) action;
325                 if (outPorts.length() > 0) {
326                     outPorts.append(" ");
327                 }
328                 outPorts.append(ao.getPort().getNodeConnectorIdAsString());
329             } else if (action instanceof SetVlanId) {
330                 SetVlanId av = (SetVlanId) action;
331                 outVlanId = String.valueOf(av.getVlanId());
332             }
333         }
334         if (outPorts.length() == 0) {
335             outPorts.append("*");
336         }
337         if (outVlanId == null) {
338             outVlanId = "*";
339         }
340         row.put("actions", actions.toString());
341         row.put("outPorts", outPorts.toString());
342         row.put("outVlanId", outVlanId);
343         row.put("durationSeconds",
344                 ((Integer) flowOnNode.getDurationSeconds()).toString());
345         row.put("idleTimeout", ((Short) flow.getIdleTimeout()).toString());
346         row.put("priority", String.valueOf(flow.getPriority()));
347         return row;
348     }
349
350 }