blob: e33924dcc637efd92a6471e8136a122ff4c7280e [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
alshabib64231d82014-09-25 18:25:31 -070019package org.onlab.onos.provider.of.link.impl;
20
21import static org.junit.Assert.assertEquals;
22import static org.junit.Assert.assertFalse;
23import static org.junit.Assert.assertNotNull;
24import static org.junit.Assert.assertNull;
25import static org.junit.Assert.assertTrue;
26
27import java.util.ArrayList;
28import java.util.Collections;
29import java.util.HashMap;
30import java.util.List;
31import java.util.Map;
32import java.util.Set;
33
34import org.junit.After;
35import org.junit.Before;
36import org.junit.Test;
37import org.onlab.onos.net.ConnectPoint;
38import org.onlab.onos.net.DeviceId;
39import org.onlab.onos.net.link.LinkDescription;
40import org.onlab.onos.net.link.LinkProvider;
41import org.onlab.onos.net.link.LinkProviderRegistry;
42import org.onlab.onos.net.link.LinkProviderService;
43import org.onlab.onos.net.provider.AbstractProviderService;
44import org.onlab.onos.net.provider.ProviderId;
45import org.onlab.onos.openflow.controller.Dpid;
46import org.onlab.onos.openflow.controller.OpenFlowPacketContext;
47import org.onlab.onos.openflow.controller.OpenFlowSwitch;
48import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
49import org.onlab.onos.openflow.controller.OpenflowControllerAdapter;
50import org.onlab.onos.openflow.controller.PacketListener;
51import org.onlab.onos.openflow.controller.RoleState;
52import org.onlab.packet.Ethernet;
53import org.onlab.packet.ONLabLddp;
54import org.projectfloodlight.openflow.protocol.OFFactory;
55import org.projectfloodlight.openflow.protocol.OFMessage;
56import org.projectfloodlight.openflow.protocol.OFPortConfig;
57import org.projectfloodlight.openflow.protocol.OFPortDesc;
58import org.projectfloodlight.openflow.protocol.OFPortReason;
59import org.projectfloodlight.openflow.protocol.OFPortStatus;
60import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
61import org.projectfloodlight.openflow.types.OFPort;
62
63import com.google.common.collect.Lists;
64import com.google.common.collect.Maps;
65
66public class OpenFlowLinkProviderTest {
67
68
69 private static final DeviceId DID1 = DeviceId.deviceId("of:0000000000000001");
70 private static final DeviceId DID2 = DeviceId.deviceId("of:0000000000000002");
71
72 private static final Dpid DPID2 = Dpid.dpid(DID2.uri());
73 private static final Dpid DPID1 = Dpid.dpid(DID1.uri());
74
75 private static final OFPortDesc PD1 = portDesc(1, true);
76 private static final OFPortDesc PD2 = portDesc(2, true);
77 private static final OFPortDesc PD3 = portDesc(1, true);
78 private static final OFPortDesc PD4 = portDesc(2, true);
79
80 private static final List<OFPortDesc> PLIST1 = Lists.newArrayList(PD1, PD2);
81 private static final List<OFPortDesc> PLIST2 = Lists.newArrayList(PD3, PD4);
82
83 private static final TestOpenFlowSwitch SW1 = new TestOpenFlowSwitch(DPID1, PLIST1);
84 private static final TestOpenFlowSwitch SW2 = new TestOpenFlowSwitch(DPID2, PLIST2);
85
86 private final OpenFlowLinkProvider provider = new OpenFlowLinkProvider();
87 private final TestLinkRegistry linkService = new TestLinkRegistry();
88 private final TestController controller = new TestController();
89
90 private TestLinkProviderService providerService;
91 private TestPacketContext pktCtx;
92
93 @Before
94 public void setUp() {
95 pktCtx = new TestPacketContext(DPID2);
96 provider.providerRegistry = linkService;
97 controller.switchMap.put(DPID1, SW1);
98 controller.switchMap.put(DPID2, SW2);
99 provider.controller = controller;
100 provider.activate();
101 }
102
103 @Test
104 public void basics() {
105 assertNotNull("registration expected", providerService);
106 assertEquals("incorrect provider", provider, providerService.provider());
107 }
108
109 @Test
110 public void switchAdd() {
111 controller.listener.switchAdded(DPID1);
112 assertFalse("Device not added", provider.discoverers.isEmpty());
113 }
114
115 @Test
116 public void switchRemove() {
117 controller.listener.switchAdded(DPID1);
118 controller.listener.switchRemoved(DPID1);
119
120 assertTrue("Discoverer is not gone", provider.discoverers.isEmpty());
121 assertTrue("Device is not gone.", vanishedDpid(DPID1));
122 }
123
124 @Test
125 public void portUp() {
126 controller.listener.switchAdded(DPID1);
127 controller.listener.portChanged(DPID1, portStatus(true, 3));
128
129 assertTrue("Port not added to discoverer",
130 provider.discoverers.get(DPID1).ports.containsKey(3));
131 }
132
133 @Test
134 public void portDown() {
135 controller.listener.switchAdded(DPID1);
136 controller.listener.portChanged(DPID1, portStatus(false, 1));
137
138 assertFalse("Port added to discoverer",
139 provider.discoverers.get(DPID1).ports.containsKey(1));
140 assertTrue("Port is not gone.", vanishedPort((long) 1));
141 }
142
143 @Test
144 public void portUnknown() {
145 controller.listener.switchAdded(DPID1);
146 controller.listener.portChanged(DPID2, portStatus(false, 1));
147
148 assertNull("DPID exists",
149 provider.discoverers.get(DPID2));
150 }
151
152 @Test
153 public void unknownPktCtx() {
154 controller.pktListener.handlePacket(pktCtx);
155
156 assertFalse("Context should still be free", pktCtx.isHandled());
157 }
158
159 @Test
160 public void knownPktCtx() {
161 controller.listener.switchAdded(DPID1);
162 controller.listener.switchAdded(DPID2);
163
164 controller.pktListener.handlePacket(pktCtx);
165
166 assertTrue("Link not detected", detectedLink(DPID1, DPID2));
167
168 }
169
170
171 @After
172 public void tearDown() {
173 provider.deactivate();
174 provider.providerRegistry = null;
175 provider.controller = null;
176 }
177
178 private OFPortStatus portStatus(boolean up, int port) {
179 OFPortDesc desc = portDesc(port, up);
180 OFPortStatus status = OFFactoryVer10.INSTANCE.buildPortStatus()
181 .setDesc(desc)
182 .setReason(up ? OFPortReason.ADD : OFPortReason.DELETE).build();
183 return status;
184
185 }
186
187 private static OFPortDesc portDesc(int port, boolean up) {
188 OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
189 builder.setPortNo(OFPort.of(port));
190 if (!up) {
191 builder.setConfig(Collections.singleton(OFPortConfig.PORT_DOWN));
192 }
193 return builder.build();
194 }
195
196 private boolean vanishedDpid(Dpid... dpids) {
197 for (int i = 0; i < dpids.length; i++) {
198 if (!providerService.vanishedDpid.contains(dpids[i])) {
199 return false;
200 }
201 }
202 return true;
203 }
204
205 private boolean vanishedPort(Long... ports) {
206 for (int i = 0; i < ports.length; i++) {
207 if (!providerService.vanishedPort.contains(ports[i])) {
208 return false;
209 }
210 }
211 return true;
212 }
213
214 private boolean detectedLink(Dpid src, Dpid dst) {
215 for (Dpid key : providerService.discoveredLinks.keySet()) {
216 if (key.equals(src)) {
217 return providerService.discoveredLinks.get(src).equals(dst);
218 }
219 }
220 return false;
221 }
222
223
224 private class TestLinkRegistry implements LinkProviderRegistry {
225
226 @Override
227 public LinkProviderService register(LinkProvider provider) {
228 providerService = new TestLinkProviderService(provider);
229 return providerService;
230 }
231
232 @Override
233 public void unregister(LinkProvider provider) {
234 }
235
236 @Override
237 public Set<ProviderId> getProviders() {
238 return null;
239 }
240
241 }
242
243 private class TestLinkProviderService
244 extends AbstractProviderService<LinkProvider>
245 implements LinkProviderService {
246
247 List<Dpid> vanishedDpid = Lists.newLinkedList();
248 List<Long> vanishedPort = Lists.newLinkedList();
249 Map<Dpid, Dpid> discoveredLinks = Maps.newHashMap();
250
251 protected TestLinkProviderService(LinkProvider provider) {
252 super(provider);
253 }
254
255 @Override
256 public void linkDetected(LinkDescription linkDescription) {
257 Dpid sDpid = Dpid.dpid(linkDescription.src().deviceId().uri());
258 Dpid dDpid = Dpid.dpid(linkDescription.dst().deviceId().uri());
259 discoveredLinks.put(sDpid, dDpid);
260 }
261
262 @Override
263 public void linkVanished(LinkDescription linkDescription) {
264 // TODO Auto-generated method stub
265
266 }
267
268 @Override
269 public void linksVanished(ConnectPoint connectPoint) {
270 vanishedPort.add(connectPoint.port().toLong());
271
272 }
273
274 @Override
275 public void linksVanished(DeviceId deviceId) {
276 vanishedDpid.add(Dpid.dpid(deviceId.uri()));
277 }
278
279
280 }
281
282 private class TestController extends OpenflowControllerAdapter {
283 PacketListener pktListener;
284 OpenFlowSwitchListener listener;
285 Map<Dpid, OpenFlowSwitch> switchMap = new HashMap<Dpid, OpenFlowSwitch>();
286
287 @Override
288 public void addPacketListener(int priority, PacketListener listener) {
289 pktListener = listener;
290 }
291
292 @Override
293 public void removePacketListener(PacketListener listener) {
294 pktListener = null;
295 }
296
297 @Override
298 public void addListener(OpenFlowSwitchListener listener) {
299 this.listener = listener;
300 }
301
302 @Override
303 public void removeListener(OpenFlowSwitchListener listener) {
304 this.listener = null;
305 }
306
307 @Override
308 public void processPacket(Dpid dpid, OFMessage msg) {
309 OpenFlowPacketContext ctx = new TestPacketContext(dpid);
310 pktListener.handlePacket(ctx);
311 }
312
313 @Override
314 public Iterable<OpenFlowSwitch> getSwitches() {
315 return Collections.emptyList();
316 }
317
318 @Override
319 public OpenFlowSwitch getSwitch(Dpid dpid) {
320 return switchMap.get(dpid);
321 }
322 }
323
324
325
326 private class TestPacketContext implements OpenFlowPacketContext {
327
328 protected Dpid swid;
329 protected boolean blocked = false;
330
331 public TestPacketContext(Dpid dpid) {
332 swid = dpid;
333 }
334
335 @Override
336 public boolean block() {
337 blocked = true;
338 return blocked;
339 }
340
341 @Override
342 public void send() {
343 }
344
345 @Override
346 public void build(OFPort outPort) {
347 }
348
349 @Override
350 public void build(Ethernet ethFrame, OFPort outPort) {
351 }
352
353 @Override
354 public Ethernet parsed() {
355 return null;
356 }
357
358 @Override
359 public byte[] unparsed() {
360 ONLabLddp lldp = new ONLabLddp();
361 lldp.setSwitch(DPID1.value());
362
363 Ethernet ethPacket = new Ethernet();
364 ethPacket.setEtherType(Ethernet.TYPE_LLDP);
365 ethPacket.setDestinationMACAddress(ONLabLddp.LLDP_NICIRA);
366 ethPacket.setPayload(lldp);
367 ethPacket.setPad(true);
368
369
370 lldp.setPort(PD1.getPortNo().getPortNumber());
371 ethPacket.setSourceMACAddress(PD1.getHwAddr().getBytes());
372 return ethPacket.serialize();
373
374 }
375
376 @Override
377 public Dpid dpid() {
378 return swid;
379 }
380
381 @Override
382 public Integer inPort() {
383 return PD3.getPortNo().getPortNumber();
384 }
385
386 @Override
387 public boolean isHandled() {
388 return blocked;
389 }
390
391 @Override
392 public boolean isBuffered() {
393 return false;
394 }
395
396 }
397
398 private static class TestOpenFlowSwitch implements OpenFlowSwitch {
399
400 private final List<OFPortDesc> ports;
401 private final Dpid dpid;
402
403 public TestOpenFlowSwitch(Dpid dpid, List<OFPortDesc> ports) {
404 this.ports = ports;
405 this.dpid = dpid;
406 }
407
408 RoleState state;
409 List<OFMessage> sent = new ArrayList<OFMessage>();
410 OFFactory factory = OFFactoryVer10.INSTANCE;
411
412 @Override
413 public void sendMsg(OFMessage msg) {
414 sent.add(msg);
415 }
416
417 @Override
418 public void sendMsg(List<OFMessage> msgs) {
419 }
420
421 @Override
422 public void handleMessage(OFMessage fromSwitch) {
423 }
424
425 @Override
426 public void setRole(RoleState role) {
427 state = role;
428 }
429
430 @Override
431 public RoleState getRole() {
432 return state;
433 }
434
435 @Override
436 public List<OFPortDesc> getPorts() {
437 return ports;
438 }
439
440 @Override
441 public OFFactory factory() {
442 return factory;
443 }
444
445 @Override
446 public String getStringId() {
447 return null;
448 }
449
450 @Override
451 public long getId() {
452 return dpid.value();
453 }
454
455 @Override
456 public String manfacturerDescription() {
457 return null;
458 }
459
460 @Override
461 public String datapathDescription() {
462 return null;
463 }
464
465 @Override
466 public String hardwareDescription() {
467 return null;
468 }
469
470 @Override
471 public String softwareDescription() {
472 return null;
473 }
474
475 @Override
476 public String serialNumber() {
477 return null;
478 }
479
480 @Override
481 public void disconnectSwitch() {
482 }
483
484 @Override
485 public void returnRoleAssertFailure(RoleState role) {
486 }
487
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700488 @Override
489 public boolean isOptical() {
490 return false;
491 }
492
alshabib64231d82014-09-25 18:25:31 -0700493 }
494}