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