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
9 package org.opendaylight.openflowplugin.openflow.md.core;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.HashMap;
15 import java.util.List;
17 import java.util.Stack;
18 import java.util.concurrent.ScheduledThreadPoolExecutor;
19 import java.util.concurrent.TimeUnit;
21 import org.junit.After;
22 import org.junit.Assert;
23 import org.junit.Before;
24 import org.junit.Test;
25 import org.junit.runner.RunWith;
26 import org.mockito.ArgumentCaptor;
27 import org.mockito.Matchers;
28 import org.mockito.Mock;
29 import org.mockito.Mockito;
30 import org.mockito.runners.MockitoJUnitRunner;
31 import org.opendaylight.openflowplugin.openflow.md.OFConstants;
32 import org.opendaylight.openflowplugin.openflow.md.core.plan.ConnectionAdapterStackImpl;
33 import org.opendaylight.openflowplugin.openflow.md.core.plan.EventFactory;
34 import org.opendaylight.openflowplugin.openflow.md.core.plan.SwitchTestEvent;
35 import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
36 import org.opendaylight.openflowplugin.openflow.md.queue.MessageSpy;
37 import org.opendaylight.openflowplugin.openflow.md.queue.PopListener;
38 import org.opendaylight.openflowplugin.openflow.md.queue.QueueKeeperLightImpl;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Capabilities;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ErrorType;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeaturesV10;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortReason;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessageBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterInputBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessageBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessageBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessageBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessageBuilder;
59 import org.opendaylight.yangtools.yang.binding.DataContainer;
60 import org.opendaylight.yangtools.yang.binding.DataObject;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
64 @RunWith(MockitoJUnitRunner.class)
65 public class ConnectionConductorImplTest {
67 protected static final Logger LOG = LoggerFactory
68 .getLogger(ConnectionConductorImplTest.class);
71 private final int maxProcessingTimeout = 500;
73 protected ConnectionAdapterStackImpl adapter;
74 private ConnectionConductorImpl connectionConductor;
75 private MDController controller;
76 private Stack<SwitchTestEvent> eventPlan;
78 private Thread libSimulation;
79 private ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(
82 private QueueKeeperLightImpl queueKeeper;
84 private PopListener<DataObject> popListener;
86 private int experimenterMessageCounter;
87 private int packetinMessageCounter;
88 private int flowremovedMessageCounter;
89 private int portstatusAddMessageCounter;
90 private int portstatusDeleteMessageCounter;
91 private int portstatusModifyMessageCounter;
92 private int errorMessageCounter;
95 private ErrorHandlerSimpleImpl errorHandler;
97 private int expectedErrors = 0;
99 private MessageSpy<DataContainer> messageSpy;
101 public void incrExperimenterMessageCounter() {
102 this.experimenterMessageCounter++;
105 public void incrPacketinMessageCounter() {
106 this.packetinMessageCounter++;
109 public void incrFlowremovedMessageCounter() {
110 this.flowremovedMessageCounter++;
113 public void incrPortstatusAddMessageCounter() {
114 this.portstatusAddMessageCounter++;
117 public void incrPortstatusDeleteMessageCounter() {
118 this.portstatusDeleteMessageCounter++;
121 public void incrPortstatusModifyMessageCounter() {
122 this.portstatusModifyMessageCounter++;
125 public void incrErrorMessageCounter() {
126 this.errorMessageCounter++;
131 * @throws java.lang.Exception
134 public void setUp() throws Exception {
135 adapter = new ConnectionAdapterStackImpl();
137 popListener = new PopListenerCountingImpl<>();
139 queueKeeper = new QueueKeeperLightImpl();
140 queueKeeper.setMessageSpy(messageSpy);
142 connectionConductor = new ConnectionConductorImpl(adapter);
143 connectionConductor.setQueueKeeper(queueKeeper);
144 connectionConductor.init();
145 connectionConductor.setErrorHandler(errorHandler);
146 controller = new MDController();
148 queueKeeper.setTranslatorMapping(controller.getMessageTranslators());
149 eventPlan = new Stack<>();
150 adapter.setEventPlan(eventPlan);
151 adapter.setProceedTimeout(5000L);
152 adapter.checkListeners();
154 controller.getMessageTranslators().putAll(assembleTranslatorMapping());
155 queueKeeper.setPopListenersMapping(assemblePopListenerMapping());
162 private Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> assemblePopListenerMapping() {
163 Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> mapping = new HashMap<>();
164 Collection<PopListener<DataObject>> popListenerBag = new ArrayList<>();
165 popListenerBag.add(popListener);
166 //TODO: add testing registered types
167 mapping.put(DataObject.class, popListenerBag);
172 * @throws java.lang.Exception
175 public void tearDown() throws Exception {
176 if (libSimulation != null) {
177 libSimulation.join();
179 queueKeeper.shutdown();
180 connectionConductor.shutdownPool();
182 for (Exception problem : adapter.getOccuredExceptions()) {
183 LOG.error("during simulation on adapter side: "
184 + problem.getMessage());
186 Assert.assertEquals(0, adapter.getOccuredExceptions().size());
188 if (LOG.isDebugEnabled()) {
189 if (eventPlan.size() > 0) {
190 LOG.debug("eventPlan size: " + eventPlan.size());
191 for (SwitchTestEvent event : eventPlan) {
192 LOG.debug(" # EVENT:: " + event.toString());
196 Assert.assertTrue("plan is not finished", eventPlan.isEmpty());
200 // logging errors if occurred
201 ArgumentCaptor<Throwable> errorCaptor = ArgumentCaptor.forClass(Throwable.class);
202 Mockito.verify(errorHandler, Mockito.atMost(1)).handleException(
203 errorCaptor.capture(), Matchers.any(SessionContext.class));
204 for (Throwable problem : errorCaptor.getAllValues()) {
205 LOG.warn(problem.getMessage(), problem);
208 Mockito.verify(errorHandler, Mockito.times(expectedErrors )).handleException(
209 Matchers.any(Throwable.class), Matchers.any(SessionContext.class));
214 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onEchoRequestMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessage)}
219 public void testOnEchoRequestMessage() throws Exception {
220 simulateV13PostHandshakeState(connectionConductor);
222 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
223 EventFactory.DEFAULT_VERSION, new EchoRequestMessageBuilder()));
225 EventFactory.createDefaultWaitForRpcEvent(42, "echoReply"));
230 * Test of handshake, covering version negotiation and features.
231 * Switch delivers first helloMessage with default version.
235 public void testHandshake1() throws Exception {
236 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
237 EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
238 eventPlan.add(0, EventFactory.createDefaultWaitForAllEvent(
239 EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"),
240 EventFactory.createDefaultWaitForRpcEvent(44, "getFeatures")));
241 eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(44,
242 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
244 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(1, "multipartRequestInput"));
245 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(2, "multipartRequestInput"));
246 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(3, "multipartRequestInput"));
247 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(4, "multipartRequestInput"));
250 Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
251 connectionConductor.getConductorState());
252 Assert.assertEquals((short) 0x04, connectionConductor.getVersion()
257 * Test of handshake, covering version negotiation and features.
258 * Controller sends first helloMessage with default version
262 public void testHandshake1SwitchStarts() throws Exception {
263 eventPlan.add(0, EventFactory.createConnectionReadyCallback(connectionConductor));
264 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(21, "helloReply"));
265 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
266 EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
267 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(43, "getFeatures"));
268 eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(43,
269 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
271 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(1, "multipartRequestInput"));
272 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(2, "multipartRequestInput"));
273 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(3, "multipartRequestInput"));
274 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(4, "multipartRequestInput"));
278 Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
279 connectionConductor.getConductorState());
280 Assert.assertEquals((short) 0x04, connectionConductor.getVersion()
285 * Test of handshake, covering version negotiation and features.
286 * Switch delivers first helloMessage with version 0x05
287 * and negotiates following versions: 0x03, 0x01
291 public void testHandshake2() throws Exception {
292 connectionConductor.setBitmapNegotiationEnable(false);
293 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
294 (short) 0x05, new HelloMessageBuilder()));
296 EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
297 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(43L,
298 (short) 0x03, new HelloMessageBuilder()));
300 EventFactory.createDefaultWaitForRpcEvent(44, "helloReply"));
301 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44L,
302 (short) 0x01, new HelloMessageBuilder()));
304 EventFactory.createDefaultWaitForRpcEvent(45, "getFeatures"));
306 eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(45,
307 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
309 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(1, "multipartRequestInput"));
310 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(2, "multipartRequestInput"));
314 Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
315 connectionConductor.getConductorState());
316 Assert.assertEquals((short) 0x01, connectionConductor.getVersion()
321 * Test of handshake, covering version negotiation and features.
322 * Controller sends first helloMessage with default version
323 * and switch negotiates following versions: 0x05, 0x03, 0x01
327 public void testHandshake2SwitchStarts() throws Exception {
328 connectionConductor.setBitmapNegotiationEnable(false);
329 eventPlan.add(0, EventFactory.createConnectionReadyCallback(connectionConductor));
331 EventFactory.createDefaultWaitForRpcEvent(21, "helloReply"));
332 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
333 (short) 0x05, new HelloMessageBuilder()));
334 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(43L,
335 (short) 0x03, new HelloMessageBuilder()));
337 EventFactory.createDefaultWaitForRpcEvent(44, "helloReply"));
338 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44L,
339 (short) 0x01, new HelloMessageBuilder()));
341 EventFactory.createDefaultWaitForRpcEvent(45, "getFeatures"));
343 eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(45,
344 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
346 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(1, "multipartRequestInput"));
347 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(2, "multipartRequestInput"));
351 Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
352 connectionConductor.getConductorState());
353 Assert.assertEquals((short) 0x01, connectionConductor.getVersion()
359 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage)}
361 * @throws InterruptedException
364 public void testOnExperimenterMessage1() throws InterruptedException {
365 simulateV13PostHandshakeState(connectionConductor);
368 EventFactory.createDefaultWaitForRpcEvent(42, "experimenter"));
369 ExperimenterMessageBuilder builder1 = new ExperimenterMessageBuilder();
370 builder1.setExperimenter(84L).setExpType(4L);
371 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
372 EventFactory.DEFAULT_VERSION, builder1));
376 Runnable sendExperimenterCmd = new Runnable() {
380 ExperimenterInputBuilder builder2 = new ExperimenterInputBuilder();
381 builder2.setExperimenter(84L).setExpType(4L);
382 EventFactory.setupHeader(42L, builder2);
383 adapter.experimenter(builder2.build());
386 pool.schedule(sendExperimenterCmd,
387 ConnectionAdapterStackImpl.JOB_DELAY, TimeUnit.MILLISECONDS);
392 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage)}
394 * @throws InterruptedException
397 public void testOnExperimenterMessage2() throws InterruptedException {
398 simulateV13PostHandshakeState(connectionConductor);
401 EventFactory.createDefaultWaitForRpcEvent(42, "experimenter"));
402 ErrorMessageBuilder builder1 = new ErrorMessageBuilder();
403 builder1.setType(ErrorType.BADREQUEST.getIntValue()).setCode(3)
404 .setData(new byte[] { 1, 2, 3 });
406 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
407 EventFactory.DEFAULT_VERSION, builder1));
411 Runnable sendExperimenterCmd = new Runnable() {
415 ExperimenterInputBuilder builder2 = new ExperimenterInputBuilder();
416 builder2.setExperimenter(84L).setExpType(4L);
417 EventFactory.setupHeader(42L, builder2);
418 adapter.experimenter(builder2.build());
421 pool.schedule(sendExperimenterCmd,
422 ConnectionAdapterStackImpl.JOB_DELAY, TimeUnit.MILLISECONDS);
427 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onFlowRemovedMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage)}
429 * @throws InterruptedException
432 public void testOnFlowRemovedMessage() throws InterruptedException {
433 IMDMessageTranslator<OfHeader, List<DataObject>> objFms = new FlowRemovedMessageService() ;
434 controller.addMessageTranslator(FlowRemovedMessage.class, 4, objFms);
436 simulateV13PostHandshakeState(connectionConductor);
438 // Now send Flow Removed messages
439 FlowRemovedMessageBuilder builder1 = new FlowRemovedMessageBuilder();
440 builder1.setVersion((short) 4);
442 connectionConductor.onFlowRemovedMessage(builder1.build());
443 synchronized (popListener) {
444 LOG.debug("about to wait for popListener");
445 popListener.wait(maxProcessingTimeout);
447 Assert.assertEquals(1, flowremovedMessageCounter);
449 connectionConductor.onFlowRemovedMessage(builder1.build());
450 synchronized (popListener) {
451 popListener.wait(maxProcessingTimeout);
453 Assert.assertEquals(2, flowremovedMessageCounter);
458 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onMultipartReplyMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage)}
462 public void testOnMultipartReplyMessage() {
463 // fail("Not yet implemented");
469 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPacketInMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage)}
471 * @throws InterruptedException
474 public void testOnPacketInMessage() throws InterruptedException {
475 IMDMessageTranslator<OfHeader, List<DataObject>> objPms = new PacketInMessageService() ;
476 controller.addMessageTranslator(PacketInMessage.class, 4, objPms);
478 simulateV13PostHandshakeState(connectionConductor);
481 PacketInMessageBuilder builder1 = new PacketInMessageBuilder();
482 builder1.setVersion((short) 4);
483 builder1.setBufferId((long)1);
484 connectionConductor.onPacketInMessage(builder1.build());
485 synchronized (popListener) {
486 popListener.wait(maxProcessingTimeout);
488 Assert.assertEquals(1, packetinMessageCounter);
489 builder1.setBufferId((long)2);
490 connectionConductor.onPacketInMessage(builder1.build());
491 synchronized (popListener) {
492 popListener.wait(maxProcessingTimeout);
494 Assert.assertEquals(2, packetinMessageCounter);
499 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPortStatusMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage)}
501 * @throws InterruptedException
504 public void testOnPortStatusMessage() throws InterruptedException {
505 IMDMessageTranslator<OfHeader, List<DataObject>> objPSms = new PortStatusMessageService() ;
506 controller.addMessageTranslator(PortStatusMessage.class, 4, objPSms);
508 simulateV13PostHandshakeState(connectionConductor);
510 // Send Port Status messages
511 PortStatusMessageBuilder builder1 = new PortStatusMessageBuilder();
512 builder1.setVersion((short) 4);
513 PortFeatures features = new PortFeatures(true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false);
514 builder1.setPortNo(90L).setReason(PortReason.OFPPRADD).setCurrentFeatures(features);
515 connectionConductor.onPortStatusMessage(builder1.build());
516 synchronized (popListener) {
517 popListener.wait(maxProcessingTimeout);
519 Assert.assertEquals(1, portstatusAddMessageCounter);
520 builder1.setPortNo(90L).setReason(PortReason.OFPPRMODIFY).setCurrentFeatures(features);
521 connectionConductor.onPortStatusMessage(builder1.build());
522 synchronized (popListener) {
523 popListener.wait(maxProcessingTimeout);
525 Assert.assertEquals(1, portstatusModifyMessageCounter);
526 builder1.setPortNo(90L).setReason(PortReason.OFPPRDELETE).setCurrentFeatures(features);
527 connectionConductor.onPortStatusMessage(builder1.build());
528 synchronized (popListener) {
529 popListener.wait(maxProcessingTimeout);
531 Assert.assertEquals(1, portstatusDeleteMessageCounter);
535 * @throws InterruptedException
537 private void executeLater() throws InterruptedException {
542 * @throws InterruptedException
544 private void executeNow() throws InterruptedException {
546 connectionConductor.shutdownPool();
550 * @throws InterruptedException
552 private void execute(boolean join) throws InterruptedException {
553 libSimulation = new Thread(adapter, "junit-adapter");
554 libSimulation.start();
556 libSimulation.join();
560 private static GetFeaturesOutputBuilder getFeatureResponseMsg() {
561 GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
562 getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
563 getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
564 getFeaturesOutputBuilder.setBuffers(4L);
565 getFeaturesOutputBuilder.setReserved(0L);
566 getFeaturesOutputBuilder.setTables((short) 2);
567 getFeaturesOutputBuilder.setCapabilities(createCapabilities(84));
569 return getFeaturesOutputBuilder;
575 private static Capabilities createCapabilities(long input) {
576 final Boolean FLOW_STATS = (input & (1 << 0)) != 0;
577 final Boolean TABLE_STATS = (input & (1 << 1)) != 0;
578 final Boolean PORT_STATS = (input & (1 << 2)) != 0;
579 final Boolean GROUP_STATS = (input & (1 << 3)) != 0;
580 final Boolean IP_REASM = (input & (1 << 5)) != 0;
581 final Boolean QUEUE_STATS = (input & (1 << 6)) != 0;
582 final Boolean PORT_BLOCKED = (input & (1 << 8)) != 0;
583 Capabilities capabilities = new Capabilities(FLOW_STATS, GROUP_STATS, IP_REASM,
584 PORT_BLOCKED, PORT_STATS, QUEUE_STATS, TABLE_STATS);
588 public class ExperimenterMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
590 public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
591 LOG.debug("Received a packet in Experimenter Service");
592 ConnectionConductorImplTest.this.incrExperimenterMessageCounter();
597 public class PacketInMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
599 public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
600 LOG.debug("Received a packet in PacketIn Service");
601 ConnectionConductorImplTest.this.incrPacketinMessageCounter();
606 public class FlowRemovedMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
608 public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
609 LOG.debug("Received a packet in FlowRemoved Service");
610 ConnectionConductorImplTest.this.incrFlowremovedMessageCounter();
615 public class PortStatusMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
617 public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
618 LOG.debug("Received a packet in PortStatus Service");
619 if ( (((PortStatusMessage)msg).getReason().equals(PortReason.OFPPRADD)) ) {
620 ConnectionConductorImplTest.this.incrPortstatusAddMessageCounter();
621 } else if (((PortStatusMessage)msg).getReason().equals(PortReason.OFPPRDELETE)){
622 ConnectionConductorImplTest.this.incrPortstatusDeleteMessageCounter();
623 } else if (((PortStatusMessage)msg).getReason().equals(PortReason.OFPPRMODIFY)) {
624 ConnectionConductorImplTest.this.incrPortstatusModifyMessageCounter();
630 public class ErrorMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
632 public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
633 LOG.debug("Received a packet in Experimenter Service");
634 ConnectionConductorImplTest.this.incrErrorMessageCounter();
641 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage)}
643 * @throws InterruptedException
646 public void testOnExperimenterMessage() throws InterruptedException {
647 simulateV13PostHandshakeState(connectionConductor);
649 ExperimenterMessageBuilder builder1 = new ExperimenterMessageBuilder();
650 builder1.setVersion((short) 4);
651 builder1.setExperimenter(84L).setExpType(4L);
652 connectionConductor.onExperimenterMessage(builder1.build());
653 synchronized (popListener) {
654 popListener.wait(maxProcessingTimeout);
656 Assert.assertEquals(1, experimenterMessageCounter);
658 builder1.setExperimenter(85L).setExpType(4L);
659 connectionConductor.onExperimenterMessage(builder1.build());
660 synchronized (popListener) {
661 popListener.wait(maxProcessingTimeout);
663 Assert.assertEquals(2, experimenterMessageCounter);
668 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage)}
670 * @throws InterruptedException
673 public void testOnErrorMessage() throws InterruptedException {
674 simulateV13PostHandshakeState(connectionConductor);
676 ErrorMessageBuilder builder1 = new ErrorMessageBuilder();
677 builder1.setVersion((short) 4);
678 builder1.setCode(100);
679 connectionConductor.onErrorMessage(builder1.build());
680 synchronized (popListener) {
681 popListener.wait(maxProcessingTimeout);
683 Assert.assertEquals(1, errorMessageCounter);
684 builder1.setCode(200);
685 connectionConductor.onErrorMessage(builder1.build());
686 synchronized (popListener) {
687 popListener.wait(maxProcessingTimeout);
689 Assert.assertEquals(2, errorMessageCounter);
693 * @return listener mapping for:
695 * <li>experimenter</li>
699 private Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> assembleTranslatorMapping() {
700 Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping = new HashMap<>();
703 IMDMessageTranslator<OfHeader, List<DataObject>> objEms = new ExperimenterMessageService() ;
704 Collection<IMDMessageTranslator<OfHeader, List<DataObject>>> existingValues = new ArrayList<>();
705 existingValues.add(objEms);
706 tKey = new TranslatorKey(4, ExperimenterMessage.class.getName());
707 translatorMapping.put(tKey, existingValues);
708 IMDMessageTranslator<OfHeader, List<DataObject>> objErms = new ErrorMessageService() ;
709 existingValues.add(objErms);
710 tKey = new TranslatorKey(4, ErrorMessage.class.getName());
711 translatorMapping.put(tKey, existingValues);
712 return translatorMapping;
717 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#processPortStatusMsg(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage)}
719 * Tests for getting features from port status message by port version
721 * <li>features are malformed - one of them is null</li>
722 * <li>mismatch between port version and port features</li>
723 * <li>mismatch between port version and port features</li>
724 * <li>non-existing port version</li>
725 * <li>port version OF 1.0</li>
726 * <li>port version OF 1.3</li>
731 public void testProcessPortStatusMsg() {
732 simulateV13PostHandshakeState(connectionConductor);
734 long portNumber = 90L;
735 long portNumberV10 = 91L;
736 PortStatusMessage msg;
738 PortStatusMessageBuilder builder = new PortStatusMessageBuilder();
739 PortFeatures features = new PortFeatures(true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false);
740 PortFeatures featuresMal = new PortFeatures(true,false,false,false,null,false,false,false,false,false,false,false,false,false,false,false);
741 PortFeaturesV10 featuresV10 = new PortFeaturesV10(true,false,false,false,false,false,false,false,false,false,false,false);
744 builder.setVersion((short) 1).setPortNo(portNumber).setReason(PortReason.OFPPRADD).setCurrentFeatures(featuresMal);
745 connectionConductor.processPortStatusMsg(builder.build());
746 Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
747 Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
749 //Version-features mismatch
750 builder.setCurrentFeatures(features);
751 connectionConductor.processPortStatusMsg(builder.build());
752 Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
753 Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
755 //Non existing version
756 builder.setVersion((short) 0);
757 connectionConductor.processPortStatusMsg(builder.build());
758 Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
759 Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
762 builder.setVersion((short) 4);
763 msg = builder.build();
764 connectionConductor.processPortStatusMsg(builder.build());
765 Assert.assertTrue(connectionConductor.getSessionContext().getPortBandwidth(portNumber));
766 Assert.assertEquals(connectionConductor.getSessionContext().getPhysicalPort(portNumber), msg);
769 builder.setVersion((short) 1).setPortNo(portNumberV10).setCurrentFeatures(null).setCurrentFeaturesV10(featuresV10);
770 msg = builder.build();
771 connectionConductor.processPortStatusMsg(builder.build());
772 Assert.assertTrue(connectionConductor.getSessionContext().getPortBandwidth(portNumberV10));
773 Assert.assertEquals(connectionConductor.getSessionContext().getPhysicalPort(portNumberV10), msg);
776 private void simulateV13PostHandshakeState(ConnectionConductorImpl conductor) {
777 GetFeaturesOutputBuilder featureOutput = getFeatureResponseMsg();
778 conductor.postHandshakeBasic(featureOutput.build(), OFConstants.OFP_VERSION_1_3);