blob: fbf12a3a2cb34b177164d718d475dd4459033053 [file] [log] [blame]
maojianwei42e23442016-02-15 10:40:48 +08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
maojianwei42e23442016-02-15 10:40:48 +08003 *
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.fnl.impl;
17
18import com.google.common.collect.ImmutableSet;
19import org.easymock.EasyMock;
20import org.junit.After;
21import org.junit.Before;
22import org.junit.Test;
23import org.onlab.packet.ChassisId;
24import org.onlab.packet.IPv4;
25import org.onlab.packet.IpPrefix;
26import org.onlab.packet.MacAddress;
27import org.onlab.packet.VlanId;
28import org.onosproject.fnl.intf.NetworkAnomaly;
29import org.onosproject.fnl.intf.NetworkDiagnostic;
30import org.onosproject.net.ConnectPoint;
31import org.onosproject.net.DefaultDevice;
32import org.onosproject.net.DefaultHost;
33import org.onosproject.net.DefaultLink;
34import org.onosproject.net.Device;
35import org.onosproject.net.DeviceId;
36import org.onosproject.net.Host;
37import org.onosproject.net.HostId;
38import org.onosproject.net.HostLocation;
39import org.onosproject.net.Link;
40import org.onosproject.net.device.DeviceService;
41import org.onosproject.net.flow.DefaultFlowEntry;
42import org.onosproject.net.flow.DefaultFlowRule;
43import org.onosproject.net.flow.DefaultTrafficSelector;
44import org.onosproject.net.flow.DefaultTrafficTreatment;
45import org.onosproject.net.flow.FlowEntry;
46import org.onosproject.net.flow.FlowRuleService;
47import org.onosproject.net.flow.TrafficSelector;
48import org.onosproject.net.flow.TrafficTreatment;
49import org.onosproject.net.host.HostService;
50import org.onosproject.net.link.LinkService;
51
52import java.util.ArrayList;
53import java.util.HashMap;
54import java.util.HashSet;
55import java.util.List;
56import java.util.Map;
57import java.util.Set;
58
59import static org.easymock.EasyMock.expect;
60import static org.easymock.EasyMock.replay;
61import static org.hamcrest.MatcherAssert.assertThat;
62import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
63import static org.onlab.packet.EthType.EtherType.IPV4;
64import static org.onlab.packet.TpPort.tpPort;
65import static org.onosproject.net.DefaultAnnotations.EMPTY;
66import static org.onosproject.net.Link.State.ACTIVE;
67import static org.onosproject.net.Link.Type.DIRECT;
68import static org.onosproject.net.PortNumber.portNumber;
69import static org.onosproject.net.flow.FlowEntry.FlowEntryState.ADDED;
70import static org.onosproject.net.provider.ProviderId.NONE;
71
72/**
73 * Unit Tests for DefaultCheckLoop class.
74 */
75public class DefaultCheckLoopTest {
76
77 private NetworkDiagnostic defaultCheckLoop;
78
79 private DeviceService ds;
80 private HostService hs;
81 private FlowRuleService frs;
82 private LinkService ls;
83
84 private List<Device> devices;
85 private List<Host> hosts;
86 private Map<DeviceId, Set<Link>> egressLinks;
87 private Map<DeviceId, List<FlowEntry>> flowEntries;
88
89
90 private static final DeviceId DEVICE_ID_A = DeviceId.deviceId("of:000000000000000A");
91 private static final DeviceId DEVICE_ID_B = DeviceId.deviceId("of:000000000000000B");
92 private static final DeviceId DEVICE_ID_C = DeviceId.deviceId("of:000000000000000C");
93 private static final DeviceId DEVICE_ID_D = DeviceId.deviceId("of:000000000000000D");
94 private static final DeviceId DEVICE_ID_E = DeviceId.deviceId("of:E000000000000000");
95 private static final DeviceId DEVICE_ID_F = DeviceId.deviceId("of:F000000000000000");
96 private static final DeviceId DEVICE_ID_G = DeviceId.deviceId("of:A000000000000000");
97
98 private static final String HOSTID_EXAMPLE = "12:34:56:78:9A:BC/1355";
99 private static final long FLOWRULE_COOKIE_EXAMPLE = 708;
100 private static final int FLOWRULE_PRIORITY_EXAMPLE = 738;
101
102
103 @Before
104 public void setUp() {
105 ds = EasyMock.createMock(DeviceService.class);
106 hs = EasyMock.createMock(HostService.class);
107 frs = EasyMock.createMock(FlowRuleService.class);
108 ls = EasyMock.createMock(LinkService.class);
109
110 defaultCheckLoop = new DefaultCheckLoop(ds, hs, frs, ls);
111 }
112
113 @After
114 public void tearDown() {
115 // do nothing
116 }
117
118 @Test
119 public void testFindLoops() {
120 produceTopoDevices();
121 produceTopoHosts();
122 produceTopoLinks();
123 produceFlowEntries();
124
125 initMock();
126
127 Set<NetworkAnomaly> loops = defaultCheckLoop.findAnomalies();
128 assertThat(loops, hasSize(1));
129 }
130
131 private void initMock() {
132 expect(ds.getDevices()).andReturn(devices).anyTimes();
133 replay(ds);
134
135 expect(hs.getHosts()).andReturn(hosts).anyTimes();
136 replay(hs);
137
138 // --- init flow rule service ---
139
140 expect(frs.getFlowEntries(DEVICE_ID_A))
141 .andReturn(flowEntries.get(DEVICE_ID_A)).anyTimes();
142 expect(frs.getFlowEntries(DEVICE_ID_B))
143 .andReturn(flowEntries.get(DEVICE_ID_B)).anyTimes();
144 expect(frs.getFlowEntries(DEVICE_ID_C))
145 .andReturn(flowEntries.get(DEVICE_ID_C)).anyTimes();
146 expect(frs.getFlowEntries(DEVICE_ID_D))
147 .andReturn(flowEntries.get(DEVICE_ID_D)).anyTimes();
148 expect(frs.getFlowEntries(DEVICE_ID_E))
149 .andReturn(flowEntries.get(DEVICE_ID_E)).anyTimes();
150 expect(frs.getFlowEntries(DEVICE_ID_F))
151 .andReturn(flowEntries.get(DEVICE_ID_F)).anyTimes();
152 expect(frs.getFlowEntries(DEVICE_ID_G))
153 .andReturn(flowEntries.get(DEVICE_ID_G)).anyTimes();
154 replay(frs);
155
156 // --- init link service ---
157
158 expect(ls.getDeviceEgressLinks(DEVICE_ID_A))
159 .andReturn(egressLinks.get(DEVICE_ID_A)).anyTimes();
160 expect(ls.getDeviceEgressLinks(DEVICE_ID_B))
161 .andReturn(egressLinks.get(DEVICE_ID_B)).anyTimes();
162 expect(ls.getDeviceEgressLinks(DEVICE_ID_C))
163 .andReturn(egressLinks.get(DEVICE_ID_C)).anyTimes();
164 expect(ls.getDeviceEgressLinks(DEVICE_ID_D))
165 .andReturn(egressLinks.get(DEVICE_ID_D)).anyTimes();
166 expect(ls.getDeviceEgressLinks(DEVICE_ID_E))
167 .andReturn(egressLinks.get(DEVICE_ID_E)).anyTimes();
168 expect(ls.getDeviceEgressLinks(DEVICE_ID_F))
169 .andReturn(egressLinks.get(DEVICE_ID_F)).anyTimes();
170 expect(ls.getDeviceEgressLinks(DEVICE_ID_G))
171 .andReturn(egressLinks.get(DEVICE_ID_G)).anyTimes();
172 replay(ls);
173 }
174
175 private void produceTopoDevices() {
176 devices = new ArrayList<>();
177 devices.add(produceOneDevice(DEVICE_ID_A));
178 devices.add(produceOneDevice(DEVICE_ID_B));
179 devices.add(produceOneDevice(DEVICE_ID_C));
180 devices.add(produceOneDevice(DEVICE_ID_D));
181 devices.add(produceOneDevice(DEVICE_ID_E));
182 devices.add(produceOneDevice(DEVICE_ID_F));
183 devices.add(produceOneDevice(DEVICE_ID_G));
184 }
185
186 private Device produceOneDevice(DeviceId dpid) {
187 return new DefaultDevice(NONE, dpid,
188 Device.Type.SWITCH, "", "", "", "", new ChassisId(),
189 EMPTY);
190 }
191
192 private void produceTopoHosts() {
193 hosts = new ArrayList<>();
194 hosts.add(produceOneHost(DEVICE_ID_A, 3));
195 hosts.add(produceOneHost(DEVICE_ID_B, 3));
196 hosts.add(produceOneHost(DEVICE_ID_D, 3));
197 hosts.add(produceOneHost(DEVICE_ID_F, 2));
198 hosts.add(produceOneHost(DEVICE_ID_F, 3));
199 hosts.add(produceOneHost(DEVICE_ID_G, 1));
200 hosts.add(produceOneHost(DEVICE_ID_G, 3));
201 }
202
203 private Host produceOneHost(DeviceId dpid, int port) {
204 return new DefaultHost(NONE, HostId.hostId(HOSTID_EXAMPLE),
205 MacAddress.valueOf(0), VlanId.vlanId(),
206 new HostLocation(dpid, portNumber(port), 1),
207 ImmutableSet.of(), EMPTY);
208 }
209
210 private void produceTopoLinks() {
211 egressLinks = new HashMap<>();
212
213 Set<Link> el = new HashSet<>();
214 el.add(produceOneEgressLink(DEVICE_ID_A, 1, DEVICE_ID_B, 1));
215 el.add(produceOneEgressLink(DEVICE_ID_A, 2, DEVICE_ID_D, 2));
216 egressLinks.put(DEVICE_ID_A, el);
217
218 el = new HashSet<>();
219 el.add(produceOneEgressLink(DEVICE_ID_B, 1, DEVICE_ID_A, 1));
220 el.add(produceOneEgressLink(DEVICE_ID_B, 2, DEVICE_ID_C, 2));
221 egressLinks.put(DEVICE_ID_B, el);
222
223 el = new HashSet<>();
224 el.add(produceOneEgressLink(DEVICE_ID_C, 1, DEVICE_ID_D, 1));
225 el.add(produceOneEgressLink(DEVICE_ID_C, 2, DEVICE_ID_B, 2));
226 el.add(produceOneEgressLink(DEVICE_ID_C, 3, DEVICE_ID_E, 3));
227 egressLinks.put(DEVICE_ID_C, el);
228
229 el = new HashSet<>();
230 el.add(produceOneEgressLink(DEVICE_ID_D, 1, DEVICE_ID_C, 1));
231 el.add(produceOneEgressLink(DEVICE_ID_D, 2, DEVICE_ID_A, 2));
232 egressLinks.put(DEVICE_ID_D, el);
233
234 el = new HashSet<>();
235 el.add(produceOneEgressLink(DEVICE_ID_E, 1, DEVICE_ID_F, 1));
236 el.add(produceOneEgressLink(DEVICE_ID_E, 2, DEVICE_ID_G, 2));
237 el.add(produceOneEgressLink(DEVICE_ID_E, 3, DEVICE_ID_C, 3));
238 egressLinks.put(DEVICE_ID_E, el);
239
240 el = new HashSet<>();
241 el.add(produceOneEgressLink(DEVICE_ID_F, 1, DEVICE_ID_E, 1));
242 egressLinks.put(DEVICE_ID_F, el);
243
244 el = new HashSet<>();
245 el.add(produceOneEgressLink(DEVICE_ID_G, 2, DEVICE_ID_E, 2));
246 egressLinks.put(DEVICE_ID_G, el);
247 }
248
249 private Link produceOneEgressLink(DeviceId srcId, int srcPort, DeviceId dstId, int dstPort) {
250 return DefaultLink.builder()
251 .providerId(NONE)
252 .src(new ConnectPoint(srcId, portNumber(srcPort)))
253 .dst(new ConnectPoint(dstId, portNumber(dstPort)))
254 .type(DIRECT)
255 .state(ACTIVE)
256 .build();
257 }
258
259 private void produceFlowEntries() {
260 flowEntries = new HashMap<>();
261
262 List<FlowEntry> fe = new ArrayList<>();
263 fe.add(produceOneFlowEntry(DEVICE_ID_A, 2));
264 flowEntries.put(DEVICE_ID_A, fe);
265
266 fe = new ArrayList<>();
267 fe.add(produceOneFlowEntry(DEVICE_ID_D, 1));
268 flowEntries.put(DEVICE_ID_D, fe);
269
270 fe = new ArrayList<>();
271 fe.add(produceOneFlowEntry(DEVICE_ID_C, 2));
272 flowEntries.put(DEVICE_ID_C, fe);
273
274 fe = new ArrayList<>();
275 fe.add(produceOneFlowEntry(DEVICE_ID_B, 1));
276 flowEntries.put(DEVICE_ID_B, fe);
277
278 flowEntries.put(DEVICE_ID_E, new ArrayList<>());
279 flowEntries.put(DEVICE_ID_F, new ArrayList<>());
280 flowEntries.put(DEVICE_ID_G, new ArrayList<>());
281
282 }
283
284 private FlowEntry produceOneFlowEntry(DeviceId dpid, int outPort) {
285
286 TrafficSelector.Builder sb = DefaultTrafficSelector.builder()
287 .matchEthType(IPV4.ethType().toShort())
288 .matchIPDst(IpPrefix.valueOf("10.0.0.0/8"))
289 .matchIPProtocol(IPv4.PROTOCOL_TCP)
290 .matchTcpDst(tpPort(22));
291
292 TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder()
293 .setOutput(portNumber(outPort));
294
295 return new DefaultFlowEntry(DefaultFlowRule.builder()
296 .withPriority(FLOWRULE_PRIORITY_EXAMPLE).forDevice(dpid).forTable(0)
297 .withCookie(FLOWRULE_COOKIE_EXAMPLE)
298 .withSelector(sb.build()).withTreatment(tb.build())
299 .makePermanent().build(), ADDED);
300 }
301}