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