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);
+    }
+}