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",
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) {
232 Map<String, String> row = new HashMap<String, String>();
234 ISwitchManager switchManager = (ISwitchManager) ServiceHelper
235 .getInstance(ISwitchManager.class, containerName, this);
236 NodeConnector nodeConnector = ncStats.getNodeConnector();
237 Description description = (Description) switchManager.getNodeProp(nodeConnector.getNode(), Description.propertyName);
238 String desc = (description == null) ? "" : description.getValue();
239 String nodeName = desc.equalsIgnoreCase("none") ? nodeConnector.getNode().getNodeIDString() : desc;
240 String nodeConnectorDisplayName = nodeConnector.getType() + "|" + nodeConnector.getID() + "@" + nodeName;
241 row.put("nodeConnector",
242 String.valueOf(nodeConnectorDisplayName));
244 row.put("rxPkts", String.valueOf(ncStats.getReceivePacketCount()));
245 row.put("txPkts", String.valueOf(ncStats.getTransmitPacketCount()));
246 row.put("rxBytes", String.valueOf(ncStats.getReceiveByteCount()));
247 row.put("txBytes", String.valueOf(ncStats.getTransmitByteCount()));
248 row.put("rxDrops", String.valueOf(ncStats.getReceiveDropCount()));
249 row.put("txDrops", String.valueOf(ncStats.getTransmitDropCount()));
250 row.put("rxErrors", String.valueOf(ncStats.getReceiveErrorCount()));
251 row.put("txErrors", String.valueOf(ncStats.getTransmitErrorCount()));
252 row.put("rxFrameErrors",
253 String.valueOf(ncStats.getReceiveFrameErrorCount()));
254 row.put("rxOverRunErrors",
255 String.valueOf(ncStats.getReceiveOverRunErrorCount()));
256 row.put("rxCRCErrors",
257 String.valueOf(ncStats.getReceiveCRCErrorCount()));
258 row.put("collisions", String.valueOf(ncStats.getCollisionCount()));
263 private Map<String, String> convertFlowStatistics(Node node,
264 FlowOnNode flowOnNode,
265 String containerName) {
266 Map<String, String> row = new HashMap<String, String>();
267 Flow flow = flowOnNode.getFlow();
268 Match match = flow.getMatch();
269 ISwitchManager switchManager = (ISwitchManager) ServiceHelper
270 .getInstance(ISwitchManager.class, containerName, this);
271 String desc = getNodeDesc(node, switchManager);
272 desc = (desc == null || desc.isEmpty() || desc.equalsIgnoreCase("none"))?
273 node.toString() : desc;
274 row.put("nodeName", desc);
275 if (match.isPresent(MatchType.IN_PORT)) {
276 row.put(MatchType.IN_PORT.id(), ((NodeConnector) flow.getMatch()
277 .getField(MatchType.IN_PORT).getValue())
278 .getNodeConnectorIdAsString());
280 row.put(MatchType.IN_PORT.id(), "*");
282 if (match.isPresent(MatchType.DL_SRC)) {
283 row.put(MatchType.DL_SRC.id(),
284 (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
285 .getField(MatchType.DL_SRC).getValue()))));
287 row.put(MatchType.DL_SRC.id(), "*");
289 if (match.isPresent(MatchType.DL_DST)) {
290 row.put(MatchType.DL_DST.id(),
291 (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
292 .getField(MatchType.DL_DST).getValue()))));
294 row.put(MatchType.DL_DST.id(), "*");
296 if (match.isPresent(MatchType.DL_TYPE)) {
297 row.put(MatchType.DL_TYPE.id(),
298 EtherTypes.getEtherTypeName(((Short) flow.getMatch()
299 .getField(MatchType.DL_TYPE).getValue())));
301 row.put(MatchType.DL_TYPE.id(), "*");
304 // Some physical switch has vlan as ffff to show "any" vlan
305 if (match.isPresent(MatchType.DL_VLAN)) {
306 if (((Short) flow.getMatch().getField(MatchType.DL_VLAN).getValue())
308 row.put(MatchType.DL_VLAN.id(), "0");
310 row.put(MatchType.DL_VLAN.id(), ((Short) flow.getMatch()
311 .getField(MatchType.DL_VLAN).getValue()).toString());
314 row.put(MatchType.DL_VLAN.id(), "*");
316 if (match.isPresent(MatchType.NW_SRC)) {
317 row.put(MatchType.NW_SRC.id(), ((InetAddress) flow.getMatch()
318 .getField(MatchType.NW_SRC).getValue()).getHostAddress());
320 row.put(MatchType.NW_SRC.id(), "*");
322 if (match.isPresent(MatchType.NW_DST)) {
323 row.put(MatchType.NW_DST.id(), ((InetAddress) flow.getMatch()
324 .getField(MatchType.NW_DST).getValue()).getHostAddress());
326 row.put(MatchType.NW_DST.id(), "*");
328 if (match.isPresent(MatchType.NW_PROTO)) {
329 row.put(MatchType.NW_PROTO.id(),
330 IPProtocols.getProtocolName(((Byte) flow.getMatch()
331 .getField(MatchType.NW_PROTO).getValue())));
333 row.put(MatchType.NW_PROTO.id(), "*");
335 if (match.isPresent(MatchType.TP_SRC)) {
336 Short tpSrc = (Short) (flow.getMatch().getField(MatchType.TP_SRC)
338 row.put(MatchType.TP_SRC.id(),
339 String.valueOf(NetUtils.getUnsignedShort(tpSrc)));
341 row.put(MatchType.TP_SRC.id(), "*");
343 if (match.isPresent(MatchType.TP_DST)) {
344 Short tpDst = (Short) (flow.getMatch().getField(MatchType.TP_DST)
346 row.put(MatchType.TP_DST.id(),
347 String.valueOf(NetUtils.getUnsignedShort(tpDst)));
349 row.put(MatchType.TP_DST.id(), "*");
352 row.put("byteCount", ((Long) flowOnNode.getByteCount()).toString());
353 row.put("packetCount", ((Long) flowOnNode.getPacketCount()).toString());
355 StringBuffer actions = new StringBuffer();
356 StringBuffer outPorts = new StringBuffer();
357 for (Action action : flow.getActions()) {
359 if (action instanceof Output) {
360 Output ao = (Output) action;
361 if (outPorts.length() > 0) {
362 outPorts.append(" ");
364 actions.append(action.getType().toString() + " = "
365 + ao.getPort().getNodeConnectorIdAsString() + "<br>");
366 } else if (action instanceof SetVlanId) {
367 SetVlanId av = (SetVlanId) action;
368 String outVlanId = String.valueOf(av.getVlanId());
369 actions.append(action.getType().toString() + " = " + outVlanId
371 } else if (action instanceof SetDlSrc) {
372 SetDlSrc ads = (SetDlSrc) action;
373 actions.append(action.getType().toString() + " = "
374 + HexEncode.bytesToHexStringFormat(ads.getDlAddress()) + "<br>");
375 } else if (action instanceof SetDlDst) {
376 SetDlDst add = (SetDlDst) action;
377 actions.append(action.getType().toString() + " = "
378 + HexEncode.bytesToHexStringFormat(add.getDlAddress())
380 } else if (action instanceof SetNwSrc) {
381 SetNwSrc ans = (SetNwSrc) action;
382 actions.append(action.getType().toString() + " = "
383 + ans.getAddressAsString() + "<br>");
384 } else if (action instanceof SetNwDst) {
385 SetNwDst and = (SetNwDst) action;
386 actions.append(action.getType().toString() + " = "
387 + and.getAddressAsString() + "<br>");
388 } else if (action instanceof SetNwTos) {
389 SetNwTos ant = (SetNwTos) action;
390 actions.append(action.getType().toString() + " = "
391 + ant.getNwTos() + "<br>");
392 } else if (action instanceof SetTpSrc) {
393 SetTpSrc ads = (SetTpSrc) action;
394 actions.append(action.getType().toString() + " = "
395 + ads.getPort() + "<br>");
396 } else if (action instanceof SetTpDst) {
397 SetTpDst atd = (SetTpDst) action;
398 actions.append(action.getType().toString() + " = "
399 + atd.getPort() + "<br>");
400 } else if (action instanceof SetVlanPcp) {
401 SetVlanPcp avp = (SetVlanPcp) action;
402 actions.append(action.getType().toString() + " = "
403 + avp.getPcp() + "<br>");
404 // } else if (action instanceof SetDlSrc) {
405 // SetDlSrc ads = (SetDlSrc) action;
407 actions.append(action.getType().toString() + "<br>");
410 row.put("actions", actions.toString());
411 row.put("durationSeconds",
412 ((Integer) flowOnNode.getDurationSeconds()).toString());
413 row.put("idleTimeout", ((Short) flow.getIdleTimeout()).toString());
414 row.put("priority", String.valueOf(flow.getPriority()));
418 private String getNodeDesc(Node node, ISwitchManager switchManager) {
419 if (switchManager == null) {
422 Description desc = (Description) switchManager.getNodeProp(node, Description.propertyName);
423 return (desc == null) ? "" : desc.getValue();