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.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;
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","Vlan Priority", "NW Src", "NW Dst","ToS Bits",
66 "NW Proto", "TP Src", "TP Dst", "Actions", "Bytes", "Packets",
67 "Time (s)", "Timeout (s)",
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;
80 public Troubleshoot() {
81 ServiceHelper.registerGlobalService(IDaylightWeb.class, this, null);
85 public String getWebName() {
90 public String getWebId() {
95 public short getWebOrder() {
100 public boolean isAuthorized(UserLevel userLevel) {
101 return userLevel.ordinal() <= AUTH_LEVEL.ordinal();
104 @RequestMapping(value = "/existingNodes", method = RequestMethod.GET)
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;
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);
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());
128 TroubleshootingJsonBean result = new TroubleshootingJsonBean();
129 result.setColumnNames(nodesColumnNames);
130 result.setNodeData(lines);
134 @RequestMapping(value = "/uptime", method = RequestMethod.GET)
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;
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);
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);
163 TroubleshootingJsonBean result = new TroubleshootingJsonBean();
164 result.setColumnNames(nodeStatsColumnNames);
165 result.setNodeData(lines);
169 @RequestMapping(value = "/flowStats", method = RequestMethod.GET)
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;
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);
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));
193 TroubleshootingJsonBean result = new TroubleshootingJsonBean();
194 result.setColumnNames(flowStatsColumnNames);
195 result.setNodeData(cells);
199 @RequestMapping(value = "/portStats", method = RequestMethod.GET)
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;
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);
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));
224 TroubleshootingJsonBean result = new TroubleshootingJsonBean();
225 result.setColumnNames(portStatsColumnNames);
226 result.setNodeData(cells);
230 private Map<String, String> convertPortsStatistics(
231 NodeConnectorStatistics ncStats, String containerName) {
233 Map<String, String> row = new HashMap<String, String>();
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));
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()));
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());
281 row.put(MatchType.IN_PORT.id(), "*");
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()))));
288 row.put(MatchType.DL_SRC.id(), "*");
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()))));
295 row.put(MatchType.DL_DST.id(), "*");
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())));
302 row.put(MatchType.DL_TYPE.id(), "*");
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())
309 row.put(MatchType.DL_VLAN.id(), "0");
311 row.put(MatchType.DL_VLAN.id(), ((Short) flow.getMatch()
312 .getField(MatchType.DL_VLAN).getValue()).toString());
315 row.put(MatchType.DL_VLAN.id(), "*");
318 if (match.isPresent(MatchType.DL_VLAN_PR)) {
319 if (((Byte) flow.getMatch().getField(MatchType.DL_VLAN_PR).getValue())
321 row.put(MatchType.DL_VLAN_PR.id(), "0");
323 row.put(MatchType.DL_VLAN_PR.id(), ((Byte) flow.getMatch()
324 .getField(MatchType.DL_VLAN_PR).getValue()).toString());
327 row.put(MatchType.DL_VLAN_PR.id(), "*");
330 if (match.isPresent(MatchType.NW_SRC)) {
331 row.put(MatchType.NW_SRC.id(), ((InetAddress) flow.getMatch()
332 .getField(MatchType.NW_SRC).getValue()).getHostAddress());
334 row.put(MatchType.NW_SRC.id(), "*");
336 if (match.isPresent(MatchType.NW_DST)) {
337 row.put(MatchType.NW_DST.id(), ((InetAddress) flow.getMatch()
338 .getField(MatchType.NW_DST).getValue()).getHostAddress());
340 row.put(MatchType.NW_DST.id(), "*");
342 if (match.isPresent(MatchType.NW_TOS)) {
343 row.put(MatchType.NW_TOS.id(), ((Byte) flow.getMatch()
344 .getField(MatchType.NW_TOS).getValue()).toString());
346 row.put(MatchType.NW_TOS.id(), "*");
348 if (match.isPresent(MatchType.NW_PROTO)) {
349 row.put(MatchType.NW_PROTO.id(),
350 IPProtocols.getProtocolName(((Byte) flow.getMatch()
351 .getField(MatchType.NW_PROTO).getValue())));
353 row.put(MatchType.NW_PROTO.id(), "*");
355 if (match.isPresent(MatchType.TP_SRC)) {
356 Short tpSrc = (Short) (flow.getMatch().getField(MatchType.TP_SRC)
358 row.put(MatchType.TP_SRC.id(),
359 String.valueOf(NetUtils.getUnsignedShort(tpSrc)));
361 row.put(MatchType.TP_SRC.id(), "*");
363 if (match.isPresent(MatchType.TP_DST)) {
364 Short tpDst = (Short) (flow.getMatch().getField(MatchType.TP_DST)
366 row.put(MatchType.TP_DST.id(),
367 String.valueOf(NetUtils.getUnsignedShort(tpDst)));
369 row.put(MatchType.TP_DST.id(), "*");
372 row.put("byteCount", ((Long) flowOnNode.getByteCount()).toString());
373 row.put("packetCount", ((Long) flowOnNode.getPacketCount()).toString());
375 StringBuffer actions = new StringBuffer();
376 StringBuffer outPorts = new StringBuffer();
377 for (Action action : flow.getActions()) {
379 if (action instanceof Output) {
380 Output ao = (Output) action;
381 if (outPorts.length() > 0) {
382 outPorts.append(" ");
384 actions.append(action.getType().toString()).append(" = ").append(ao.getPort().getNodeConnectorIdAsString()).append("<br>");
385 } else if (action instanceof SetVlanId) {
386 SetVlanId av = (SetVlanId) action;
387 String outVlanId = String.valueOf(av.getVlanId());
388 actions.append(action.getType().toString()).append(" = ").append(outVlanId).append("<br>");
389 } else if (action instanceof SetDlSrc) {
390 SetDlSrc ads = (SetDlSrc) action;
391 actions.append(action.getType().toString()).append(" = ").append(HexEncode.bytesToHexStringFormat(ads.getDlAddress())).append("<br>");
392 } else if (action instanceof SetDlDst) {
393 SetDlDst add = (SetDlDst) action;
394 actions.append(action.getType().toString()).append(" = ").append(HexEncode.bytesToHexStringFormat(add.getDlAddress())).append("<br>");
395 } else if (action instanceof SetNwSrc) {
396 SetNwSrc ans = (SetNwSrc) action;
397 actions.append(action.getType().toString()).append(" = ").append(ans.getAddressAsString()).append("<br>");
398 } else if (action instanceof SetNwDst) {
399 SetNwDst and = (SetNwDst) action;
400 actions.append(action.getType().toString()).append(" = ").append(and.getAddressAsString()).append("<br>");
401 } else if (action instanceof SetNwTos) {
402 SetNwTos ant = (SetNwTos) action;
403 actions.append(action.getType().toString()).append(" = ").append(ant.getNwTos()).append("<br>");
404 } else if (action instanceof SetTpSrc) {
405 SetTpSrc ads = (SetTpSrc) action;
406 actions.append(action.getType().toString()).append(" = ").append(ads.getPort()).append("<br>");
407 } else if (action instanceof SetTpDst) {
408 SetTpDst atd = (SetTpDst) action;
409 actions.append(action.getType().toString()).append(" = ").append(atd.getPort()).append("<br>");
410 } else if (action instanceof SetVlanPcp) {
411 SetVlanPcp avp = (SetVlanPcp) action;
412 actions.append(action.getType().toString()).append(" = ").append(avp.getPcp()).append("<br>");
413 // } else if (action instanceof SetDlSrc) {
414 // SetDlSrc ads = (SetDlSrc) action;
416 actions.append(action.getType().toString()).append("<br>");
419 row.put("actions", actions.toString());
420 row.put("durationSeconds",
421 ((Integer) flowOnNode.getDurationSeconds()).toString());
422 row.put("idleTimeout", ((Short) flow.getIdleTimeout()).toString());
423 row.put("priority", String.valueOf(NetUtils.getUnsignedShort(flow.getPriority())));
427 private String getNodeDesc(Node node, ISwitchManager switchManager) {
428 if (switchManager == null) {
431 Description desc = (Description) switchManager.getNodeProp(node, Description.propertyName);
432 return (desc == null) ? "" : desc.getValue();