2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.troubleshoot.web;
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;
20 import javax.servlet.http.HttpServletRequest;
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.reader.NodeDescription;
45 import org.opendaylight.controller.sal.utils.EtherTypes;
46 import org.opendaylight.controller.sal.utils.GlobalConstants;
47 import org.opendaylight.controller.sal.utils.HexEncode;
48 import org.opendaylight.controller.sal.utils.IPProtocols;
49 import org.opendaylight.controller.sal.utils.NetUtils;
50 import org.opendaylight.controller.sal.utils.ServiceHelper;
51 import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
52 import org.opendaylight.controller.switchmanager.ISwitchManager;
53 import org.opendaylight.controller.web.DaylightWebUtil;
54 import org.opendaylight.controller.web.IDaylightWeb;
55 import org.springframework.stereotype.Controller;
56 import org.springframework.web.bind.annotation.RequestMapping;
57 import org.springframework.web.bind.annotation.RequestMethod;
58 import org.springframework.web.bind.annotation.RequestParam;
59 import org.springframework.web.bind.annotation.ResponseBody;
63 public class Troubleshoot implements IDaylightWeb {
64 private static final UserLevel AUTH_LEVEL = UserLevel.CONTAINERUSER;
65 private static final List<String> flowStatsColumnNames = Arrays.asList("Node", "In Port",
66 "DL Src", "DL Dst", "DL Type", "DL Vlan","Vlan Priority", "NW Src", "NW Dst","ToS Bits",
67 "NW Proto", "TP Src", "TP Dst", "Actions", "Bytes", "Packets",
68 "Time (s)", "Timeout (s)",
70 private static final List<String> portStatsColumnNames = Arrays.asList("Node Connector",
71 "Rx Pkts", "Tx Pkts", "Rx Bytes", "Tx Bytes", "Rx Drops",
72 "Tx Drops", "Rx Errs", "Tx Errs", "Rx Frame Errs",
73 "Rx OverRun Errs", "Rx CRC Errs", "Collisions");
74 private static final List<String> nodesColumnNames = Arrays.asList("Node", "Node ID", "Statistics");
75 private static final List<String> nodeStatsColumnNames = Arrays.asList("Node", "Node ID", "Statistics");
76 private final String WEB_NAME = "Troubleshoot";
77 private final String WEB_ID = "troubleshoot";
78 private final short WEB_ORDER = 4;
81 public Troubleshoot() {
82 ServiceHelper.registerGlobalService(IDaylightWeb.class, this, null);
86 public String getWebName() {
91 public String getWebId() {
96 public short getWebOrder() {
101 public boolean isAuthorized(UserLevel userLevel) {
102 return userLevel.ordinal() <= AUTH_LEVEL.ordinal();
105 @RequestMapping(value = "/nodeInfo", method = RequestMethod.GET)
107 public NodeDescription getNodeInfo(HttpServletRequest request, @RequestParam(required = false) String container,
108 @RequestParam(required = true) String nodeId) {
109 List<Map<String, String>> lines = new ArrayList<Map<String, String>>();
110 String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
112 // Derive the privilege this user has on the current container
113 String userName = request.getUserPrincipal().getName();
114 Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
116 if (privilege != Privilege.NONE) {
117 IStatisticsManager statisticsManager = (IStatisticsManager) ServiceHelper
118 .getInstance(IStatisticsManager.class, containerName, this);
119 if(statisticsManager != null){
120 Node node = Node.fromString(nodeId);
121 NodeDescription nodeDesc = statisticsManager.getNodeDescription(node);
126 return new NodeDescription();
129 @RequestMapping(value = "/existingNodes", method = RequestMethod.GET)
131 public TroubleshootingJsonBean getExistingNodes(HttpServletRequest request, @RequestParam(required = false) String container) {
132 List<Map<String, String>> lines = new ArrayList<Map<String, String>>();
133 String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
135 // Derive the privilege this user has on the current container
136 String userName = request.getUserPrincipal().getName();
137 Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
139 if (privilege != Privilege.NONE) {
140 ISwitchManager switchManager = (ISwitchManager) ServiceHelper
141 .getInstance(ISwitchManager.class, containerName, this);
142 Set<Node> nodeSet = (switchManager != null) ? switchManager.getNodes() : null;
143 if (nodeSet != null) {
144 for (Node node : nodeSet) {
145 Map<String, String> device = new HashMap<String, String>();
146 device.put("nodeName", getNodeDesc(node, switchManager));
147 device.put("nodeId", node.toString());
153 TroubleshootingJsonBean result = new TroubleshootingJsonBean();
154 result.setColumnNames(nodesColumnNames);
155 result.setNodeData(lines);
159 @RequestMapping(value = "/uptime", method = RequestMethod.GET)
161 public TroubleshootingJsonBean getUptime(HttpServletRequest request, @RequestParam(required = false) String container) {
162 List<Map<String, String>> lines = new ArrayList<Map<String, String>>();
163 String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
165 // Derive the privilege this user has on the current container
166 String userName = request.getUserPrincipal().getName();
167 Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
169 if (privilege != Privilege.NONE) {
170 ISwitchManager switchManager = (ISwitchManager) ServiceHelper
171 .getInstance(ISwitchManager.class, containerName, this);
172 Set<Node> nodeSet = (switchManager != null) ? switchManager.getNodes() : null;
173 if (nodeSet != null) {
174 for (Node node : nodeSet) {
175 Map<String, String> device = new HashMap<String, String>();
176 device.put("nodeName", getNodeDesc(node, switchManager));
177 device.put("nodeId", node.toString());
178 TimeStamp timeStamp = (TimeStamp) switchManager.getNodeProp(
179 node, TimeStamp.TimeStampPropName);
180 Long time = (timeStamp == null) ? 0 : timeStamp.getValue();
181 String date = (time == 0) ? "" : (new Date(time)).toString();
182 device.put("connectedSince", date);
188 TroubleshootingJsonBean result = new TroubleshootingJsonBean();
189 result.setColumnNames(nodeStatsColumnNames);
190 result.setNodeData(lines);
194 @RequestMapping(value = "/flowStats", method = RequestMethod.GET)
196 public TroubleshootingJsonBean getFlowStats(
197 @RequestParam("nodeId") String nodeId,
198 HttpServletRequest request, @RequestParam(required = false) String container) {
199 List<Map<String, String>> cells = new ArrayList<Map<String, String>>();
200 String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
202 // Derive the privilege this user has on the current container
203 String userName = request.getUserPrincipal().getName();
204 Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
206 if (privilege != Privilege.NONE) {
207 IStatisticsManager statisticsManager = (IStatisticsManager) ServiceHelper
208 .getInstance(IStatisticsManager.class, containerName, this);
209 if (statisticsManager != null) {
210 Node node = Node.fromString(nodeId);
211 List<FlowOnNode> statistics = statisticsManager.getFlows(node);
212 for (FlowOnNode stats : statistics) {
213 cells.add(this.convertFlowStatistics(node, stats, containerName));
218 TroubleshootingJsonBean result = new TroubleshootingJsonBean();
219 result.setColumnNames(flowStatsColumnNames);
220 result.setNodeData(cells);
224 @RequestMapping(value = "/portStats", method = RequestMethod.GET)
226 public TroubleshootingJsonBean getPortStats(
227 @RequestParam("nodeId") String nodeId,
228 HttpServletRequest request, @RequestParam(required = false) String container) {
229 List<Map<String, String>> cells = new ArrayList<Map<String, String>>();
230 String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
232 // Derive the privilege this user has on the current container
233 String userName = request.getUserPrincipal().getName();
234 Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
236 if (privilege != Privilege.NONE) {
237 IStatisticsManager statisticsManager = (IStatisticsManager) ServiceHelper
238 .getInstance(IStatisticsManager.class, containerName, this);
239 if (statisticsManager != null) {
240 Node node = Node.fromString(nodeId);
241 List<NodeConnectorStatistics> statistics = statisticsManager
242 .getNodeConnectorStatistics(node);
243 for (NodeConnectorStatistics stats : statistics) {
244 cells.add(this.convertPortsStatistics(stats, containerName));
249 TroubleshootingJsonBean result = new TroubleshootingJsonBean();
250 result.setColumnNames(portStatsColumnNames);
251 result.setNodeData(cells);
255 private Map<String, String> convertPortsStatistics(
256 NodeConnectorStatistics ncStats, String containerName) {
258 Map<String, String> row = new HashMap<String, String>();
260 ISwitchManager switchManager = (ISwitchManager) ServiceHelper
261 .getInstance(ISwitchManager.class, containerName, this);
262 NodeConnector nodeConnector = ncStats.getNodeConnector();
263 Description description = (Description) switchManager.getNodeProp(nodeConnector.getNode(), Description.propertyName);
264 String desc = (description == null) ? "" : description.getValue();
265 String nodeName = desc.equalsIgnoreCase("none") ? nodeConnector.getNode().getNodeIDString() : desc;
266 String nodeConnectorDisplayName = nodeConnector.getType() + "|" + nodeConnector.getID() + "@" + nodeName;
267 row.put("nodeConnector",
268 String.valueOf(nodeConnectorDisplayName));
270 row.put("rxPkts", String.valueOf(ncStats.getReceivePacketCount()));
271 row.put("txPkts", String.valueOf(ncStats.getTransmitPacketCount()));
272 row.put("rxBytes", String.valueOf(ncStats.getReceiveByteCount()));
273 row.put("txBytes", String.valueOf(ncStats.getTransmitByteCount()));
274 row.put("rxDrops", String.valueOf(ncStats.getReceiveDropCount()));
275 row.put("txDrops", String.valueOf(ncStats.getTransmitDropCount()));
276 row.put("rxErrors", String.valueOf(ncStats.getReceiveErrorCount()));
277 row.put("txErrors", String.valueOf(ncStats.getTransmitErrorCount()));
278 row.put("rxFrameErrors",
279 String.valueOf(ncStats.getReceiveFrameErrorCount()));
280 row.put("rxOverRunErrors",
281 String.valueOf(ncStats.getReceiveOverRunErrorCount()));
282 row.put("rxCRCErrors",
283 String.valueOf(ncStats.getReceiveCRCErrorCount()));
284 row.put("collisions", String.valueOf(ncStats.getCollisionCount()));
289 private Map<String, String> convertFlowStatistics(Node node,
290 FlowOnNode flowOnNode,
291 String containerName) {
292 Map<String, String> row = new HashMap<String, String>();
293 Flow flow = flowOnNode.getFlow();
294 Match match = flow.getMatch();
295 ISwitchManager switchManager = (ISwitchManager) ServiceHelper
296 .getInstance(ISwitchManager.class, containerName, this);
297 String desc = getNodeDesc(node, switchManager);
298 desc = (desc == null || desc.isEmpty() || desc.equalsIgnoreCase("none"))?
299 node.toString() : desc;
300 row.put("nodeName", desc);
301 if (match.isPresent(MatchType.IN_PORT)) {
302 row.put(MatchType.IN_PORT.id(), ((NodeConnector) flow.getMatch()
303 .getField(MatchType.IN_PORT).getValue())
304 .getNodeConnectorIdAsString());
306 row.put(MatchType.IN_PORT.id(), "*");
308 if (match.isPresent(MatchType.DL_SRC)) {
309 row.put(MatchType.DL_SRC.id(),
310 (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
311 .getField(MatchType.DL_SRC).getValue()))));
313 row.put(MatchType.DL_SRC.id(), "*");
315 if (match.isPresent(MatchType.DL_DST)) {
316 row.put(MatchType.DL_DST.id(),
317 (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
318 .getField(MatchType.DL_DST).getValue()))));
320 row.put(MatchType.DL_DST.id(), "*");
322 if (match.isPresent(MatchType.DL_TYPE)) {
323 row.put(MatchType.DL_TYPE.id(),
324 EtherTypes.getEtherTypeName(((Short) flow.getMatch()
325 .getField(MatchType.DL_TYPE).getValue())));
327 row.put(MatchType.DL_TYPE.id(), "*");
330 // Some physical switch has vlan as ffff to show "any" vlan
331 if (match.isPresent(MatchType.DL_VLAN)) {
332 if (((Short) flow.getMatch().getField(MatchType.DL_VLAN).getValue())
334 row.put(MatchType.DL_VLAN.id(), "0");
336 row.put(MatchType.DL_VLAN.id(), ((Short) flow.getMatch()
337 .getField(MatchType.DL_VLAN).getValue()).toString());
340 row.put(MatchType.DL_VLAN.id(), "*");
343 if (match.isPresent(MatchType.DL_VLAN_PR)) {
344 if (((Byte) flow.getMatch().getField(MatchType.DL_VLAN_PR).getValue())
346 row.put(MatchType.DL_VLAN_PR.id(), "0");
348 row.put(MatchType.DL_VLAN_PR.id(), ((Byte) flow.getMatch()
349 .getField(MatchType.DL_VLAN_PR).getValue()).toString());
352 row.put(MatchType.DL_VLAN_PR.id(), "*");
355 if (match.isPresent(MatchType.NW_SRC)) {
356 row.put(MatchType.NW_SRC.id(), ((InetAddress) flow.getMatch()
357 .getField(MatchType.NW_SRC).getValue()).getHostAddress());
359 row.put(MatchType.NW_SRC.id(), "*");
361 if (match.isPresent(MatchType.NW_DST)) {
362 row.put(MatchType.NW_DST.id(), ((InetAddress) flow.getMatch()
363 .getField(MatchType.NW_DST).getValue()).getHostAddress());
365 row.put(MatchType.NW_DST.id(), "*");
367 if (match.isPresent(MatchType.NW_TOS)) {
368 row.put(MatchType.NW_TOS.id(), ((Byte) flow.getMatch()
369 .getField(MatchType.NW_TOS).getValue()).toString());
371 row.put(MatchType.NW_TOS.id(), "*");
373 if (match.isPresent(MatchType.NW_PROTO)) {
374 row.put(MatchType.NW_PROTO.id(),
375 IPProtocols.getProtocolName(((Byte) flow.getMatch()
376 .getField(MatchType.NW_PROTO).getValue())));
378 row.put(MatchType.NW_PROTO.id(), "*");
380 if (match.isPresent(MatchType.TP_SRC)) {
381 Short tpSrc = (Short) (flow.getMatch().getField(MatchType.TP_SRC)
383 row.put(MatchType.TP_SRC.id(),
384 String.valueOf(NetUtils.getUnsignedShort(tpSrc)));
386 row.put(MatchType.TP_SRC.id(), "*");
388 if (match.isPresent(MatchType.TP_DST)) {
389 Short tpDst = (Short) (flow.getMatch().getField(MatchType.TP_DST)
391 row.put(MatchType.TP_DST.id(),
392 String.valueOf(NetUtils.getUnsignedShort(tpDst)));
394 row.put(MatchType.TP_DST.id(), "*");
397 row.put("byteCount", ((Long) flowOnNode.getByteCount()).toString());
398 row.put("packetCount", ((Long) flowOnNode.getPacketCount()).toString());
400 StringBuffer actions = new StringBuffer();
401 StringBuffer outPorts = new StringBuffer();
402 for (Action action : flow.getActions()) {
404 if (action instanceof Output) {
405 Output ao = (Output) action;
406 if (outPorts.length() > 0) {
407 outPorts.append(" ");
409 actions.append(action.getType().toString()).append(" = ").append(ao.getPort().getNodeConnectorIdAsString()).append("<br>");
410 } else if (action instanceof SetVlanId) {
411 SetVlanId av = (SetVlanId) action;
412 String outVlanId = String.valueOf(av.getVlanId());
413 actions.append(action.getType().toString()).append(" = ").append(outVlanId).append("<br>");
414 } else if (action instanceof SetDlSrc) {
415 SetDlSrc ads = (SetDlSrc) action;
416 actions.append(action.getType().toString()).append(" = ").append(HexEncode.bytesToHexStringFormat(ads.getDlAddress())).append("<br>");
417 } else if (action instanceof SetDlDst) {
418 SetDlDst add = (SetDlDst) action;
419 actions.append(action.getType().toString()).append(" = ").append(HexEncode.bytesToHexStringFormat(add.getDlAddress())).append("<br>");
420 } else if (action instanceof SetNwSrc) {
421 SetNwSrc ans = (SetNwSrc) action;
422 actions.append(action.getType().toString()).append(" = ").append(ans.getAddressAsString()).append("<br>");
423 } else if (action instanceof SetNwDst) {
424 SetNwDst and = (SetNwDst) action;
425 actions.append(action.getType().toString()).append(" = ").append(and.getAddressAsString()).append("<br>");
426 } else if (action instanceof SetNwTos) {
427 SetNwTos ant = (SetNwTos) action;
428 actions.append(action.getType().toString()).append(" = ").append(ant.getNwTos()).append("<br>");
429 } else if (action instanceof SetTpSrc) {
430 SetTpSrc ads = (SetTpSrc) action;
431 actions.append(action.getType().toString()).append(" = ").append(ads.getPort()).append("<br>");
432 } else if (action instanceof SetTpDst) {
433 SetTpDst atd = (SetTpDst) action;
434 actions.append(action.getType().toString()).append(" = ").append(atd.getPort()).append("<br>");
435 } else if (action instanceof SetVlanPcp) {
436 SetVlanPcp avp = (SetVlanPcp) action;
437 actions.append(action.getType().toString()).append(" = ").append(avp.getPcp()).append("<br>");
438 // } else if (action instanceof SetDlSrc) {
439 // SetDlSrc ads = (SetDlSrc) action;
441 actions.append(action.getType().toString()).append("<br>");
444 row.put("actions", actions.toString());
445 row.put("durationSeconds",
446 ((Integer) flowOnNode.getDurationSeconds()).toString());
447 row.put("idleTimeout", ((Short) flow.getIdleTimeout()).toString());
448 row.put("priority", String.valueOf(NetUtils.getUnsignedShort(flow.getPriority())));
452 private String getNodeDesc(Node node, ISwitchManager switchManager) {
453 if (switchManager == null) {
456 Description desc = (Description) switchManager.getNodeProp(node, Description.propertyName);
457 return (desc == null) ? "" : desc.getValue();