ONOS Network Troubleshooting System
Newest Commit changes:
1. Add unit tests.
2. Fix review comments.
3. Add support to BUCK.
Could you please make a Code Review, we wish to hear anything from you :)
Thank you very much!
----------------------------------------------------
ONOS Network Troubleshooting System
Modularity design. In present, include these tow module:
1. Routing Loop Detection
Welcome your contribution for more modules in the future...
Beijing University of Posts and Telecommunications
new: withdraw blackhole tracing for redesign;
fix obvious checkstyle problem.
Change-Id: Id6d3aa0bc00c8da8ac046e6903f17cfdf954d919
diff --git a/apps/network-troubleshoot/core/src/test/java/org/onosproject/fnl/impl/DefaultCheckLoopTest.java b/apps/network-troubleshoot/core/src/test/java/org/onosproject/fnl/impl/DefaultCheckLoopTest.java
new file mode 100644
index 0000000..3c72a09
--- /dev/null
+++ b/apps/network-troubleshoot/core/src/test/java/org/onosproject/fnl/impl/DefaultCheckLoopTest.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2015-present Open Networking Laboratory
+ *
+ * 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.fnl.impl;
+
+import com.google.common.collect.ImmutableSet;
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.ChassisId;
+import org.onlab.packet.IPv4;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.fnl.intf.NetworkAnomaly;
+import org.onosproject.fnl.intf.NetworkDiagnostic;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DefaultHost;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.Link;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.DefaultFlowEntry;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.link.LinkService;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
+import static org.onlab.packet.EthType.EtherType.IPV4;
+import static org.onlab.packet.TpPort.tpPort;
+import static org.onosproject.net.DefaultAnnotations.EMPTY;
+import static org.onosproject.net.Link.State.ACTIVE;
+import static org.onosproject.net.Link.Type.DIRECT;
+import static org.onosproject.net.PortNumber.portNumber;
+import static org.onosproject.net.flow.FlowEntry.FlowEntryState.ADDED;
+import static org.onosproject.net.provider.ProviderId.NONE;
+
+/**
+ * Unit Tests for DefaultCheckLoop class.
+ */
+public class DefaultCheckLoopTest {
+
+ private NetworkDiagnostic defaultCheckLoop;
+
+ private DeviceService ds;
+ private HostService hs;
+ private FlowRuleService frs;
+ private LinkService ls;
+
+ private List<Device> devices;
+ private List<Host> hosts;
+ private Map<DeviceId, Set<Link>> egressLinks;
+ private Map<DeviceId, List<FlowEntry>> flowEntries;
+
+
+ private static final DeviceId DEVICE_ID_A = DeviceId.deviceId("of:000000000000000A");
+ private static final DeviceId DEVICE_ID_B = DeviceId.deviceId("of:000000000000000B");
+ private static final DeviceId DEVICE_ID_C = DeviceId.deviceId("of:000000000000000C");
+ private static final DeviceId DEVICE_ID_D = DeviceId.deviceId("of:000000000000000D");
+ private static final DeviceId DEVICE_ID_E = DeviceId.deviceId("of:E000000000000000");
+ private static final DeviceId DEVICE_ID_F = DeviceId.deviceId("of:F000000000000000");
+ private static final DeviceId DEVICE_ID_G = DeviceId.deviceId("of:A000000000000000");
+
+ private static final String HOSTID_EXAMPLE = "12:34:56:78:9A:BC/1355";
+ private static final long FLOWRULE_COOKIE_EXAMPLE = 708;
+ private static final int FLOWRULE_PRIORITY_EXAMPLE = 738;
+
+
+ @Before
+ public void setUp() {
+ ds = EasyMock.createMock(DeviceService.class);
+ hs = EasyMock.createMock(HostService.class);
+ frs = EasyMock.createMock(FlowRuleService.class);
+ ls = EasyMock.createMock(LinkService.class);
+
+ defaultCheckLoop = new DefaultCheckLoop(ds, hs, frs, ls);
+ }
+
+ @After
+ public void tearDown() {
+ // do nothing
+ }
+
+ @Test
+ public void testFindLoops() {
+ produceTopoDevices();
+ produceTopoHosts();
+ produceTopoLinks();
+ produceFlowEntries();
+
+ initMock();
+
+ Set<NetworkAnomaly> loops = defaultCheckLoop.findAnomalies();
+ assertThat(loops, hasSize(1));
+ }
+
+ private void initMock() {
+ expect(ds.getDevices()).andReturn(devices).anyTimes();
+ replay(ds);
+
+ expect(hs.getHosts()).andReturn(hosts).anyTimes();
+ replay(hs);
+
+ // --- init flow rule service ---
+
+ expect(frs.getFlowEntries(DEVICE_ID_A))
+ .andReturn(flowEntries.get(DEVICE_ID_A)).anyTimes();
+ expect(frs.getFlowEntries(DEVICE_ID_B))
+ .andReturn(flowEntries.get(DEVICE_ID_B)).anyTimes();
+ expect(frs.getFlowEntries(DEVICE_ID_C))
+ .andReturn(flowEntries.get(DEVICE_ID_C)).anyTimes();
+ expect(frs.getFlowEntries(DEVICE_ID_D))
+ .andReturn(flowEntries.get(DEVICE_ID_D)).anyTimes();
+ expect(frs.getFlowEntries(DEVICE_ID_E))
+ .andReturn(flowEntries.get(DEVICE_ID_E)).anyTimes();
+ expect(frs.getFlowEntries(DEVICE_ID_F))
+ .andReturn(flowEntries.get(DEVICE_ID_F)).anyTimes();
+ expect(frs.getFlowEntries(DEVICE_ID_G))
+ .andReturn(flowEntries.get(DEVICE_ID_G)).anyTimes();
+ replay(frs);
+
+ // --- init link service ---
+
+ expect(ls.getDeviceEgressLinks(DEVICE_ID_A))
+ .andReturn(egressLinks.get(DEVICE_ID_A)).anyTimes();
+ expect(ls.getDeviceEgressLinks(DEVICE_ID_B))
+ .andReturn(egressLinks.get(DEVICE_ID_B)).anyTimes();
+ expect(ls.getDeviceEgressLinks(DEVICE_ID_C))
+ .andReturn(egressLinks.get(DEVICE_ID_C)).anyTimes();
+ expect(ls.getDeviceEgressLinks(DEVICE_ID_D))
+ .andReturn(egressLinks.get(DEVICE_ID_D)).anyTimes();
+ expect(ls.getDeviceEgressLinks(DEVICE_ID_E))
+ .andReturn(egressLinks.get(DEVICE_ID_E)).anyTimes();
+ expect(ls.getDeviceEgressLinks(DEVICE_ID_F))
+ .andReturn(egressLinks.get(DEVICE_ID_F)).anyTimes();
+ expect(ls.getDeviceEgressLinks(DEVICE_ID_G))
+ .andReturn(egressLinks.get(DEVICE_ID_G)).anyTimes();
+ replay(ls);
+ }
+
+ private void produceTopoDevices() {
+ devices = new ArrayList<>();
+ devices.add(produceOneDevice(DEVICE_ID_A));
+ devices.add(produceOneDevice(DEVICE_ID_B));
+ devices.add(produceOneDevice(DEVICE_ID_C));
+ devices.add(produceOneDevice(DEVICE_ID_D));
+ devices.add(produceOneDevice(DEVICE_ID_E));
+ devices.add(produceOneDevice(DEVICE_ID_F));
+ devices.add(produceOneDevice(DEVICE_ID_G));
+ }
+
+ private Device produceOneDevice(DeviceId dpid) {
+ return new DefaultDevice(NONE, dpid,
+ Device.Type.SWITCH, "", "", "", "", new ChassisId(),
+ EMPTY);
+ }
+
+ private void produceTopoHosts() {
+ hosts = new ArrayList<>();
+ hosts.add(produceOneHost(DEVICE_ID_A, 3));
+ hosts.add(produceOneHost(DEVICE_ID_B, 3));
+ hosts.add(produceOneHost(DEVICE_ID_D, 3));
+ hosts.add(produceOneHost(DEVICE_ID_F, 2));
+ hosts.add(produceOneHost(DEVICE_ID_F, 3));
+ hosts.add(produceOneHost(DEVICE_ID_G, 1));
+ hosts.add(produceOneHost(DEVICE_ID_G, 3));
+ }
+
+ private Host produceOneHost(DeviceId dpid, int port) {
+ return new DefaultHost(NONE, HostId.hostId(HOSTID_EXAMPLE),
+ MacAddress.valueOf(0), VlanId.vlanId(),
+ new HostLocation(dpid, portNumber(port), 1),
+ ImmutableSet.of(), EMPTY);
+ }
+
+ private void produceTopoLinks() {
+ egressLinks = new HashMap<>();
+
+ Set<Link> el = new HashSet<>();
+ el.add(produceOneEgressLink(DEVICE_ID_A, 1, DEVICE_ID_B, 1));
+ el.add(produceOneEgressLink(DEVICE_ID_A, 2, DEVICE_ID_D, 2));
+ egressLinks.put(DEVICE_ID_A, el);
+
+ el = new HashSet<>();
+ el.add(produceOneEgressLink(DEVICE_ID_B, 1, DEVICE_ID_A, 1));
+ el.add(produceOneEgressLink(DEVICE_ID_B, 2, DEVICE_ID_C, 2));
+ egressLinks.put(DEVICE_ID_B, el);
+
+ el = new HashSet<>();
+ el.add(produceOneEgressLink(DEVICE_ID_C, 1, DEVICE_ID_D, 1));
+ el.add(produceOneEgressLink(DEVICE_ID_C, 2, DEVICE_ID_B, 2));
+ el.add(produceOneEgressLink(DEVICE_ID_C, 3, DEVICE_ID_E, 3));
+ egressLinks.put(DEVICE_ID_C, el);
+
+ el = new HashSet<>();
+ el.add(produceOneEgressLink(DEVICE_ID_D, 1, DEVICE_ID_C, 1));
+ el.add(produceOneEgressLink(DEVICE_ID_D, 2, DEVICE_ID_A, 2));
+ egressLinks.put(DEVICE_ID_D, el);
+
+ el = new HashSet<>();
+ el.add(produceOneEgressLink(DEVICE_ID_E, 1, DEVICE_ID_F, 1));
+ el.add(produceOneEgressLink(DEVICE_ID_E, 2, DEVICE_ID_G, 2));
+ el.add(produceOneEgressLink(DEVICE_ID_E, 3, DEVICE_ID_C, 3));
+ egressLinks.put(DEVICE_ID_E, el);
+
+ el = new HashSet<>();
+ el.add(produceOneEgressLink(DEVICE_ID_F, 1, DEVICE_ID_E, 1));
+ egressLinks.put(DEVICE_ID_F, el);
+
+ el = new HashSet<>();
+ el.add(produceOneEgressLink(DEVICE_ID_G, 2, DEVICE_ID_E, 2));
+ egressLinks.put(DEVICE_ID_G, el);
+ }
+
+ private Link produceOneEgressLink(DeviceId srcId, int srcPort, DeviceId dstId, int dstPort) {
+ return DefaultLink.builder()
+ .providerId(NONE)
+ .src(new ConnectPoint(srcId, portNumber(srcPort)))
+ .dst(new ConnectPoint(dstId, portNumber(dstPort)))
+ .type(DIRECT)
+ .state(ACTIVE)
+ .build();
+ }
+
+ private void produceFlowEntries() {
+ flowEntries = new HashMap<>();
+
+ List<FlowEntry> fe = new ArrayList<>();
+ fe.add(produceOneFlowEntry(DEVICE_ID_A, 2));
+ flowEntries.put(DEVICE_ID_A, fe);
+
+ fe = new ArrayList<>();
+ fe.add(produceOneFlowEntry(DEVICE_ID_D, 1));
+ flowEntries.put(DEVICE_ID_D, fe);
+
+ fe = new ArrayList<>();
+ fe.add(produceOneFlowEntry(DEVICE_ID_C, 2));
+ flowEntries.put(DEVICE_ID_C, fe);
+
+ fe = new ArrayList<>();
+ fe.add(produceOneFlowEntry(DEVICE_ID_B, 1));
+ flowEntries.put(DEVICE_ID_B, fe);
+
+ flowEntries.put(DEVICE_ID_E, new ArrayList<>());
+ flowEntries.put(DEVICE_ID_F, new ArrayList<>());
+ flowEntries.put(DEVICE_ID_G, new ArrayList<>());
+
+ }
+
+ private FlowEntry produceOneFlowEntry(DeviceId dpid, int outPort) {
+
+ TrafficSelector.Builder sb = DefaultTrafficSelector.builder()
+ .matchEthType(IPV4.ethType().toShort())
+ .matchIPDst(IpPrefix.valueOf("10.0.0.0/8"))
+ .matchIPProtocol(IPv4.PROTOCOL_TCP)
+ .matchTcpDst(tpPort(22));
+
+ TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder()
+ .setOutput(portNumber(outPort));
+
+ return new DefaultFlowEntry(DefaultFlowRule.builder()
+ .withPriority(FLOWRULE_PRIORITY_EXAMPLE).forDevice(dpid).forTable(0)
+ .withCookie(FLOWRULE_COOKIE_EXAMPLE)
+ .withSelector(sb.build()).withTreatment(tb.build())
+ .makePermanent().build(), ADDED);
+ }
+}