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