blob: 0e510660fc7ff5fe58ebc18fed4da08971c76aa8 [file] [log] [blame]
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.t3.cli;
import org.apache.commons.lang.StringUtils;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Completion;
import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import org.onlab.packet.EthType;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.VlanId;
import org.onlab.util.Generator;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cli.PlaceholderCompleter;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.t3.api.StaticPacketTrace;
import org.onosproject.t3.api.TroubleshootService;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* Starts a Static Packet Trace for all the multicast routes in the system and prints the result.
*/
@Service
@Command(scope = "onos", name = "t3-troubleshoot-mcast",
description = "Traces all the mcast routes present in the system")
public class TroubleshootMcastCommand extends AbstractShellCommand {
@Option(name = "-v", aliases = "--verbose", description = "Outputs trace for each mcast route")
@Completion(PlaceholderCompleter.class)
private boolean verbosity1 = false;
@Option(name = "-vv", aliases = "--veryverbose", description = "Outputs middle level details of every trace")
@Completion(PlaceholderCompleter.class)
private boolean verbosity2 = false;
@Option(name = "-vvv", aliases = "--veryveryverbose", description = "Outputs complete details of every trace")
@Completion(PlaceholderCompleter.class)
private boolean verbosity3 = false;
@Option(name = "-vid", aliases = "--vlanId", description = "Vlan of incoming packet", valueToShowInHelp = "None")
@Completion(PlaceholderCompleter.class)
String vlan = "None";
@Override
protected void doExecute() {
TroubleshootService service = get(TroubleshootService.class);
if (!service.checkNibValidity()) {
// if the NIB is found invalid, fill it with the current network states so that this command can proceed
print(T3CliUtils.NIB_AUTOFILLED);
TroubleshootLoadSnapshotCommand cmd = new TroubleshootLoadSnapshotCommand();
cmd.doExecute();
if (!service.checkNibValidity()) {
// if the NIB is still invalid even after auto-filled snapshots, stop and warn
print(T3CliUtils.NIB_TERMINATE);
return;
}
} else {
print(service.printNibSummary());
}
print("Tracing all Multicast routes in the System");
//Create the generator for the list of traces.
VlanId vlanId = vlan == null || vlan.isEmpty() ? VlanId.NONE : VlanId.vlanId(vlan);
Generator<Set<StaticPacketTrace>> generator = service.traceMcast(vlanId);
int totalTraces = 0;
List<StaticPacketTrace> failedTraces = new ArrayList<>();
StaticPacketTrace previousTrace = null;
while (generator.iterator().hasNext()) {
totalTraces++;
//Print also Route if possible or packet
Set<StaticPacketTrace> traces = generator.iterator().next();
if (!verbosity1 && !verbosity2 && !verbosity3) {
for (StaticPacketTrace trace : traces) {
previousTrace = printTrace(previousTrace, trace);
if (!trace.isSuccess()) {
print("Failure: %s", trace.resultMessage());
failedTraces.add(trace);
} else {
print(trace.resultMessage());
}
}
} else {
traces.forEach(trace -> {
print("Tracing packet: %s", trace.getInitialPacket());
print("%s", T3CliUtils.printTrace(trace, verbosity2, verbosity3));
print("%s", StringUtils.rightPad("", 125, '-'));
});
}
}
if (!verbosity1 && !verbosity2 && !verbosity3) {
if (failedTraces.size() != 0) {
print("%s", StringUtils.rightPad("", 125, '-'));
print("Failed Traces: %s", failedTraces.size());
}
previousTrace = null;
for (StaticPacketTrace trace : failedTraces) {
previousTrace = printTrace(previousTrace, trace);
print("Failure: %s", trace.resultMessage());
}
print("%s", StringUtils.rightPad("", 125, '-'));
print("Summary");
print("Total Traces %s, errors %s", totalTraces, failedTraces.size());
print("%s", StringUtils.rightPad("", 125, '-'));
}
}
private StaticPacketTrace printTrace(StaticPacketTrace previousTrace, StaticPacketTrace trace) {
if (previousTrace == null || !previousTrace.equals(trace)) {
print("%s", StringUtils.rightPad("", 125, '-'));
previousTrace = trace;
ConnectPoint initialConnectPoint = trace.getInitialConnectPoint();
TrafficSelector initialPacket = trace.getInitialPacket();
boolean isIPv4 = ((EthTypeCriterion) initialPacket.getCriterion(Criterion.Type.ETH_TYPE))
.ethType().equals(EthType.EtherType.IPV4.ethType()
);
IpPrefix group = ((IPCriterion) (isIPv4 ? trace.getInitialPacket()
.getCriterion(Criterion.Type.IPV4_DST) : trace.getInitialPacket()
.getCriterion(Criterion.Type.IPV6_DST))).ip();
print("Source %s, group %s", initialConnectPoint, group);
}
StringBuilder destinations = new StringBuilder();
if (trace.getCompletePaths().size() > 1) {
destinations.append("Sinks: ");
} else {
destinations.append("Sink: ");
}
trace.getCompletePaths().forEach(path -> {
destinations.append(path.get(path.size() - 1) + " ");
});
print("%s", destinations.toString());
return previousTrace;
}
}