blob: a8f652415f64a928e25883f324f64053501f6759 [file] [log] [blame]
Andrea Campanellae4084402017-12-15 15:27:31 +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 */
16package org.onosproject.t3.impl;
17
18import com.google.common.collect.ImmutableList;
19import com.google.common.collect.ImmutableSet;
20import org.junit.Before;
21import org.junit.Test;
Andrea Campanella17d45192018-01-18 17:11:42 +010022import org.onlab.packet.ChassisId;
Andrea Campanellae4084402017-12-15 15:27:31 +010023import org.onlab.packet.EthType;
24import org.onlab.packet.IpAddress;
25import org.onlab.packet.MacAddress;
26import org.onlab.packet.VlanId;
27import org.onosproject.net.ConnectPoint;
Andrea Campanella17d45192018-01-18 17:11:42 +010028import org.onosproject.net.DefaultAnnotations;
29import org.onosproject.net.DefaultDevice;
Andrea Campanellae4084402017-12-15 15:27:31 +010030import org.onosproject.net.DefaultLink;
Andrea Campanella17d45192018-01-18 17:11:42 +010031import org.onosproject.net.Device;
Andrea Campanellae4084402017-12-15 15:27:31 +010032import org.onosproject.net.DeviceId;
33import org.onosproject.net.Host;
34import org.onosproject.net.Link;
Andrea Campanella17d45192018-01-18 17:11:42 +010035import org.onosproject.net.device.DeviceServiceAdapter;
Andrea Campanellae4084402017-12-15 15:27:31 +010036import org.onosproject.net.driver.DefaultDriver;
37import org.onosproject.net.driver.Driver;
38import org.onosproject.net.driver.DriverServiceAdapter;
39import org.onosproject.net.flow.FlowEntry;
40import org.onosproject.net.flow.FlowRuleServiceAdapter;
41import org.onosproject.net.flow.TrafficSelector;
42import org.onosproject.net.flow.criteria.Criterion;
43import org.onosproject.net.flow.criteria.EthTypeCriterion;
44import org.onosproject.net.flow.criteria.VlanIdCriterion;
45import org.onosproject.net.group.Group;
46import org.onosproject.net.group.GroupServiceAdapter;
47import org.onosproject.net.host.HostServiceAdapter;
48import org.onosproject.net.link.LinkServiceAdapter;
49import org.onosproject.net.provider.ProviderId;
50import org.onosproject.t3.api.StaticPacketTrace;
51import org.slf4j.Logger;
52
53import java.util.HashMap;
54import java.util.Set;
55
56import static org.junit.Assert.assertEquals;
57import static org.junit.Assert.assertNotNull;
58import static org.junit.Assert.assertNull;
59import static org.junit.Assert.assertTrue;
Andrea Campanella17d45192018-01-18 17:11:42 +010060import static org.onosproject.net.Device.Type.SWITCH;
Andrea Campanellae4084402017-12-15 15:27:31 +010061import static org.onosproject.t3.impl.T3TestObjects.*;
62import static org.slf4j.LoggerFactory.getLogger;
63
64/**
65 * Test Class for Troubleshoot Manager.
66 */
67public class TroubleshootManagerTest {
68
69 private static final Logger log = getLogger(TroubleshootManager.class);
70
71 private TroubleshootManager mngr;
72
73 @Before
74 public void setUp() throws Exception {
75 mngr = new TroubleshootManager();
76 mngr.flowRuleService = new TestFlowRuleService();
77 mngr.hostService = new TestHostService();
78 mngr.linkService = new TestLinkService();
79 mngr.driverService = new TestDriverService();
80 mngr.groupService = new TestGroupService();
Andrea Campanella17d45192018-01-18 17:11:42 +010081 mngr.deviceService = new TestDeviceService();
Andrea Campanellae4084402017-12-15 15:27:31 +010082
83 assertNotNull("Manager should not be null", mngr);
84
85 assertNotNull("Flow rule Service should not be null", mngr.flowRuleService);
86 assertNotNull("Host Service should not be null", mngr.hostService);
87 assertNotNull("Group Service should not be null", mngr.groupService);
88 assertNotNull("Driver Service should not be null", mngr.driverService);
89 assertNotNull("Link Service should not be null", mngr.linkService);
Andrea Campanella17d45192018-01-18 17:11:42 +010090 assertNotNull("Device Service should not be null", mngr.deviceService);
91 }
92
93 /**
94 * Tests failure on non existent device.
95 */
96 @Test(expected = NullPointerException.class)
97 public void nonExistentDevice() {
98 StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint("nonexistent" + "/1"));
99 }
100
101 /**
102 * Tests failure on offline device.
103 */
104 @Test
105 public void offlineDevice() {
106 StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint(OFFLINE_DEVICE + "/1"));
107 assertNotNull("Trace should not be null", traceFail);
108 assertNull("Trace should have 0 output", traceFail.getGroupOuputs(SINGLE_FLOW_DEVICE));
Andrea Campanella7d3cf652018-01-22 15:10:30 +0100109 }
110
111 /**
112 * Tests failure on same output.
113 */
114 @Test
115 public void sameOutput() {
116 StaticPacketTrace traceFail = mngr.trace(PACKET_OK, SAME_OUTPUT_FLOW_CP);
117 assertNotNull("Trace should not be null", traceFail);
118 assertTrue("Trace should be unsuccessful",
119 traceFail.resultMessage().contains("is same as initial input"));
Andrea Campanella17d45192018-01-18 17:11:42 +0100120 log.info("trace {}", traceFail.resultMessage());
Andrea Campanellae4084402017-12-15 15:27:31 +0100121 }
122
Andrea Campanella7d3cf652018-01-22 15:10:30 +0100123
Andrea Campanellae4084402017-12-15 15:27:31 +0100124 /**
Andrea Campanella4401bd72018-01-18 16:54:34 +0100125 * Tests failure on device with no flows.
Andrea Campanellae4084402017-12-15 15:27:31 +0100126 */
127 @Test
128 public void noFlows() {
129 StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint("test/1"));
130 assertNotNull("Trace should not be null", traceFail);
131 assertNull("Trace should have 0 output", traceFail.getGroupOuputs(SINGLE_FLOW_DEVICE));
132 log.info("trace {}", traceFail.resultMessage());
133 }
134
135 /**
136 * Test a single flow rule that has output port in it.
137 */
138 @Test
139 public void testSingleFlowRule() {
140
141 testSuccess(PACKET_OK, SINGLE_FLOW_IN_CP, SINGLE_FLOW_DEVICE, SINGLE_FLOW_OUT_CP, 1);
142
143 testFaliure(PACKET_FAIL, SINGLE_FLOW_IN_CP, SINGLE_FLOW_DEVICE);
144 }
145
146 /**
147 * Tests two flow rule the last one of which has output port in it.
148 */
149 @Test
150 public void testDualFlowRule() {
151
152 //Test Success
153
Andrea Campanella4401bd72018-01-18 16:54:34 +0100154 StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, DUAL_FLOW_IN_CP, DUAL_FLOW_DEVICE,
155 DUAL_FLOW_OUT_CP, 1);
Andrea Campanellae4084402017-12-15 15:27:31 +0100156
157 //Testing Vlan
158 Criterion criterion = traceSuccess.getGroupOuputs(DUAL_FLOW_DEVICE).get(0).
159 getFinalPacket().getCriterion(Criterion.Type.VLAN_VID);
160 assertNotNull("Packet Should have Vlan", criterion);
161
162 VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) criterion;
163
164 assertEquals("Vlan should be 100", VlanId.vlanId((short) 100), vlanIdCriterion.vlanId());
165
166 //Test Faliure
167 testFaliure(PACKET_FAIL, DUAL_FLOW_IN_CP, DUAL_FLOW_DEVICE);
168
169 }
170
171 /**
172 * Test a single flow rule that points to a group with output port in it.
173 */
174 @Test
175 public void flowAndGroup() throws Exception {
176
Andrea Campanella4401bd72018-01-18 16:54:34 +0100177 StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, GROUP_FLOW_IN_CP, GROUP_FLOW_DEVICE,
178 GROUP_FLOW_OUT_CP, 1);
Andrea Campanellae4084402017-12-15 15:27:31 +0100179
180 assertTrue("Wrong Output Group", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
181 .get(0).getGroups().contains(GROUP));
Andrea Campanella3970e472018-01-25 16:44:04 +0100182 assertEquals("Packet should not have MPLS Label", EthType.EtherType.IPV4.ethType(),
183 ((EthTypeCriterion) traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
184 .get(0).getFinalPacket().getCriterion(Criterion.Type.ETH_TYPE)).ethType());
185 assertNull("Packet should not have MPLS Label", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
186 .get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_LABEL));
187 assertNull("Packet should not have MPLS Label", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
188 .get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_BOS));
Andrea Campanellae4084402017-12-15 15:27:31 +0100189
190 }
191
192 /**
193 * Test path through a 3 device topology.
194 */
195 @Test
196 public void singlePathTopology() throws Exception {
197
198 StaticPacketTrace traceSuccess = testSuccess(PACKET_OK_TOPO, TOPO_FLOW_1_IN_CP,
199 TOPO_FLOW_3_DEVICE, TOPO_FLOW_3_OUT_CP, 1);
200
201 assertTrue("Incorrect path",
202 traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_2_IN_CP));
203 assertTrue("Incorrect path",
204 traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_2_OUT_CP));
205 assertTrue("Incorrect path",
206 traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_3_IN_CP));
207
208 }
209
210 /**
211 * Test path through a 4 device topology with first device that has groups with multiple output buckets.
212 */
213 @Test
214 public void testGroupTopo() throws Exception {
215
216 StaticPacketTrace traceSuccess = testSuccess(PACKET_OK_TOPO, TOPO_FLOW_IN_CP,
217 TOPO_FLOW_3_DEVICE, TOPO_FLOW_3_OUT_CP, 2);
218
219 assertTrue("Incorrect groups",
220 traceSuccess.getGroupOuputs(TOPO_GROUP_FLOW_DEVICE).get(0).getGroups().contains(TOPO_GROUP));
221 assertTrue("Incorrect bucket",
222 traceSuccess.getGroupOuputs(TOPO_GROUP_FLOW_DEVICE).get(1).getGroups().contains(TOPO_GROUP));
223 }
224
225 /**
226 * Test HW support in a single device with 2 flow rules to check hit of static HW rules.
227 */
228 @Test
229 public void hardwareTest() throws Exception {
230
231 StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, HARDWARE_DEVICE_IN_CP,
232 HARDWARE_DEVICE, HARDWARE_DEVICE_OUT_CP, 1);
233
234 assertEquals("wrong ETH type", EthType.EtherType.IPV4.ethType(),
235 ((EthTypeCriterion) traceSuccess.getGroupOuputs(HARDWARE_DEVICE).get(0).getFinalPacket()
236 .getCriterion(Criterion.Type.ETH_TYPE)).ethType());
237
238 }
239
240 private StaticPacketTrace testSuccess(TrafficSelector packet, ConnectPoint in, DeviceId deviceId, ConnectPoint out,
241 int paths) {
242 StaticPacketTrace traceSuccess = mngr.trace(packet, in);
243
244 log.info("trace {}", traceSuccess);
245
246 log.info("trace {}", traceSuccess.resultMessage());
247
248 assertNotNull("trace should not be null", traceSuccess);
249 assertEquals("Trace should have " + paths + " output", paths, traceSuccess.getGroupOuputs(deviceId).size());
250 assertEquals("Trace should only have " + paths + "output", paths, traceSuccess.getCompletePaths().size());
251 assertTrue("Trace should be successful",
252 traceSuccess.resultMessage().contains("Reached required destination Host"));
253 assertEquals("Incorrect Output CP", out,
254 traceSuccess.getGroupOuputs(deviceId).get(0).getOutput());
255
256 return traceSuccess;
257 }
258
259 private void testFaliure(TrafficSelector packet, ConnectPoint in, DeviceId deviceId) {
260 StaticPacketTrace traceFail = mngr.trace(packet, in);
261
262 log.info("trace {}", traceFail.resultMessage());
263
264 assertNotNull("Trace should not be null", traceFail);
265 assertNull("Trace should have 0 output", traceFail.getGroupOuputs(deviceId));
266 }
267
268 private class TestFlowRuleService extends FlowRuleServiceAdapter {
269 @Override
270 public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
271 if (deviceId.equals(SINGLE_FLOW_DEVICE)) {
272 return ImmutableList.of(SINGLE_FLOW_ENTRY);
273 } else if (deviceId.equals(DUAL_FLOW_DEVICE)) {
274 return ImmutableList.of(FIRST_FLOW_ENTRY, SECOND_FLOW_ENTRY);
275 } else if (deviceId.equals(GROUP_FLOW_DEVICE)) {
276 return ImmutableList.of(GROUP_FLOW_ENTRY);
277 } else if (deviceId.equals(TOPO_FLOW_DEVICE) ||
278 deviceId.equals(TOPO_FLOW_2_DEVICE) ||
279 deviceId.equals(TOPO_FLOW_3_DEVICE) ||
280 deviceId.equals(TOPO_FLOW_4_DEVICE)) {
281 return ImmutableList.of(TOPO_SINGLE_FLOW_ENTRY, TOPO_SECOND_INPUT_FLOW_ENTRY);
282 } else if (deviceId.equals(TOPO_GROUP_FLOW_DEVICE)) {
283 return ImmutableList.of(TOPO_GROUP_FLOW_ENTRY);
Andrea Campanella4401bd72018-01-18 16:54:34 +0100284 } else if (deviceId.equals(HARDWARE_DEVICE)) {
Andrea Campanellae4084402017-12-15 15:27:31 +0100285 return ImmutableList.of(HARDWARE_ETH_FLOW_ENTRY, HARDWARE_FLOW_ENTRY);
Andrea Campanella7d3cf652018-01-22 15:10:30 +0100286 } else if (deviceId.equals(SAME_OUTPUT_FLOW_DEVICE)) {
287 return ImmutableList.of(SAME_OUTPUT_FLOW_ENTRY);
Andrea Campanellae4084402017-12-15 15:27:31 +0100288 }
289 return ImmutableList.of();
290 }
291 }
292
293 private class TestDriverService extends DriverServiceAdapter {
294 @Override
295 public Driver getDriver(DeviceId deviceId) {
Andrea Campanella4401bd72018-01-18 16:54:34 +0100296 if (deviceId.equals(HARDWARE_DEVICE)) {
Andrea Campanellae4084402017-12-15 15:27:31 +0100297 return new DefaultDriver("ofdpa", ImmutableList.of(),
298 "test", "test", "test", new HashMap<>(), new HashMap<>());
299 }
300 return new DefaultDriver("NotHWDriver", ImmutableList.of(),
301 "test", "test", "test", new HashMap<>(), new HashMap<>());
302 }
303 }
304
305 private class TestGroupService extends GroupServiceAdapter {
306 @Override
307 public Iterable<Group> getGroups(DeviceId deviceId) {
308 if (deviceId.equals(GROUP_FLOW_DEVICE)) {
309 return ImmutableList.of(GROUP);
310 } else if (deviceId.equals(TOPO_GROUP_FLOW_DEVICE)) {
311 return ImmutableList.of(TOPO_GROUP);
312 }
313 return ImmutableList.of();
314 }
315 }
316
317 private class TestHostService extends HostServiceAdapter {
318 @Override
319 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
320 if (connectPoint.equals(TOPO_FLOW_3_OUT_CP)) {
321 return ImmutableSet.of(H2);
322 }
323 return ImmutableSet.of(H1);
324 }
325
326 @Override
327 public Set<Host> getHostsByMac(MacAddress mac) {
328 if (mac.equals(H1.mac())) {
329 return ImmutableSet.of(H1);
330 } else if (mac.equals(H2.mac())) {
331 return ImmutableSet.of(H2);
332 }
333 return ImmutableSet.of();
334 }
335
336 @Override
337 public Set<Host> getHostsByIp(IpAddress ip) {
338 if ((H1.ipAddresses().contains(ip))) {
339 return ImmutableSet.of(H1);
340 } else if ((H2.ipAddresses().contains(ip))) {
341 return ImmutableSet.of(H2);
342 }
343 return ImmutableSet.of();
344 }
345 }
346
347 private class TestLinkService extends LinkServiceAdapter {
348 @Override
349 public Set<Link> getEgressLinks(ConnectPoint connectPoint) {
350 if (connectPoint.equals(TOPO_FLOW_1_OUT_CP)
351 || connectPoint.equals(TOPO_FLOW_OUT_CP_1)) {
352 return ImmutableSet.of(DefaultLink.builder()
353 .providerId(ProviderId.NONE)
354 .type(Link.Type.DIRECT)
355 .src(connectPoint)
356 .dst(TOPO_FLOW_2_IN_CP)
357 .build());
358 } else if (connectPoint.equals(TOPO_FLOW_2_OUT_CP)) {
359 return ImmutableSet.of(DefaultLink.builder()
360 .providerId(ProviderId.NONE)
361 .type(Link.Type.DIRECT)
362 .src(TOPO_FLOW_2_OUT_CP)
363 .dst(TOPO_FLOW_3_IN_CP)
364 .build());
365 } else if (connectPoint.equals(TOPO_FLOW_OUT_CP_2)) {
366 return ImmutableSet.of(DefaultLink.builder()
367 .providerId(ProviderId.NONE)
368 .type(Link.Type.DIRECT)
369 .src(TOPO_FLOW_OUT_CP_2)
370 .dst(TOPO_FLOW_4_IN_CP)
371 .build());
372 } else if (connectPoint.equals(TOPO_FLOW_4_OUT_CP)) {
373 return ImmutableSet.of(DefaultLink.builder()
374 .providerId(ProviderId.NONE)
375 .type(Link.Type.DIRECT)
376 .src(TOPO_FLOW_4_OUT_CP)
377 .dst(TOPO_FLOW_3_IN_2_CP)
378 .build());
379 }
380 return ImmutableSet.of();
381 }
382 }
Andrea Campanella17d45192018-01-18 17:11:42 +0100383
384 private class TestDeviceService extends DeviceServiceAdapter {
385 @Override
386 public Device getDevice(DeviceId deviceId) {
387 if (deviceId.equals(DeviceId.deviceId("nonexistent"))) {
388 return null;
389 }
390 return new DefaultDevice(ProviderId.NONE, DeviceId.deviceId("test"), SWITCH,
391 "test", "test", "test", "test", new ChassisId(),
392 DefaultAnnotations.builder().set("foo", "bar").build());
393 }
394
395 @Override
396 public boolean isAvailable(DeviceId deviceId) {
397 if (deviceId.equals(OFFLINE_DEVICE)) {
398 return false;
399 }
400 return true;
401 }
402 }
Andrea Campanellae4084402017-12-15 15:27:31 +0100403}