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", "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(), "*");
317 if (match.isPresent(MatchType.NW_SRC)) {
318 row.put(MatchType.NW_SRC.id(), ((InetAddress) flow.getMatch()
319 .getField(MatchType.NW_SRC).getValue()).getHostAddress());
321 row.put(MatchType.NW_SRC.id(), "*");
323 if (match.isPresent(MatchType.NW_DST)) {
324 row.put(MatchType.NW_DST.id(), ((InetAddress) flow.getMatch()
325 .getField(MatchType.NW_DST).getValue()).getHostAddress());
327 row.put(MatchType.NW_DST.id(), "*");
329 if (match.isPresent(MatchType.NW_TOS)) {
330 row.put(MatchType.NW_TOS.id(), ((Byte) flow.getMatch()
331 .getField(MatchType.NW_TOS).getValue()).toString());
333 row.put(MatchType.NW_TOS.id(), "*");
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())));
340 row.put(MatchType.NW_PROTO.id(), "*");
342 if (match.isPresent(MatchType.TP_SRC)) {
343 Short tpSrc = (Short) (flow.getMatch().getField(MatchType.TP_SRC)
345 row.put(MatchType.TP_SRC.id(),
346 String.valueOf(NetUtils.getUnsignedShort(tpSrc)));
348 row.put(MatchType.TP_SRC.id(), "*");
350 if (match.isPresent(MatchType.TP_DST)) {
351 Short tpDst = (Short) (flow.getMatch().getField(MatchType.TP_DST)
353 row.put(MatchType.TP_DST.id(),
354 String.valueOf(NetUtils.getUnsignedShort(tpDst)));
356 row.put(MatchType.TP_DST.id(), "*");
359 row.put("byteCount", ((Long) flowOnNode.getByteCount()).toString());
360 row.put("packetCount", ((Long) flowOnNode.getPacketCount()).toString());
362 StringBuffer actions = new StringBuffer();
363 StringBuffer outPorts = new StringBuffer();
364 for (Action action : flow.getActions()) {
366 if (action instanceof Output) {
367 Output ao = (Output) action;
368 if (outPorts.length() > 0) {
369 outPorts.append(" ");
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;
403 actions.append(action.getType().toString()).append("<br>");
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()));
414 private String getNodeDesc(Node node, ISwitchManager switchManager) {
415 if (switchManager == null) {
418 Description desc = (Description) switchManager.getNodeProp(node, Description.propertyName);
419 return (desc == null) ? "" : desc.getValue();