[CORD-2755] PingAll scenario for Ipv4 and Ipv6 hosts
Change-Id: I8d57568a94580807e62fb5953a881850a73f43ed
diff --git a/apps/t3/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java b/apps/t3/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java
index e56035d..542dcfd 100644
--- a/apps/t3/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java
+++ b/apps/t3/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java
@@ -17,8 +17,10 @@
package org.onosproject.t3.api;
import com.google.common.collect.ImmutableList;
+import org.apache.commons.lang3.tuple.Pair;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.TrafficSelector;
@@ -26,6 +28,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
/**
* Encapsulates the result of tracing a packet (traffic selector) through
@@ -39,6 +42,7 @@
private Map<DeviceId, List<GroupsInDevice>> outputsForDevice;
private Map<DeviceId, List<FlowEntry>> flowsForDevice;
private StringBuilder resultMessage;
+ private Pair<Host, Host> hosts;
/**
* Builds the trace with a given packet and a connect point.
@@ -53,6 +57,24 @@
outputsForDevice = new HashMap<>();
flowsForDevice = new HashMap<>();
resultMessage = new StringBuilder();
+ hosts = null;
+ }
+
+ /**
+ * Builds the trace with a given packet and a connect point.
+ *
+ * @param packet the packet to trace
+ * @param in the initial connect point
+ * @param hosts pair of source and destination hosts
+ */
+ public StaticPacketTrace(TrafficSelector packet, ConnectPoint in, Pair<Host, Host> hosts) {
+ this.inPacket = packet;
+ this.in = in;
+ completePaths = new ArrayList<>();
+ outputsForDevice = new HashMap<>();
+ flowsForDevice = new HashMap<>();
+ resultMessage = new StringBuilder();
+ this.hosts = hosts;
}
/**
@@ -155,6 +177,24 @@
return flowsForDevice.getOrDefault(deviceId, ImmutableList.of());
}
+ /**
+ * Return, if present, the two hosts at the endpoints of this trace.
+ *
+ * @return pair of source and destination hosts
+ */
+ public Optional<Pair<Host, Host>> getEndpointHosts() {
+ return Optional.ofNullable(hosts);
+ }
+
+ /**
+ * Sets the two hosts at the endpoints of this trace.
+ *
+ * @param endpointHosts pair of source and destination hosts
+ */
+ public void addEndpointHosts(Pair<Host, Host> endpointHosts) {
+ hosts = endpointHosts;
+ }
+
@Override
public String toString() {
return "StaticPacketTrace{" +
diff --git a/apps/t3/src/main/java/org/onosproject/t3/api/TroubleshootService.java b/apps/t3/src/main/java/org/onosproject/t3/api/TroubleshootService.java
index 01bae57..028df64 100644
--- a/apps/t3/src/main/java/org/onosproject/t3/api/TroubleshootService.java
+++ b/apps/t3/src/main/java/org/onosproject/t3/api/TroubleshootService.java
@@ -21,6 +21,8 @@
import org.onosproject.net.HostId;
import org.onosproject.net.flow.TrafficSelector;
+import java.util.List;
+
/**
* API for troubleshooting services, providing static analysis of installed
* flows and groups.
@@ -28,6 +30,14 @@
public interface TroubleshootService {
/**
+ * Requests a static trace be performed between all hosts in the network, given a type of traffic.
+ *
+ * @param type the etherType of the traffic we want to trace.
+ * @return a trace result
+ */
+ List<StaticPacketTrace> pingAll(EthType.EtherType type);
+
+ /**
* Requests a static trace be performed between the two hosts in the network, given a type of traffic.
*
* @param sourceHost source host
diff --git a/apps/t3/src/main/java/org/onosproject/t3/cli/TroubleshootPingAllTraceCommand.java b/apps/t3/src/main/java/org/onosproject/t3/cli/TroubleshootPingAllTraceCommand.java
new file mode 100644
index 0000000..8cecc8d
--- /dev/null
+++ b/apps/t3/src/main/java/org/onosproject/t3/cli/TroubleshootPingAllTraceCommand.java
@@ -0,0 +1,110 @@
+/*
+ * 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.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.Host;
+import org.onosproject.t3.api.StaticPacketTrace;
+import org.onosproject.t3.api.TroubleshootService;
+
+import java.util.List;
+
+import static org.onlab.packet.EthType.EtherType;
+
+/**
+ * Starts a Static Packet Trace for a given input and prints the result.
+ */
+@Command(scope = "onos", name = "t3-troubleshoot-pingall",
+ description = "Traces a ping between all hosts in the system of a given ETH type")
+public class TroubleshootPingAllTraceCommand extends AbstractShellCommand {
+
+ private static final String FMT_SHORT =
+ "id=%s, mac=%s, locations=%s, vlan=%s, ip(s)=%s";
+
+ @Option(name = "-et", aliases = "--ethType", description = "ETH Type", valueToShowInHelp = "ipv4")
+ String ethType = "ipv4";
+
+ @Option(name = "-v", aliases = "--verbose", description = "Outputs trace for each host to host combination")
+ private boolean verbosity1 = false;
+
+ @Override
+ protected void execute() {
+ TroubleshootService service = get(TroubleshootService.class);
+
+ EtherType type = EtherType.valueOf(ethType.toUpperCase());
+
+ print("Tracing between all %s hosts", ethType);
+
+ if (!type.equals(EtherType.IPV4) && !type.equals(EtherType.IPV6)) {
+ print("Command only support IPv4 or IPv6");
+ } else {
+ print("--------------------------------------------------------------------------");
+ //Obtain the list of traces
+ List<StaticPacketTrace> traces = service.pingAll(type);
+
+ if (traces.size() == 0) {
+ print("No traces were obtained, please check system configuration");
+ }
+
+ traces.forEach(trace -> {
+ if (trace.getInitialPacket() != null) {
+ if (verbosity1) {
+ printVerbose(trace);
+ } else {
+ printResultOnly(trace);
+ }
+ } else {
+ print("Error in obtaining trace: %s", trace.resultMessage());
+ }
+ print("--------------------------------------------------------------------------");
+ });
+ }
+
+
+ }
+
+ private void printResultOnly(StaticPacketTrace trace) {
+ if (trace.getEndpointHosts().isPresent()) {
+ Host source = trace.getEndpointHosts().get().getLeft();
+ Host destination = trace.getEndpointHosts().get().getRight();
+ print("Source %s --> Destination %s", source.id(), destination.id());
+ print("%s", trace.resultMessage());
+ } else {
+ print("Can't gather host information from trace");
+ print("%s", trace.resultMessage());
+ }
+ }
+
+ private void printVerbose(StaticPacketTrace trace) {
+ if (trace.getEndpointHosts().isPresent()) {
+ Host source = trace.getEndpointHosts().get().getLeft();
+ print("Source host %s", printHost(source));
+ Host destination = trace.getEndpointHosts().get().getRight();
+ print("Destination host %s", printHost(destination));
+ }
+ print("%s", trace.getInitialPacket());
+ print("%s", T3CliUtils.printTrace(trace, false, false));
+ }
+
+ private String printHost(Host host) {
+ return String.format(FMT_SHORT, host.id(), host.mac(),
+ host.locations(),
+ host.vlan(), host.ipAddresses());
+ }
+}
diff --git a/apps/t3/src/main/java/org/onosproject/t3/cli/TroubleshootSimpleTraceCommand.java b/apps/t3/src/main/java/org/onosproject/t3/cli/TroubleshootSimpleTraceCommand.java
index 997ef42a..3674e32 100644
--- a/apps/t3/src/main/java/org/onosproject/t3/cli/TroubleshootSimpleTraceCommand.java
+++ b/apps/t3/src/main/java/org/onosproject/t3/cli/TroubleshootSimpleTraceCommand.java
@@ -59,7 +59,7 @@
EtherType type = EtherType.valueOf(ethType.toUpperCase());
- //Printing the created packet
+ //Printing the traced hosts
print("Tracing between: %s and %s", srcHost, dstHost);
//Build the trace
diff --git a/apps/t3/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java b/apps/t3/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java
index 2c41382..4087ec9 100644
--- a/apps/t3/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java
+++ b/apps/t3/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java
@@ -19,6 +19,7 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
@@ -131,12 +132,29 @@
protected EdgePortService edgePortService;
@Override
+ public List<StaticPacketTrace> pingAll(EtherType type) {
+ ImmutableList.Builder<StaticPacketTrace> tracesBuilder = ImmutableList.builder();
+ hostService.getHosts().forEach(host -> {
+ List<IpAddress> ipAddresses = getIpAddresses(host, type, false);
+ if (ipAddresses.size() > 0) {
+ hostService.getHosts().forEach(hostToPing -> {
+ List<IpAddress> ipAddressesToPing = getIpAddresses(hostToPing, type, false);
+ if (ipAddressesToPing.size() > 0 && !host.equals(hostToPing)) {
+ tracesBuilder.add(trace(host.id(), hostToPing.id(), type));
+ }
+ });
+ }
+ });
+ return tracesBuilder.build();
+ }
+
+ @Override
public StaticPacketTrace trace(HostId sourceHost, HostId destinationHost, EtherType etherType) {
Host source = hostService.getHost(sourceHost);
Host destination = hostService.getHost(destinationHost);
- //Temporary trace to fail in case we don't have neough information or what is provided is incoherent
- StaticPacketTrace failTrace = new StaticPacketTrace(null, null);
+ //Temporary trace to fail in case we don't have enough information or what is provided is incoherent
+ StaticPacketTrace failTrace = new StaticPacketTrace(null, null, Pair.of(source, destination));
if (source == null) {
failTrace.addResultMessage("Source Host " + sourceHost + " does not exist");
@@ -160,7 +178,9 @@
// we are under same leaf so it's L2 Unicast.
if (areBridged(source, destination)) {
selectorBuilder.matchEthDst(destination.mac());
- return trace(selectorBuilder.build(), source.location());
+ StaticPacketTrace trace = trace(selectorBuilder.build(), source.location());
+ trace.addEndpointHosts(Pair.of(source, destination));
+ return trace;
}
//handle the IPs for src and dst in case of L3
@@ -191,8 +211,9 @@
failTrace.addResultMessage("Can't get " + source.location().deviceId() +
" router MAC from segment routing config can't perform L3 tracing.");
}
-
- return trace(selectorBuilder.build(), source.location());
+ StaticPacketTrace trace = trace(selectorBuilder.build(), source.location());
+ trace.addEndpointHosts(Pair.of(source, destination));
+ return trace;
} catch (ConfigException e) {
failTrace.addResultMessage("Can't get config " + e.getMessage());
@@ -212,14 +233,7 @@
*/
private boolean matchIP(Host host, StaticPacketTrace failTrace, Builder selectorBuilder,
EtherType etherType, boolean src) {
- List<IpAddress> ips = host.ipAddresses().stream().filter(ipAddress -> {
- if (etherType.equals(EtherType.IPV4)) {
- return ipAddress.isIp4() && !ipAddress.isLinkLocal();
- } else if (etherType.equals(EtherType.IPV6)) {
- return ipAddress.isIp6() && !ipAddress.isLinkLocal();
- }
- return false;
- }).collect(Collectors.toList());
+ List<IpAddress> ips = getIpAddresses(host, etherType, true);
if (ips.size() > 0) {
if (etherType.equals(EtherType.IPV4)) {
@@ -242,6 +256,21 @@
return true;
}
+ private List<IpAddress> getIpAddresses(Host host, EtherType etherType, boolean checklocal) {
+ return host.ipAddresses().stream().filter(ipAddress -> {
+ boolean correctIp = false;
+ if (etherType.equals(EtherType.IPV4)) {
+ correctIp = ipAddress.isIp4();
+ } else if (etherType.equals(EtherType.IPV6)) {
+ correctIp = ipAddress.isIp6();
+ }
+ if (checklocal) {
+ correctIp = correctIp && !ipAddress.isLinkLocal();
+ }
+ return correctIp;
+ }).collect(Collectors.toList());
+ }
+
/**
* Checks that two hosts are bridged (L2Unicast).
*
diff --git a/apps/t3/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/t3/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 7444994..8fe5597 100644
--- a/apps/t3/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/apps/t3/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -28,6 +28,12 @@
<entry key="-et" value-ref="ethTypeCompleter"/>
</optional-completers>
</command>
+ <command>
+ <action class="org.onosproject.t3.cli.TroubleshootPingAllTraceCommand"/>
+ <optional-completers>
+ <entry key="-et" value-ref="ethTypeCompleter"/>
+ </optional-completers>
+ </command>
</command-bundle>
<bean id="hostIdCompleter" class="org.onosproject.cli.net.HostIdCompleter"/>