blob: 93e843aa000b20d1d0f3d6946cf3be0cecda9a01 [file] [log] [blame]
Andrea Campanella41de8062018-02-28 16:43:16 +01001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
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
19import org.apache.commons.lang.StringUtils;
Ray Milkey86ad7bb2018-09-27 12:32:28 -070020import org.apache.karaf.shell.api.action.Command;
Ray Milkeyebe0ec62018-10-10 14:32:38 -070021import org.apache.karaf.shell.api.action.Completion;
Ray Milkey86ad7bb2018-09-27 12:32:28 -070022import org.apache.karaf.shell.api.action.Option;
Ray Milkey7a2dee52018-09-28 10:58:28 -070023import org.apache.karaf.shell.api.action.lifecycle.Service;
Andrea Campanella41de8062018-02-28 16:43:16 +010024import org.onlab.packet.IpAddress;
25import org.onosproject.cli.AbstractShellCommand;
Ray Milkeyebe0ec62018-10-10 14:32:38 -070026import org.onosproject.cli.net.EthTypeCompleter;
Andrea Campanella41de8062018-02-28 16:43:16 +010027import org.onosproject.net.Host;
28import org.onosproject.net.flow.criteria.Criterion;
29import org.onosproject.net.flow.criteria.IPCriterion;
30import org.onosproject.t3.api.StaticPacketTrace;
31import org.onosproject.t3.api.TroubleshootService;
32import org.onosproject.t3.impl.Generator;
33
Andrea Campanellac8e6a502018-03-12 19:25:44 -070034import java.util.ArrayList;
35import java.util.List;
Andrea Campanella41de8062018-02-28 16:43:16 +010036import java.util.Set;
37
38import static java.lang.Thread.sleep;
39import static org.onlab.packet.EthType.EtherType;
40
41/**
42 * Starts a Static Packet Trace for a given input and prints the result.
43 */
Ray Milkey7a2dee52018-09-28 10:58:28 -070044@Service
Andrea Campanella41de8062018-02-28 16:43:16 +010045@Command(scope = "onos", name = "t3-troubleshoot-pingall",
46 description = "Traces a ping between all hosts in the system of a given ETH type")
47public class TroubleshootPingAllCommand extends AbstractShellCommand {
48
49 private static final String FMT_SHORT =
50 "id=%s, mac=%s, locations=%s, vlan=%s, ip(s)=%s";
51
52 @Option(name = "-et", aliases = "--ethType", description = "ETH Type", valueToShowInHelp = "ipv4")
Ray Milkeyebe0ec62018-10-10 14:32:38 -070053 @Completion(EthTypeCompleter.class)
Andrea Campanella41de8062018-02-28 16:43:16 +010054 String ethType = "ipv4";
55
56 @Option(name = "-v", aliases = "--verbose", description = "Outputs trace for each host to host combination")
57 private boolean verbosity1 = false;
58
59 @Option(name = "-vv", aliases = "--veryverbose", description = "Outputs details of every trace")
60 private boolean verbosity2 = false;
61
62 @Option(name = "-d", aliases = "--delay", description = "delay between host to host trace display")
63 private long delay = 0;
64
65 @Override
Ray Milkey86ad7bb2018-09-27 12:32:28 -070066 protected void doExecute() {
Andrea Campanella41de8062018-02-28 16:43:16 +010067 TroubleshootService service = get(TroubleshootService.class);
68
69 EtherType type = EtherType.valueOf(ethType.toUpperCase());
70
71 print("Tracing between all %s hosts", ethType);
72
73 if (!type.equals(EtherType.IPV4) && !type.equals(EtherType.IPV6)) {
74 print("Command only support IPv4 or IPv6");
75 } else {
76 //Create the generator for the list of traces.
77 Generator<Set<StaticPacketTrace>> generator = service.pingAllGenerator(type);
78 Host previousHost = null;
Andrea Campanellac8e6a502018-03-12 19:25:44 -070079 int totalTraces = 0;
80 List<StaticPacketTrace> failedTraces = new ArrayList<>();
81 boolean ipv4 = type.equals(EtherType.IPV4);
Andrea Campanella41de8062018-02-28 16:43:16 +010082 while (generator.iterator().hasNext()) {
83 Set<StaticPacketTrace> traces = generator.iterator().next();
Andrea Campanellac8e6a502018-03-12 19:25:44 -070084 totalTraces++;
Andrea Campanella41de8062018-02-28 16:43:16 +010085 for (StaticPacketTrace trace : traces) {
Andrea Campanella41de8062018-02-28 16:43:16 +010086 //no verbosity is mininet style output
87 if (!verbosity1 && !verbosity2) {
88 if (trace.getEndpointHosts().isPresent()) {
89 Host src = trace.getEndpointHosts().get().getLeft();
90 if (previousHost == null || !previousHost.equals(src)) {
91 print("%s", StringUtils.rightPad("", 125, '-'));
Andrea Campanellac8e6a502018-03-12 19:25:44 -070092 previousHost = printSrc(trace, ipv4, src);
Andrea Campanella41de8062018-02-28 16:43:16 +010093 }
Andrea Campanellac8e6a502018-03-12 19:25:44 -070094 String host = getDstString(trace, ipv4, src);
95 if (!trace.isSuccess()) {
96 host = host + " " + trace.resultMessage();
97 failedTraces.add(trace);
98 }
99 print("%s", host);
Andrea Campanella41de8062018-02-28 16:43:16 +0100100 }
101 } else {
102 print("%s", StringUtils.leftPad("", 125, '-'));
103
104 if (trace.getInitialPacket() != null) {
105 if (verbosity1) {
106 printResultOnly(trace, ipv4);
107 } else if (verbosity2) {
108 printVerbose(trace);
109 }
110 } else {
111 if (trace.getEndpointHosts().isPresent()) {
112 Host source = trace.getEndpointHosts().get().getLeft();
113 Host destination = trace.getEndpointHosts().get().getRight();
114 print("Source %s --> Destination %s", source.id(), destination.id());
115 }
116 print("Error in obtaining trace: %s", trace.resultMessage());
117 }
118 }
119 }
120 try {
121 sleep(delay);
122 } catch (InterruptedException e) {
123 log.debug("interrupted while sleep");
124 }
125 }
126 print("%s", StringUtils.rightPad("", 125, '-'));
Andrea Campanellac8e6a502018-03-12 19:25:44 -0700127 print("Failed Traces: %s", failedTraces.size());
128 print("%s", StringUtils.rightPad("", 125, '-'));
129 failedTraces.forEach(t -> {
130 if (t.getEndpointHosts().isPresent()) {
131 printSrc(t, ipv4, t.getEndpointHosts().get().getLeft());
132 String dst = getDstString(t, ipv4, t.getEndpointHosts().get().getRight());
133 dst = dst + " " + t.resultMessage();
134 print("%s", dst);
135 print("%s", StringUtils.rightPad("", 125, '-'));
136 }
137 });
138 print("Summary");
139 print("Total Traces %s, errors %s", totalTraces, failedTraces.size());
Andrea Campanella41de8062018-02-28 16:43:16 +0100140 }
141 }
142
Andrea Campanellac8e6a502018-03-12 19:25:44 -0700143 private String getDstString(StaticPacketTrace trace, boolean ipv4, Host src) {
144 String host;
145 IpAddress ipAddress = getIpAddress(trace, ipv4, src, false);
146 if (ipAddress == null) {
147 host = String.format(" %s %s", trace.getEndpointHosts().get().getRight().id(),
148 trace.isSuccess());
149 } else {
150 host = String.format(" %s (%s) %s",
151 trace.getEndpointHosts().get().getRight().id(), ipAddress,
152 trace.isSuccess());
153 }
154 return host;
155 }
156
157 private Host printSrc(StaticPacketTrace trace, boolean ipv4, Host src) {
158 Host previousHost;
159 IpAddress ipAddress = getIpAddress(trace, ipv4, src, true);
160 if (ipAddress == null) {
161 print("%s", src.id() + " -->");
162 } else {
163 print("%s (%s) -->", src.id(), ipAddress);
164 }
165 previousHost = src;
166 return previousHost;
167 }
168
Andrea Campanella41de8062018-02-28 16:43:16 +0100169 private IpAddress getIpAddress(StaticPacketTrace trace, boolean ipv4, Host host, boolean src) {
170 IpAddress ipAddress;
171 if (ipv4) {
172 Criterion.Type type = src ? Criterion.Type.IPV4_SRC : Criterion.Type.IPV4_DST;
pier4c2715e2019-04-11 18:20:01 +0200173 if (trace.getInitialPacket() != null && trace.getInitialPacket().getCriterion(type) != null) {
Andrea Campanella41de8062018-02-28 16:43:16 +0100174 ipAddress = ((IPCriterion) trace.getInitialPacket()
175 .getCriterion(type)).ip().address();
176 } else {
177 ipAddress = host.ipAddresses().stream().filter(IpAddress::isIp4)
Seyeon Jeonga7a6f4a2020-02-19 17:51:05 -0800178 .findAny().orElse(null);
Andrea Campanella41de8062018-02-28 16:43:16 +0100179 }
180 } else {
181 Criterion.Type type = src ? Criterion.Type.IPV6_SRC : Criterion.Type.IPV6_DST;
pier4c2715e2019-04-11 18:20:01 +0200182 if (trace.getInitialPacket() != null && trace.getInitialPacket().getCriterion(type) != null) {
Andrea Campanella41de8062018-02-28 16:43:16 +0100183 ipAddress = ((IPCriterion) trace.getInitialPacket()
184 .getCriterion(type)).ip().address();
185 } else {
186 ipAddress = host.ipAddresses().stream().filter(IpAddress::isIp6)
Seyeon Jeonga7a6f4a2020-02-19 17:51:05 -0800187 .findAny().orElse(null);
Andrea Campanella41de8062018-02-28 16:43:16 +0100188 }
189 }
190 return ipAddress;
191 }
192
193 private void printResultOnly(StaticPacketTrace trace, boolean ipv4) {
194 if (trace.getEndpointHosts().isPresent()) {
195 Host source = trace.getEndpointHosts().get().getLeft();
196 Host destination = trace.getEndpointHosts().get().getRight();
197 IpAddress srcIP;
198 IpAddress dstIP;
199 if (ipv4 && trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_SRC) != null) {
200 srcIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_SRC)).ip().address();
201 dstIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_DST)).ip().address();
202 print("Source %s (%s) --> Destination %s (%s)", source.id(), srcIP, destination.id(), dstIP);
203 } else if (trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_SRC) != null) {
204 srcIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_SRC)).ip().address();
205 dstIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_DST)).ip().address();
206 print("Source %s (%s) --> Destination %s (%s)", source.id(), srcIP, destination.id(), dstIP);
207 } else {
208 print("Source %s --> Destination %s", source.id(), destination.id());
209 }
210 print("%s", trace.resultMessage());
211 } else {
212 print("Can't gather host information from trace");
213 print("%s", trace.resultMessage());
214 }
215 }
216
217 private void printVerbose(StaticPacketTrace trace) {
218 if (trace.getEndpointHosts().isPresent()) {
219 Host source = trace.getEndpointHosts().get().getLeft();
220 print("Source host %s", printHost(source));
221 Host destination = trace.getEndpointHosts().get().getRight();
222 print("Destination host %s", printHost(destination));
223 }
224 print("%s", trace.getInitialPacket());
225 print("%s", T3CliUtils.printTrace(trace, false, false));
226 }
227
228 private String printHost(Host host) {
229 return String.format(FMT_SHORT, host.id(), host.mac(),
230 host.locations(),
231 host.vlan(), host.ipAddresses());
232 }
233}