blob: ed11cbe04f4caa702000d928708703b47189d206 [file] [log] [blame]
Andrea Campanella01e886e2017-12-15 15:27:31 +01001/*
Andrea Campanellaaf34b7c2018-02-08 17:10:11 +01002 * Copyright 2018-present Open Networking Foundation
Andrea Campanella01e886e2017-12-15 15:27:31 +01003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.t3.cli;
18
Andrea Campanella6f2d6742018-02-07 12:00:12 +010019import com.google.common.base.Preconditions;
Ray Milkey86ad7bb2018-09-27 12:32:28 -070020import org.apache.karaf.shell.api.action.Command;
21import org.apache.karaf.shell.api.action.Option;
Ray Milkey7a2dee52018-09-28 10:58:28 -070022import org.apache.karaf.shell.api.action.lifecycle.Service;
Andrea Campanella01e886e2017-12-15 15:27:31 +010023import org.onlab.packet.IpAddress;
24import org.onlab.packet.MacAddress;
Andrea Campanella09ca07a2018-01-25 16:44:04 +010025import org.onlab.packet.MplsLabel;
Andrea Campanella01e886e2017-12-15 15:27:31 +010026import org.onlab.packet.TpPort;
27import org.onlab.packet.VlanId;
28import org.onosproject.cli.AbstractShellCommand;
29import org.onosproject.net.ConnectPoint;
Andrea Campanella6f2d6742018-02-07 12:00:12 +010030import org.onosproject.net.DeviceId;
31import org.onosproject.net.PortNumber;
Andrea Campanella01e886e2017-12-15 15:27:31 +010032import org.onosproject.net.flow.DefaultTrafficSelector;
33import org.onosproject.net.flow.TrafficSelector;
Andrea Campanella01e886e2017-12-15 15:27:31 +010034import org.onosproject.t3.api.StaticPacketTrace;
35import org.onosproject.t3.api.TroubleshootService;
36
Andrea Campanella8be1af92018-01-24 15:14:03 +010037import static org.onlab.packet.EthType.EtherType;
38
Andrea Campanella01e886e2017-12-15 15:27:31 +010039/**
40 * Starts a Static Packet Trace for a given input and prints the result.
41 */
Ray Milkey7a2dee52018-09-28 10:58:28 -070042@Service
Andrea Campanella36769e22018-02-26 11:03:48 +010043@Command(scope = "onos", name = "t3-troubleshoot",
Andrea Campanella01e886e2017-12-15 15:27:31 +010044 description = "troubleshoots flows and groups between source and destination")
45public class TroubleshootTraceCommand extends AbstractShellCommand {
46
47
48 private static final String FLOW_SHORT_FORMAT = " %s, bytes=%s, packets=%s, "
49 + "table=%s, priority=%s, selector=%s, treatment=%s";
50
51 private static final String GROUP_FORMAT =
52 " id=0x%s, state=%s, type=%s, bytes=%s, packets=%s, appId=%s, referenceCount=%s";
53 private static final String GROUP_BUCKET_FORMAT =
54 " id=0x%s, bucket=%s, bytes=%s, packets=%s, actions=%s";
55
Andrea Campanella6f2d6742018-02-07 12:00:12 +010056 private static final String CONTROLLER = "CONTROLLER";
57
Andrea Campanella01e886e2017-12-15 15:27:31 +010058 @Option(name = "-v", aliases = "--verbose", description = "Outputs complete path")
59 private boolean verbosity1 = false;
60
61 @Option(name = "-vv", aliases = "--veryverbose", description = "Outputs flows and groups for every device")
62 private boolean verbosity2 = false;
63
64 @Option(name = "-s", aliases = "--srcIp", description = "Source IP")
65 String srcIp = null;
66
67 @Option(name = "-sp", aliases = "--srcPort", description = "Source Port", required = true)
68 String srcPort = null;
69
70 @Option(name = "-sm", aliases = "--srcMac", description = "Source MAC")
71 String srcMac = null;
72
73 @Option(name = "-et", aliases = "--ethType", description = "ETH Type", valueToShowInHelp = "ipv4")
74 String ethType = "ipv4";
75
76 @Option(name = "-stp", aliases = "--srcTcpPort", description = "Source TCP Port")
77 String srcTcpPort = null;
78
Andrea Campanella8be1af92018-01-24 15:14:03 +010079 @Option(name = "-d", aliases = "--dstIp", description = "Destination IP")
80 String dstIp = null;
Andrea Campanella01e886e2017-12-15 15:27:31 +010081
82 @Option(name = "-dm", aliases = "--dstMac", description = "Destination MAC")
83 String dstMac = null;
84
Andrea Campanella6f2d6742018-02-07 12:00:12 +010085 @Option(name = "-dtp", aliases = "--dstTcpPort", description = "destination TCP Port")
Andrea Campanella01e886e2017-12-15 15:27:31 +010086 String dstTcpPort = null;
87
88 @Option(name = "-vid", aliases = "--vlanId", description = "Vlan of incoming packet", valueToShowInHelp = "None")
89 String vlan = "None";
90
Andrea Campanella09ca07a2018-01-25 16:44:04 +010091 @Option(name = "-ml", aliases = "--mplsLabel", description = "Mpls label of incoming packet")
92 String mplsLabel = null;
93
Andrea Campanellad5bb2ef2018-01-31 16:43:23 +010094 @Option(name = "-mb", aliases = "--mplsBos", description = "MPLS BOS")
Andrea Campanella09ca07a2018-01-25 16:44:04 +010095 String mplsBos = null;
Andrea Campanella01e886e2017-12-15 15:27:31 +010096
Andrea Campanellad5bb2ef2018-01-31 16:43:23 +010097 @Option(name = "-ipp", aliases = "--ipProto", description = "IP Proto")
98 String ipProto = null;
99
100 @Option(name = "-udps", aliases = "--udpSrc", description = "UDP Source")
101 String udpSrc = null;
102
103 @Option(name = "-udpd", aliases = "--udpDst", description = "UDP Destination")
104 String udpDst = null;
105
Andrea Campanella01e886e2017-12-15 15:27:31 +0100106 @Override
Ray Milkey86ad7bb2018-09-27 12:32:28 -0700107 protected void doExecute() {
Andrea Campanella01e886e2017-12-15 15:27:31 +0100108 TroubleshootService service = get(TroubleshootService.class);
Andrea Campanella6f2d6742018-02-07 12:00:12 +0100109 String[] cpInfo = srcPort.split("/");
110 Preconditions.checkArgument(cpInfo.length == 2, "wrong format of source port");
111 ConnectPoint cp;
112 //Uses input port as a convenience to carry the Controller port, proper flood behaviour is handled in the
113 // troubleshoot manager.
114 if (cpInfo[1].equalsIgnoreCase(CONTROLLER)) {
115 cp = new ConnectPoint(DeviceId.deviceId(cpInfo[0]), PortNumber.CONTROLLER);
116 } else {
117 cp = ConnectPoint.deviceConnectPoint(srcPort);
118 }
119
Andrea Campanella8be1af92018-01-24 15:14:03 +0100120 EtherType type = EtherType.valueOf(ethType.toUpperCase());
Andrea Campanella01e886e2017-12-15 15:27:31 +0100121
122 //Input Port must be specified
123 TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder()
124 .matchInPort(cp.port());
125
126 if (srcIp != null) {
Andrea Campanella8be1af92018-01-24 15:14:03 +0100127 if (type.equals(EtherType.IPV6)) {
128 selectorBuilder.matchIPv6Src(IpAddress.valueOf(srcIp).toIpPrefix());
129 } else {
130 selectorBuilder.matchIPSrc(IpAddress.valueOf(srcIp).toIpPrefix());
131 }
Andrea Campanella01e886e2017-12-15 15:27:31 +0100132 }
133
134 if (srcMac != null) {
135 selectorBuilder.matchEthSrc(MacAddress.valueOf(srcMac));
136 }
137
138 //if EthType option is not specified using IPv4
Andrea Campanella8be1af92018-01-24 15:14:03 +0100139 selectorBuilder.matchEthType(type.ethType().toShort());
Andrea Campanella01e886e2017-12-15 15:27:31 +0100140
141 if (srcTcpPort != null) {
142 selectorBuilder.matchTcpSrc(TpPort.tpPort(Integer.parseInt(srcTcpPort)));
143 }
144
Andrea Campanella8be1af92018-01-24 15:14:03 +0100145 if (dstIp != null) {
146 if (type.equals(EtherType.IPV6)) {
147 selectorBuilder.matchIPv6Dst(IpAddress.valueOf(dstIp).toIpPrefix());
148 } else {
149 selectorBuilder.matchIPDst(IpAddress.valueOf(dstIp).toIpPrefix());
150 }
151 }
Andrea Campanella01e886e2017-12-15 15:27:31 +0100152
153 if (dstMac != null) {
154 selectorBuilder.matchEthDst(MacAddress.valueOf(dstMac));
155 }
156 if (dstTcpPort != null) {
157 selectorBuilder.matchTcpDst(TpPort.tpPort(Integer.parseInt(dstTcpPort)));
158 }
159
160 //if vlan option is not specified using NONE
161 selectorBuilder.matchVlanId(VlanId.vlanId(vlan));
162
Andrea Campanella09ca07a2018-01-25 16:44:04 +0100163 if (mplsLabel != null) {
164 selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(Integer.parseInt(mplsLabel)));
165 }
166
167 if (mplsBos != null) {
168 selectorBuilder.matchMplsBos(Boolean.valueOf(mplsBos));
169 }
Andrea Campanella01e886e2017-12-15 15:27:31 +0100170
Andrea Campanellad5bb2ef2018-01-31 16:43:23 +0100171 if (ipProto != null) {
172 selectorBuilder.matchIPProtocol(Byte.valueOf(ipProto));
173 }
174
175 if (udpSrc != null) {
176 selectorBuilder.matchUdpSrc(TpPort.tpPort(Integer.parseInt(udpSrc)));
177 }
178
179 if (udpDst != null) {
180 selectorBuilder.matchUdpDst(TpPort.tpPort(Integer.parseInt(udpDst)));
181 }
182
183
Andrea Campanella01e886e2017-12-15 15:27:31 +0100184 TrafficSelector packet = selectorBuilder.build();
185
186 //Printing the created packet
187 print("Tracing packet: %s", packet.criteria());
188
189 //Build the trace
190 StaticPacketTrace trace = service.trace(packet, cp);
Andrea Campanella01e886e2017-12-15 15:27:31 +0100191
Andrea Campanellaaf34b7c2018-02-08 17:10:11 +0100192 print("%s", T3CliUtils.printTrace(trace, verbosity1, verbosity2));
Andrea Campanella01e886e2017-12-15 15:27:31 +0100193
Andrea Campanella01e886e2017-12-15 15:27:31 +0100194 }
195}