2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.openflowplugin.impl.connection;
10 import static org.mockito.ArgumentMatchers.any;
11 import static org.mockito.ArgumentMatchers.anyShort;
13 import com.google.common.collect.Lists;
14 import com.google.common.util.concurrent.Futures;
15 import java.math.BigInteger;
16 import java.time.LocalDateTime;
17 import java.util.ArrayList;
18 import java.util.List;
19 import org.junit.After;
20 import org.junit.Assert;
21 import org.junit.Before;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.mockito.ArgumentCaptor;
25 import org.mockito.Mock;
26 import org.mockito.Mockito;
27 import org.mockito.junit.MockitoJUnitRunner;
28 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
29 import org.opendaylight.openflowplugin.api.OFConstants;
30 import org.opendaylight.openflowplugin.api.openflow.connection.DeviceConnectionStatusProvider;
31 import org.opendaylight.openflowplugin.api.openflow.md.core.ErrorHandler;
32 import org.opendaylight.openflowplugin.api.openflow.md.core.HandshakeListener;
33 import org.opendaylight.openflowplugin.impl.common.DeviceConnectionRateLimiter;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.HelloElementType;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloOutput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.Elements;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.ElementsBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfigBuilder;
44 import org.opendaylight.yangtools.yang.common.RpcResult;
45 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
46 import org.opendaylight.yangtools.yang.common.Uint16;
47 import org.opendaylight.yangtools.yang.common.Uint32;
48 import org.opendaylight.yangtools.yang.common.Uint64;
49 import org.opendaylight.yangtools.yang.common.Uint8;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
56 @RunWith(MockitoJUnitRunner.class)
57 public class HandshakeManagerImplTest {
59 private static final Logger LOG = LoggerFactory.getLogger(HandshakeManagerImplTest.class);
60 private static final Uint16 DEVICE_CONNECTION_RATE_LIMIT_PER_MIN = Uint16.ZERO;
61 private static final int DEVICE_CONNECTION_HOLD_TIME_IN_SECONDS = 60;
63 private HandshakeManagerImpl handshakeManager;
65 private ConnectionAdapter adapter;
67 private ErrorHandler errorHandler;
69 private HandshakeListener handshakeListener;
71 private DeviceConnectionStatusProvider deviceConnectionStatusProvider;
73 private DeviceConnectionRateLimiter deviceConnectionRateLimiter;
75 private RpcResult<GetFeaturesOutput> resultFeatures;
77 private final long helloXid = 42L;
79 private int expectedErrors = 0;
82 * invoked before every test method.
86 deviceConnectionRateLimiter = new DeviceConnectionRateLimiter(new OpenflowProviderConfigBuilder()
87 .setDeviceConnectionRateLimitPerMin(DEVICE_CONNECTION_RATE_LIMIT_PER_MIN).build());
88 handshakeManager = new HandshakeManagerImpl(adapter, OFConstants.OFP_VERSION_1_3, OFConstants.VERSION_ORDER,
89 errorHandler, handshakeListener, false, deviceConnectionRateLimiter,
90 DEVICE_CONNECTION_HOLD_TIME_IN_SECONDS, deviceConnectionStatusProvider);
92 resultFeatures = RpcResultBuilder.success(new GetFeaturesOutputBuilder().setDatapathId(Uint64.ONE).build())
95 Mockito.when(adapter.hello(any(HelloInput.class)))
96 .thenReturn(Futures.immediateFuture(RpcResultBuilder.success((HelloOutput) null).build()));
97 Mockito.when(deviceConnectionStatusProvider.getDeviceLastConnectionTime(BigInteger.ONE))
98 .thenReturn(LocalDateTime.now().minusSeconds(DEVICE_CONNECTION_HOLD_TIME_IN_SECONDS));
102 * invoked after each test method.
105 public void teardown() {
106 // logging errors if occurred
107 ArgumentCaptor<Throwable> errorCaptor = ArgumentCaptor.forClass(Throwable.class);
108 Mockito.verify(errorHandler, Mockito.atMost(1)).handleException(errorCaptor.capture());
109 for (Throwable problem : errorCaptor.getAllValues()) {
110 LOG.warn(problem.getMessage(), problem);
113 Mockito.verify(errorHandler, Mockito.times(expectedErrors)).handleException(any(Throwable.class));
118 * {@link org.opendaylight.openflowplugin.openflow.md.core
119 * .HandshakeManagerImpl#proposeCommonBitmapVersion(java.util.List)}.
122 public void testProposeCommonBitmapVersion() {
124 = new Boolean[][]{{true, true, true, false, false, false}, {true, true, true, false, false}};
126 for (Boolean[] verasionList : versions) {
127 ElementsBuilder elementsBuilder = new ElementsBuilder();
128 elementsBuilder.setVersionBitmap(Lists.newArrayList(verasionList));
129 Elements element = elementsBuilder.build();
130 List<Elements> elements = Lists.newArrayList(element);
131 Short proposal = handshakeManager.proposeCommonBitmapVersion(elements);
132 Assert.assertEquals(Short.valueOf((short) 1), proposal);
138 * {@link org.opendaylight.openflowplugin.openflow.md.core.HandshakeManagerImpl#proposeNextVersion(short)}.
141 @SuppressWarnings("checkstyle:Illegalcatch")
142 public void testProposeNextVersion() {
143 short[] remoteVer = new short[]{0x05, 0x04, 0x03, 0x02, 0x01, 0x8f, 0xff};
144 short[] expectedProposal = new short[]{0x04, 0x04, 0x01, 0x01, 0x01, 0x04, 0x04};
146 for (int i = 0; i < remoteVer.length; i++) {
147 short actualProposal = handshakeManager.proposeNextVersion(remoteVer[i]);
148 Assert.assertEquals(String.format("proposing for version: %04x", remoteVer[i]), expectedProposal[i],
153 handshakeManager.proposeNextVersion((short) 0);
154 Assert.fail("there should be no proposition for this version");
155 } catch (Exception e) {
160 //////// Version Negotiation Tests //////////////
163 * Test of version negotiation Where switch version = 1.0.
167 public void testVersionNegotiation10() {
168 LOG.debug("testVersionNegotiation10");
169 Short version = OFConstants.OFP_VERSION_1_0;
171 Mockito.when(adapter.getFeatures(any(GetFeaturesInput.class)))
172 .thenReturn(Futures.immediateFuture(resultFeatures));
174 handshakeManager.shake(null);
176 handshakeManager.shake(createHelloMessage(version, helloXid).build());
178 Mockito.verify(handshakeListener).onHandshakeSuccessful(resultFeatures.getResult(), version);
182 * Test of version negotiation Where switch version = 1.0.
186 public void testVersionNegotiation10SwitchStarts() {
187 LOG.debug("testVersionNegotiation10-ss");
188 Short version = OFConstants.OFP_VERSION_1_0;
190 Mockito.when(adapter.getFeatures(any(GetFeaturesInput.class)))
191 .thenReturn(Futures.immediateFuture(resultFeatures));
193 handshakeManager.shake(createHelloMessage(version, helloXid).build());
195 Mockito.verify(handshakeListener).onHandshakeSuccessful(resultFeatures.getResult(), version);
199 * Test of version negotiation Where switch version < 1.0.
200 * Switch delivers first helloMessage with version 0x00 = negotiation unsuccessful
203 public void testVersionNegotiation00() {
204 LOG.debug("testVersionNegotiation00");
206 Short version = (short) 0x00;
208 handshakeManager.shake(createHelloMessage(version, helloXid).build());
210 Mockito.verify(handshakeListener, Mockito.never())
211 .onHandshakeSuccessful(any(GetFeaturesOutput.class), anyShort());
215 * Test of version negotiation Where switch version < 1.0.
216 * Switch delivers first helloMessage with version 0x00 = negotiation unsuccessful
219 public void testVersionNegotiation00SwitchStarts() {
220 LOG.debug("testVersionNegotiation00-ss");
222 Short version = (short) 0x00;
224 handshakeManager.shake(null);
226 handshakeManager.shake(createHelloMessage(version, helloXid).build());
228 Mockito.verify(handshakeListener, Mockito.never())
229 .onHandshakeSuccessful(any(GetFeaturesOutput.class), anyShort());
233 * Test of version negotiation Where 1.0 < switch version < 1.3.
237 public void testVersionNegotiation11() {
238 LOG.debug("testVersionNegotiation11");
239 Short version = (short) 0x02;
240 Short expVersion = (short) 0x01;
242 Mockito.when(adapter.getFeatures(any(GetFeaturesInput.class)))
243 .thenReturn(Futures.immediateFuture(resultFeatures));
245 handshakeManager.shake(createHelloMessage(version, helloXid).build());
247 handshakeManager.shake(createHelloMessage(expVersion, helloXid).build());
249 Mockito.verify(handshakeListener).onHandshakeSuccessful(resultFeatures.getResult(), expVersion);
253 * Test of version negotiation Where 1.0 < switch version < 1.3.
256 public void testVersionNegotiation11SwitchStarts() {
257 LOG.debug("testVersionNegotiation11-ss");
258 final Short version = (short) 0x02;
259 final Short expVersion = (short) 0x01;
261 Mockito.when(adapter.getFeatures(any(GetFeaturesInput.class)))
262 .thenReturn(Futures.immediateFuture(resultFeatures));
264 handshakeManager.shake(null);
266 handshakeManager.shake(createHelloMessage(version, helloXid).build());
268 handshakeManager.shake(createHelloMessage(expVersion, helloXid).build());
270 Mockito.verify(handshakeListener).onHandshakeSuccessful(resultFeatures.getResult(), expVersion);
274 * Test of version negotiation Where switch version = 1.3.
278 public void testVersionNegotiation13() {
279 LOG.debug("testVersionNegotiation13");
280 Short version = OFConstants.OFP_VERSION_1_3;
282 Mockito.when(adapter.getFeatures(any(GetFeaturesInput.class)))
283 .thenReturn(Futures.immediateFuture(resultFeatures));
285 handshakeManager.shake(createHelloMessage(version, helloXid).build());
287 Mockito.verify(handshakeListener).onHandshakeSuccessful(resultFeatures.getResult(), version);
291 * Test of version negotiation Where switch version = 1.3.
295 public void testVersionNegotiation13SwitchStarts() {
296 LOG.debug("testVersionNegotiation13-ss");
297 Short version = OFConstants.OFP_VERSION_1_3;
299 Mockito.when(adapter.getFeatures(any(GetFeaturesInput.class)))
300 .thenReturn(Futures.immediateFuture(resultFeatures));
302 handshakeManager.shake(null);
304 handshakeManager.shake(createHelloMessage(version, helloXid).build());
306 Mockito.verify(handshakeListener).onHandshakeSuccessful(resultFeatures.getResult(), version);
310 * Test of version negotiation Where switch version >= 1.3.
314 public void testVersionNegotiation15() {
315 LOG.debug("testVersionNegotiation15");
316 Short version = (short) 0x06;
317 Short expVersion = OFConstants.OFP_VERSION_1_3;
319 Mockito.when(adapter.getFeatures(any(GetFeaturesInput.class)))
320 .thenReturn(Futures.immediateFuture(resultFeatures));
322 handshakeManager.shake(createHelloMessage(version, helloXid).build());
324 handshakeManager.shake(createHelloMessage(expVersion, helloXid).build());
326 Mockito.verify(handshakeListener).onHandshakeSuccessful(resultFeatures.getResult(), expVersion);
330 * Test of version negotiation Where switch version >= 1.3.
334 public void testVersionNegotiation15SwitchStart() {
335 LOG.debug("testVersionNegotiation15-ss");
336 Short version = (short) 0x06;
337 Short expVersion = OFConstants.OFP_VERSION_1_3;
339 Mockito.when(adapter.getFeatures(any(GetFeaturesInput.class)))
340 .thenReturn(Futures.immediateFuture(resultFeatures));
342 handshakeManager.shake(createHelloMessage(version, helloXid).build());
344 handshakeManager.shake(createHelloMessage(expVersion, helloXid).build());
346 Mockito.verify(handshakeListener).onHandshakeSuccessful(resultFeatures.getResult(), expVersion);
350 * Test of version negotiation Where switch version > 1.3.
354 public void testVersionNegotiation15_MultipleCall() {
355 LOG.debug("testVersionNegotiation15_MultipleCall");
356 Short version = (short) 0x06;
359 handshakeManager.shake(createHelloMessage(version, helloXid).build());
361 handshakeManager.shake(createHelloMessage(version, helloXid).build());
363 Mockito.verify(handshakeListener, Mockito.never())
364 .onHandshakeSuccessful(any(GetFeaturesOutput.class), anyShort());
368 * Test of version negotiation Where switch version > 1.3.
372 public void testVersionNegotiation15_MultipleCallSwitchStarts() {
373 LOG.debug("testVersionNegotiation15_MultipleCall-ss");
374 Short version = (short) 0x06;
377 handshakeManager.shake(null);
379 handshakeManager.shake(createHelloMessage(version, helloXid).build());
381 handshakeManager.shake(createHelloMessage(version, helloXid).build());
383 Mockito.verify(handshakeListener, Mockito.never())
384 .onHandshakeSuccessful(any(GetFeaturesOutput.class), anyShort());
388 * Test of version negotiation Where bitmap version {0x05,0x01}.
392 public void testVersionNegotiation10InBitmap() {
393 LOG.debug("testVersionNegotiation10InBitmap");
394 Short version = OFConstants.OFP_VERSION_1_0;
395 handshakeManager.setUseVersionBitmap(true);
397 HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
398 addVersionBitmap(Lists.newArrayList((short) 0x05, OFConstants.OFP_VERSION_1_0), helloMessage);
400 Mockito.when(adapter.getFeatures(any(GetFeaturesInput.class)))
401 .thenReturn(Futures.immediateFuture(resultFeatures));
403 handshakeManager.shake(helloMessage.build());
405 Mockito.verify(handshakeListener).onHandshakeSuccessful(resultFeatures.getResult(), version);
409 * Test of version negotiation Where bitmap version {0x05,0x01}.
413 public void testVersionNegotiation10InBitmapSwitchStarts() {
414 LOG.debug("testVersionNegotiation10InBitmap-ss");
415 Short version = OFConstants.OFP_VERSION_1_0;
416 handshakeManager.setUseVersionBitmap(true);
418 HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
419 addVersionBitmap(Lists.newArrayList((short) 0x05, OFConstants.OFP_VERSION_1_0), helloMessage);
421 Mockito.when(adapter.getFeatures(any(GetFeaturesInput.class)))
422 .thenReturn(Futures.immediateFuture(resultFeatures));
424 handshakeManager.shake(null);
426 handshakeManager.shake(helloMessage.build());
428 Mockito.verify(handshakeListener).onHandshakeSuccessful(resultFeatures.getResult(), version);
432 * Test of version negotiation Where bitmap version {0x05,0x04}.
436 public void testVersionNegotiation13InBitmap() {
437 LOG.debug("testVersionNegotiation13InBitmap");
438 Short version = OFConstants.OFP_VERSION_1_3;
439 handshakeManager.setUseVersionBitmap(true);
441 HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
442 addVersionBitmap(Lists.newArrayList((short) 0x05, OFConstants.OFP_VERSION_1_3), helloMessage);
444 Mockito.when(adapter.getFeatures(any(GetFeaturesInput.class)))
445 .thenReturn(Futures.immediateFuture(resultFeatures));
447 handshakeManager.shake(helloMessage.build());
449 Mockito.verify(handshakeListener).onHandshakeSuccessful(resultFeatures.getResult(), version);
453 * Test of version negotiation Where bitmap version {0x05,0x04}.
457 public void testVersionNegotiation13InBitmapSwitchFirst() {
458 LOG.debug("testVersionNegotiation13InBitmap-ss");
459 Short version = OFConstants.OFP_VERSION_1_3;
460 handshakeManager.setUseVersionBitmap(true);
462 HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
463 addVersionBitmap(Lists.newArrayList((short) 0x05, OFConstants.OFP_VERSION_1_3), helloMessage);
465 Mockito.when(adapter.getFeatures(any(GetFeaturesInput.class)))
466 .thenReturn(Futures.immediateFuture(resultFeatures));
468 handshakeManager.shake(null);
470 handshakeManager.shake(helloMessage.build());
472 Mockito.verify(handshakeListener).onHandshakeSuccessful(resultFeatures.getResult(), version);
476 * Test of version negotiation Where bitmap version {0x05,0x02}.
480 public void testVersionNegotiationNoCommonVersionInBitmap() {
481 LOG.debug("testVersionNegotiationNoCommonVersionInBitmap");
482 Short version = (short) 0x05;
484 handshakeManager.setUseVersionBitmap(true);
486 HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
487 addVersionBitmap(Lists.newArrayList((short) 0x05, (short) 0x02), helloMessage);
489 handshakeManager.shake(helloMessage.build());
491 Mockito.verify(handshakeListener, Mockito.never())
492 .onHandshakeSuccessful(any(GetFeaturesOutput.class), anyShort());
496 * Test of version negotiation Where bitmap version {0x05,0x02}.
500 public void testVersionNegotiationNoCommonVersionInBitmapSwitchStarts() {
501 LOG.debug("testVersionNegotiationNoCommonVersionInBitmap-ss");
502 Short version = (short) 0x05;
504 handshakeManager.setUseVersionBitmap(true);
506 HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
507 addVersionBitmap(Lists.newArrayList((short) 0x05, (short) 0x02), helloMessage);
509 handshakeManager.shake(null);
511 handshakeManager.shake(helloMessage.build());
513 Mockito.verify(handshakeListener, Mockito.never())
514 .onHandshakeSuccessful(any(GetFeaturesOutput.class), anyShort());
519 * Creates hello message.
521 * @param ofpVersion10 version
522 * @param helloXid hello xid
525 private static HelloMessageBuilder createHelloMessage(short ofpVersion10, long helloXid) {
526 return new HelloMessageBuilder().setVersion(Uint8.valueOf(ofpVersion10)).setXid(Uint32.valueOf(helloXid));
530 * Adds version bitmap.
531 * @param versionOrder version order
532 * @param helloBuilder hello builder
535 private static HelloMessageBuilder addVersionBitmap(List<Short> versionOrder, HelloMessageBuilder helloBuilder) {
536 short highestVersion = versionOrder.get(0);
537 int elementsCount = highestVersion / Integer.SIZE;
538 ElementsBuilder elementsBuilder = new ElementsBuilder();
540 List<Elements> elementList = new ArrayList<>();
541 int orderIndex = versionOrder.size();
542 int value = versionOrder.get(--orderIndex);
543 for (int index = 0; index <= elementsCount; index++) {
544 List<Boolean> booleanList = new ArrayList<>();
545 for (int i = 0; i < Integer.SIZE; i++) {
546 if (value == index * Integer.SIZE + i) {
547 booleanList.add(true);
548 value = orderIndex == 0 ? highestVersion : versionOrder.get(--orderIndex);
550 booleanList.add(false);
553 elementsBuilder.setType(HelloElementType.forValue(1));
554 elementsBuilder.setVersionBitmap(booleanList);
555 elementList.add(elementsBuilder.build());
558 helloBuilder.setElements(elementList);