blob: db7d69febad1357dd3e405e7c062e4ab84cdae1b [file] [log] [blame]
Andrea Campanellae4084402017-12-15 15:27:31 +01001/*
Andrea Campanella55c3f422018-02-08 17:10:11 +01002 * Copyright 2018-present Open Networking Foundation
Andrea Campanellae4084402017-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 Campanella1445f7a2018-02-07 12:00:12 +010019import com.google.common.base.Preconditions;
Ray Milkey822567d2018-09-27 12:32:28 -070020import org.apache.karaf.shell.api.action.Command;
Seyeon Jeong83e79862020-02-28 01:17:34 -080021import org.apache.karaf.shell.api.action.Completion;
Ray Milkey822567d2018-09-27 12:32:28 -070022import org.apache.karaf.shell.api.action.Option;
Ray Milkeyac725032018-09-28 10:58:28 -070023import org.apache.karaf.shell.api.action.lifecycle.Service;
Andrea Campanellae4084402017-12-15 15:27:31 +010024import org.onlab.packet.IpAddress;
25import org.onlab.packet.MacAddress;
Andrea Campanella3970e472018-01-25 16:44:04 +010026import org.onlab.packet.MplsLabel;
Andrea Campanellae4084402017-12-15 15:27:31 +010027import org.onlab.packet.TpPort;
28import org.onlab.packet.VlanId;
29import org.onosproject.cli.AbstractShellCommand;
Seyeon Jeong83e79862020-02-28 01:17:34 -080030import org.onosproject.cli.PlaceholderCompleter;
31import org.onosproject.cli.net.ConnectPointCompleter;
32import org.onosproject.cli.net.EthTypeCompleter;
33import org.onosproject.cli.net.IpProtocolCompleter;
Andrea Campanellae4084402017-12-15 15:27:31 +010034import org.onosproject.net.ConnectPoint;
Andrea Campanella1445f7a2018-02-07 12:00:12 +010035import org.onosproject.net.DeviceId;
36import org.onosproject.net.PortNumber;
Andrea Campanellae4084402017-12-15 15:27:31 +010037import org.onosproject.net.flow.DefaultTrafficSelector;
38import org.onosproject.net.flow.TrafficSelector;
Andrea Campanellae4084402017-12-15 15:27:31 +010039import org.onosproject.t3.api.StaticPacketTrace;
40import org.onosproject.t3.api.TroubleshootService;
41
Andrea Campanella7db72fc2018-01-24 15:14:03 +010042import static org.onlab.packet.EthType.EtherType;
43
Andrea Campanellae4084402017-12-15 15:27:31 +010044/**
45 * Starts a Static Packet Trace for a given input and prints the result.
46 */
Ray Milkeyac725032018-09-28 10:58:28 -070047@Service
Andrea Campanellad756ede2018-02-26 11:03:48 +010048@Command(scope = "onos", name = "t3-troubleshoot",
Andrea Campanellae4084402017-12-15 15:27:31 +010049 description = "troubleshoots flows and groups between source and destination")
50public class TroubleshootTraceCommand extends AbstractShellCommand {
51
52
53 private static final String FLOW_SHORT_FORMAT = " %s, bytes=%s, packets=%s, "
54 + "table=%s, priority=%s, selector=%s, treatment=%s";
55
56 private static final String GROUP_FORMAT =
57 " id=0x%s, state=%s, type=%s, bytes=%s, packets=%s, appId=%s, referenceCount=%s";
58 private static final String GROUP_BUCKET_FORMAT =
59 " id=0x%s, bucket=%s, bytes=%s, packets=%s, actions=%s";
60
Andrea Campanella1445f7a2018-02-07 12:00:12 +010061 private static final String CONTROLLER = "CONTROLLER";
62
Andrea Campanellae4084402017-12-15 15:27:31 +010063 @Option(name = "-v", aliases = "--verbose", description = "Outputs complete path")
Seyeon Jeong83e79862020-02-28 01:17:34 -080064 @Completion(PlaceholderCompleter.class)
Andrea Campanellae4084402017-12-15 15:27:31 +010065 private boolean verbosity1 = false;
66
67 @Option(name = "-vv", aliases = "--veryverbose", description = "Outputs flows and groups for every device")
Seyeon Jeong83e79862020-02-28 01:17:34 -080068 @Completion(PlaceholderCompleter.class)
Andrea Campanellae4084402017-12-15 15:27:31 +010069 private boolean verbosity2 = false;
70
71 @Option(name = "-s", aliases = "--srcIp", description = "Source IP")
Seyeon Jeong83e79862020-02-28 01:17:34 -080072 @Completion(PlaceholderCompleter.class)
Andrea Campanellae4084402017-12-15 15:27:31 +010073 String srcIp = null;
74
75 @Option(name = "-sp", aliases = "--srcPort", description = "Source Port", required = true)
Seyeon Jeong83e79862020-02-28 01:17:34 -080076 @Completion(ConnectPointCompleter.class)
Andrea Campanellae4084402017-12-15 15:27:31 +010077 String srcPort = null;
78
79 @Option(name = "-sm", aliases = "--srcMac", description = "Source MAC")
Seyeon Jeong83e79862020-02-28 01:17:34 -080080 @Completion(PlaceholderCompleter.class)
Andrea Campanellae4084402017-12-15 15:27:31 +010081 String srcMac = null;
82
83 @Option(name = "-et", aliases = "--ethType", description = "ETH Type", valueToShowInHelp = "ipv4")
Seyeon Jeong83e79862020-02-28 01:17:34 -080084 @Completion(EthTypeCompleter.class)
Andrea Campanellae4084402017-12-15 15:27:31 +010085 String ethType = "ipv4";
86
87 @Option(name = "-stp", aliases = "--srcTcpPort", description = "Source TCP Port")
Seyeon Jeong83e79862020-02-28 01:17:34 -080088 @Completion(PlaceholderCompleter.class)
Andrea Campanellae4084402017-12-15 15:27:31 +010089 String srcTcpPort = null;
90
Andrea Campanella7db72fc2018-01-24 15:14:03 +010091 @Option(name = "-d", aliases = "--dstIp", description = "Destination IP")
Seyeon Jeong83e79862020-02-28 01:17:34 -080092 @Completion(PlaceholderCompleter.class)
Andrea Campanella7db72fc2018-01-24 15:14:03 +010093 String dstIp = null;
Andrea Campanellae4084402017-12-15 15:27:31 +010094
95 @Option(name = "-dm", aliases = "--dstMac", description = "Destination MAC")
Seyeon Jeong83e79862020-02-28 01:17:34 -080096 @Completion(PlaceholderCompleter.class)
Andrea Campanellae4084402017-12-15 15:27:31 +010097 String dstMac = null;
98
Andrea Campanella1445f7a2018-02-07 12:00:12 +010099 @Option(name = "-dtp", aliases = "--dstTcpPort", description = "destination TCP Port")
Seyeon Jeong83e79862020-02-28 01:17:34 -0800100 @Completion(PlaceholderCompleter.class)
Andrea Campanellae4084402017-12-15 15:27:31 +0100101 String dstTcpPort = null;
102
103 @Option(name = "-vid", aliases = "--vlanId", description = "Vlan of incoming packet", valueToShowInHelp = "None")
Seyeon Jeong83e79862020-02-28 01:17:34 -0800104 @Completion(PlaceholderCompleter.class)
Andrea Campanellae4084402017-12-15 15:27:31 +0100105 String vlan = "None";
106
Andrea Campanella3970e472018-01-25 16:44:04 +0100107 @Option(name = "-ml", aliases = "--mplsLabel", description = "Mpls label of incoming packet")
Seyeon Jeong83e79862020-02-28 01:17:34 -0800108 @Completion(PlaceholderCompleter.class)
Andrea Campanella3970e472018-01-25 16:44:04 +0100109 String mplsLabel = null;
110
Andrea Campanella8292ba62018-01-31 16:43:23 +0100111 @Option(name = "-mb", aliases = "--mplsBos", description = "MPLS BOS")
Seyeon Jeong83e79862020-02-28 01:17:34 -0800112 @Completion(PlaceholderCompleter.class)
Andrea Campanella3970e472018-01-25 16:44:04 +0100113 String mplsBos = null;
Andrea Campanellae4084402017-12-15 15:27:31 +0100114
Andrea Campanella8292ba62018-01-31 16:43:23 +0100115 @Option(name = "-ipp", aliases = "--ipProto", description = "IP Proto")
Seyeon Jeong83e79862020-02-28 01:17:34 -0800116 @Completion(IpProtocolCompleter.class)
Andrea Campanella8292ba62018-01-31 16:43:23 +0100117 String ipProto = null;
118
119 @Option(name = "-udps", aliases = "--udpSrc", description = "UDP Source")
Seyeon Jeong83e79862020-02-28 01:17:34 -0800120 @Completion(PlaceholderCompleter.class)
Andrea Campanella8292ba62018-01-31 16:43:23 +0100121 String udpSrc = null;
122
123 @Option(name = "-udpd", aliases = "--udpDst", description = "UDP Destination")
Seyeon Jeong83e79862020-02-28 01:17:34 -0800124 @Completion(PlaceholderCompleter.class)
Andrea Campanella8292ba62018-01-31 16:43:23 +0100125 String udpDst = null;
126
Andrea Campanellae4084402017-12-15 15:27:31 +0100127 @Override
Ray Milkey822567d2018-09-27 12:32:28 -0700128 protected void doExecute() {
Andrea Campanellae4084402017-12-15 15:27:31 +0100129 TroubleshootService service = get(TroubleshootService.class);
Seyeon Jeong5018bdd2020-02-28 01:17:34 -0800130 if (!service.checkNibValidity()) {
131 // if the NIB is found invalid, fill it with the current network states so that this command can proceed
132 print(T3CliUtils.NIB_AUTOFILLED);
133 TroubleshootLoadSnapshotCommand cmd = new TroubleshootLoadSnapshotCommand();
134 cmd.doExecute();
135 if (!service.checkNibValidity()) {
136 // if the NIB is still invalid even after auto-filled snapshots, stop and warn
137 print(T3CliUtils.NIB_TERMINATE);
138 return;
139 }
140 } else {
141 print(service.printNibSummary());
Seyeon Jeong83e79862020-02-28 01:17:34 -0800142 }
143
Andrea Campanella1445f7a2018-02-07 12:00:12 +0100144 String[] cpInfo = srcPort.split("/");
145 Preconditions.checkArgument(cpInfo.length == 2, "wrong format of source port");
146 ConnectPoint cp;
147 //Uses input port as a convenience to carry the Controller port, proper flood behaviour is handled in the
148 // troubleshoot manager.
149 if (cpInfo[1].equalsIgnoreCase(CONTROLLER)) {
150 cp = new ConnectPoint(DeviceId.deviceId(cpInfo[0]), PortNumber.CONTROLLER);
151 } else {
152 cp = ConnectPoint.deviceConnectPoint(srcPort);
153 }
154
Andrea Campanella7db72fc2018-01-24 15:14:03 +0100155 EtherType type = EtherType.valueOf(ethType.toUpperCase());
Andrea Campanellae4084402017-12-15 15:27:31 +0100156
157 //Input Port must be specified
158 TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder()
159 .matchInPort(cp.port());
160
161 if (srcIp != null) {
Andrea Campanella7db72fc2018-01-24 15:14:03 +0100162 if (type.equals(EtherType.IPV6)) {
163 selectorBuilder.matchIPv6Src(IpAddress.valueOf(srcIp).toIpPrefix());
164 } else {
165 selectorBuilder.matchIPSrc(IpAddress.valueOf(srcIp).toIpPrefix());
166 }
Andrea Campanellae4084402017-12-15 15:27:31 +0100167 }
168
169 if (srcMac != null) {
170 selectorBuilder.matchEthSrc(MacAddress.valueOf(srcMac));
171 }
172
173 //if EthType option is not specified using IPv4
Andrea Campanella7db72fc2018-01-24 15:14:03 +0100174 selectorBuilder.matchEthType(type.ethType().toShort());
Andrea Campanellae4084402017-12-15 15:27:31 +0100175
176 if (srcTcpPort != null) {
177 selectorBuilder.matchTcpSrc(TpPort.tpPort(Integer.parseInt(srcTcpPort)));
178 }
179
Andrea Campanella7db72fc2018-01-24 15:14:03 +0100180 if (dstIp != null) {
181 if (type.equals(EtherType.IPV6)) {
182 selectorBuilder.matchIPv6Dst(IpAddress.valueOf(dstIp).toIpPrefix());
183 } else {
184 selectorBuilder.matchIPDst(IpAddress.valueOf(dstIp).toIpPrefix());
185 }
186 }
Andrea Campanellae4084402017-12-15 15:27:31 +0100187
188 if (dstMac != null) {
189 selectorBuilder.matchEthDst(MacAddress.valueOf(dstMac));
190 }
191 if (dstTcpPort != null) {
192 selectorBuilder.matchTcpDst(TpPort.tpPort(Integer.parseInt(dstTcpPort)));
193 }
194
195 //if vlan option is not specified using NONE
196 selectorBuilder.matchVlanId(VlanId.vlanId(vlan));
197
Andrea Campanella3970e472018-01-25 16:44:04 +0100198 if (mplsLabel != null) {
199 selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(Integer.parseInt(mplsLabel)));
200 }
201
202 if (mplsBos != null) {
203 selectorBuilder.matchMplsBos(Boolean.valueOf(mplsBos));
204 }
Andrea Campanellae4084402017-12-15 15:27:31 +0100205
Andrea Campanella8292ba62018-01-31 16:43:23 +0100206 if (ipProto != null) {
207 selectorBuilder.matchIPProtocol(Byte.valueOf(ipProto));
208 }
209
210 if (udpSrc != null) {
211 selectorBuilder.matchUdpSrc(TpPort.tpPort(Integer.parseInt(udpSrc)));
212 }
213
214 if (udpDst != null) {
215 selectorBuilder.matchUdpDst(TpPort.tpPort(Integer.parseInt(udpDst)));
216 }
217
218
Andrea Campanellae4084402017-12-15 15:27:31 +0100219 TrafficSelector packet = selectorBuilder.build();
220
221 //Printing the created packet
222 print("Tracing packet: %s", packet.criteria());
223
224 //Build the trace
225 StaticPacketTrace trace = service.trace(packet, cp);
Andrea Campanellae4084402017-12-15 15:27:31 +0100226
Andrea Campanella55c3f422018-02-08 17:10:11 +0100227 print("%s", T3CliUtils.printTrace(trace, verbosity1, verbosity2));
Andrea Campanellae4084402017-12-15 15:27:31 +0100228
Andrea Campanellae4084402017-12-15 15:27:31 +0100229 }
230}