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.PopListener;
37 import org.opendaylight.openflowplugin.openflow.md.queue.QueueKeeperLightImpl;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Capabilities;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ErrorType;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeaturesV10;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortReason;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessageBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterInputBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessageBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessageBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
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.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.features._case.MultipartReplyGroupFeaturesBuilder;
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 ErrorHandlerQueueImpl errorHandler;
97 private int expectedErrors = 0;
99 public void incrExperimenterMessageCounter() {
100 this.experimenterMessageCounter++;
103 public void incrPacketinMessageCounter() {
104 this.packetinMessageCounter++;
107 public void incrFlowremovedMessageCounter() {
108 this.flowremovedMessageCounter++;
111 public void incrPortstatusAddMessageCounter() {
112 this.portstatusAddMessageCounter++;
115 public void incrPortstatusDeleteMessageCounter() {
116 this.portstatusDeleteMessageCounter++;
119 public void incrPortstatusModifyMessageCounter() {
120 this.portstatusModifyMessageCounter++;
123 public void incrErrorMessageCounter() {
124 this.errorMessageCounter++;
129 * @throws java.lang.Exception
132 public void setUp() throws Exception {
133 adapter = new ConnectionAdapterStackImpl();
135 popListener = new PopListenerCountingImpl<>();
137 queueKeeper = new QueueKeeperLightImpl();
139 connectionConductor = new ConnectionConductorImpl(adapter);
140 connectionConductor.setQueueKeeper(queueKeeper);
141 connectionConductor.init();
142 pool.execute(errorHandler);
143 connectionConductor.setErrorHandler(errorHandler);
144 controller = new MDController();
146 queueKeeper.setTranslatorMapping(controller.getMessageTranslators());
147 eventPlan = new Stack<>();
148 adapter.setEventPlan(eventPlan);
149 adapter.setProceedTimeout(5000L);
150 adapter.checkListeners();
152 controller.getMessageTranslators().putAll(assembleTranslatorMapping());
153 queueKeeper.setPopListenersMapping(assemblePopListenerMapping());
160 private Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> assemblePopListenerMapping() {
161 Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> mapping = new HashMap<>();
162 Collection<PopListener<DataObject>> popListenerBag = new ArrayList<>();
163 popListenerBag.add(popListener);
164 //TODO: add testing registered types
165 mapping.put(DataObject.class, popListenerBag);
170 * @throws java.lang.Exception
173 public void tearDown() throws Exception {
174 if (libSimulation != null) {
175 libSimulation.join();
177 queueKeeper.shutdown();
178 connectionConductor.shutdownPool();
180 for (Exception problem : adapter.getOccuredExceptions()) {
181 LOG.error("during simulation on adapter side: "
182 + problem.getMessage());
184 Assert.assertEquals(0, adapter.getOccuredExceptions().size());
186 if (LOG.isDebugEnabled()) {
187 if (eventPlan.size() > 0) {
188 LOG.debug("eventPlan size: " + eventPlan.size());
189 for (SwitchTestEvent event : eventPlan) {
190 LOG.debug(" # EVENT:: " + event.toString());
194 Assert.assertTrue("plan is not finished", eventPlan.isEmpty());
198 // logging errors if occurred
199 ArgumentCaptor<Throwable> errorCaptor = ArgumentCaptor.forClass(Throwable.class);
200 Mockito.verify(errorHandler, Mockito.atMost(1)).handleException(
201 errorCaptor.capture(), Matchers.any(SessionContext.class));
202 for (Throwable problem : errorCaptor.getAllValues()) {
203 LOG.warn(problem.getMessage(), problem);
206 Mockito.verify(errorHandler, Mockito.times(expectedErrors )).handleException(
207 Matchers.any(Throwable.class), Matchers.any(SessionContext.class));
212 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onEchoRequestMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessage)}
217 public void testOnEchoRequestMessage() throws Exception {
218 simulateV13PostHandshakeState(connectionConductor);
220 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
221 EventFactory.DEFAULT_VERSION, new EchoRequestMessageBuilder()));
223 EventFactory.createDefaultWaitForRpcEvent(42, "echoReply"));
228 * Test of handshake, covering version negotiation and features.
229 * Switch delivers first helloMessage with default version.
233 public void testHandshake1() throws Exception {
234 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
235 EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
236 eventPlan.add(0, EventFactory.createDefaultWaitForAllEvent(
237 EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"),
238 EventFactory.createDefaultWaitForRpcEvent(44, "getFeatures")));
239 eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(44,
240 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
242 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(1, "multipartRequestInput"));
243 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(2, "multipartRequestInput"));
244 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(3, "multipartRequestInput"));
245 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(4, "multipartRequestInput"));
248 Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
249 connectionConductor.getConductorState());
250 Assert.assertEquals((short) 0x04, connectionConductor.getVersion()
255 * Test of handshake, covering version negotiation and features.
256 * Controller sends first helloMessage with default version
260 public void testHandshake1SwitchStarts() throws Exception {
261 eventPlan.add(0, EventFactory.createConnectionReadyCallback(connectionConductor));
262 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(21, "helloReply"));
263 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
264 EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
265 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(43, "getFeatures"));
266 eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(43,
267 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
269 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(1, "multipartRequestInput"));
270 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(2, "multipartRequestInput"));
271 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(3, "multipartRequestInput"));
272 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(4, "multipartRequestInput"));
276 Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
277 connectionConductor.getConductorState());
278 Assert.assertEquals((short) 0x04, connectionConductor.getVersion()
283 * Test of handshake, covering version negotiation and features.
284 * Switch delivers first helloMessage with version 0x05
285 * and negotiates following versions: 0x03, 0x01
289 public void testHandshake2() throws Exception {
290 connectionConductor.setBitmapNegotiationEnable(false);
291 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
292 (short) 0x05, new HelloMessageBuilder()));
294 EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
295 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(43L,
296 (short) 0x03, new HelloMessageBuilder()));
298 EventFactory.createDefaultWaitForRpcEvent(44, "helloReply"));
299 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44L,
300 (short) 0x01, new HelloMessageBuilder()));
302 EventFactory.createDefaultWaitForRpcEvent(45, "getFeatures"));
304 eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(45,
305 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
307 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(1, "multipartRequestInput"));
308 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(2, "multipartRequestInput"));
312 Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
313 connectionConductor.getConductorState());
314 Assert.assertEquals((short) 0x01, connectionConductor.getVersion()
319 * Test of handshake, covering version negotiation and features.
320 * Controller sends first helloMessage with default version
321 * and switch negotiates following versions: 0x05, 0x03, 0x01
325 public void testHandshake2SwitchStarts() throws Exception {
326 connectionConductor.setBitmapNegotiationEnable(false);
327 eventPlan.add(0, EventFactory.createConnectionReadyCallback(connectionConductor));
329 EventFactory.createDefaultWaitForRpcEvent(21, "helloReply"));
330 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
331 (short) 0x05, new HelloMessageBuilder()));
332 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(43L,
333 (short) 0x03, new HelloMessageBuilder()));
335 EventFactory.createDefaultWaitForRpcEvent(44, "helloReply"));
336 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44L,
337 (short) 0x01, new HelloMessageBuilder()));
339 EventFactory.createDefaultWaitForRpcEvent(45, "getFeatures"));
341 eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(45,
342 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
344 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(1, "multipartRequestInput"));
345 eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(2, "multipartRequestInput"));
349 Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
350 connectionConductor.getConductorState());
351 Assert.assertEquals((short) 0x01, connectionConductor.getVersion()
357 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage)}
359 * @throws InterruptedException
362 public void testOnExperimenterMessage1() throws InterruptedException {
363 simulateV13PostHandshakeState(connectionConductor);
366 EventFactory.createDefaultWaitForRpcEvent(42, "experimenter"));
367 ExperimenterMessageBuilder builder1 = new ExperimenterMessageBuilder();
368 builder1.setExperimenter(84L).setExpType(4L);
369 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
370 EventFactory.DEFAULT_VERSION, builder1));
374 Runnable sendExperimenterCmd = new Runnable() {
378 ExperimenterInputBuilder builder2 = new ExperimenterInputBuilder();
379 builder2.setExperimenter(84L).setExpType(4L);
380 EventFactory.setupHeader(42L, builder2);
381 adapter.experimenter(builder2.build());
384 pool.schedule(sendExperimenterCmd,
385 ConnectionAdapterStackImpl.JOB_DELAY, TimeUnit.MILLISECONDS);
390 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage)}
392 * @throws InterruptedException
395 public void testOnExperimenterMessage2() throws InterruptedException {
396 simulateV13PostHandshakeState(connectionConductor);
399 EventFactory.createDefaultWaitForRpcEvent(42, "experimenter"));
400 ErrorMessageBuilder builder1 = new ErrorMessageBuilder();
401 builder1.setType(ErrorType.BADREQUEST.getIntValue()).setCode(3)
402 .setData(new byte[] { 1, 2, 3 });
404 eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
405 EventFactory.DEFAULT_VERSION, builder1));
409 Runnable sendExperimenterCmd = new Runnable() {
413 ExperimenterInputBuilder builder2 = new ExperimenterInputBuilder();
414 builder2.setExperimenter(84L).setExpType(4L);
415 EventFactory.setupHeader(42L, builder2);
416 adapter.experimenter(builder2.build());
419 pool.schedule(sendExperimenterCmd,
420 ConnectionAdapterStackImpl.JOB_DELAY, TimeUnit.MILLISECONDS);
425 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onFlowRemovedMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage)}
427 * @throws InterruptedException
430 public void testOnFlowRemovedMessage() throws InterruptedException {
431 IMDMessageTranslator<OfHeader, List<DataObject>> objFms = new FlowRemovedMessageService() ;
432 controller.addMessageTranslator(FlowRemovedMessage.class, 4, objFms);
434 simulateV13PostHandshakeState(connectionConductor);
436 // Now send Flow Removed messages
437 FlowRemovedMessageBuilder builder1 = new FlowRemovedMessageBuilder();
438 builder1.setVersion((short) 4);
440 connectionConductor.onFlowRemovedMessage(builder1.build());
441 synchronized (popListener) {
442 LOG.debug("about to wait for popListener");
443 popListener.wait(maxProcessingTimeout);
445 Assert.assertEquals(1, flowremovedMessageCounter);
447 connectionConductor.onFlowRemovedMessage(builder1.build());
448 synchronized (popListener) {
449 popListener.wait(maxProcessingTimeout);
451 Assert.assertEquals(2, flowremovedMessageCounter);
456 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onMultipartReplyMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage)}
460 public void testOnMultipartReplyMessage() {
461 // fail("Not yet implemented");
467 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPacketInMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage)}
469 * @throws InterruptedException
472 public void testOnPacketInMessage() throws InterruptedException {
473 IMDMessageTranslator<OfHeader, List<DataObject>> objPms = new PacketInMessageService() ;
474 controller.addMessageTranslator(PacketInMessage.class, 4, objPms);
476 simulateV13PostHandshakeState(connectionConductor);
479 PacketInMessageBuilder builder1 = new PacketInMessageBuilder();
480 builder1.setVersion((short) 4);
481 builder1.setBufferId((long)1);
482 connectionConductor.onPacketInMessage(builder1.build());
483 synchronized (popListener) {
484 popListener.wait(maxProcessingTimeout);
486 Assert.assertEquals(1, packetinMessageCounter);
487 builder1.setBufferId((long)2);
488 connectionConductor.onPacketInMessage(builder1.build());
489 synchronized (popListener) {
490 popListener.wait(maxProcessingTimeout);
492 Assert.assertEquals(2, packetinMessageCounter);
497 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPortStatusMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage)}
499 * @throws InterruptedException
502 public void testOnPortStatusMessage() throws InterruptedException {
503 IMDMessageTranslator<OfHeader, List<DataObject>> objPSms = new PortStatusMessageService() ;
504 controller.addMessageTranslator(PortStatusMessage.class, 4, objPSms);
506 simulateV13PostHandshakeState(connectionConductor);
508 // Send Port Status messages
509 PortStatusMessageBuilder builder1 = new PortStatusMessageBuilder();
510 builder1.setVersion((short) 4);
511 PortFeatures features = new PortFeatures(true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false);
512 builder1.setPortNo(90L).setReason(PortReason.OFPPRADD).setCurrentFeatures(features);
513 connectionConductor.onPortStatusMessage(builder1.build());
514 synchronized (popListener) {
515 popListener.wait(maxProcessingTimeout);
517 Assert.assertEquals(1, portstatusAddMessageCounter);
518 builder1.setPortNo(90L).setReason(PortReason.OFPPRMODIFY).setCurrentFeatures(features);
519 connectionConductor.onPortStatusMessage(builder1.build());
520 synchronized (popListener) {
521 popListener.wait(maxProcessingTimeout);
523 Assert.assertEquals(1, portstatusModifyMessageCounter);
524 builder1.setPortNo(90L).setReason(PortReason.OFPPRDELETE).setCurrentFeatures(features);
525 connectionConductor.onPortStatusMessage(builder1.build());
526 synchronized (popListener) {
527 popListener.wait(maxProcessingTimeout);
529 Assert.assertEquals(1, portstatusDeleteMessageCounter);
533 * @throws InterruptedException
535 private void executeLater() throws InterruptedException {
540 * @throws InterruptedException
542 private void executeNow() throws InterruptedException {
544 connectionConductor.shutdownPool();
548 * @throws InterruptedException
550 private void execute(boolean join) throws InterruptedException {
551 libSimulation = new Thread(adapter, "junit-adapter");
552 libSimulation.start();
554 libSimulation.join();
558 private static GetFeaturesOutputBuilder getFeatureResponseMsg() {
559 GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
560 getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
561 getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
562 getFeaturesOutputBuilder.setBuffers(4L);
563 getFeaturesOutputBuilder.setReserved(0L);
564 getFeaturesOutputBuilder.setTables((short) 2);
565 getFeaturesOutputBuilder.setCapabilities(createCapabilities(84));
567 return getFeaturesOutputBuilder;
573 private static Capabilities createCapabilities(long input) {
574 final Boolean FLOW_STATS = (input & (1 << 0)) != 0;
575 final Boolean TABLE_STATS = (input & (1 << 1)) != 0;
576 final Boolean PORT_STATS = (input & (1 << 2)) != 0;
577 final Boolean GROUP_STATS = (input & (1 << 3)) != 0;
578 final Boolean IP_REASM = (input & (1 << 5)) != 0;
579 final Boolean QUEUE_STATS = (input & (1 << 6)) != 0;
580 final Boolean PORT_BLOCKED = (input & (1 << 8)) != 0;
581 Capabilities capabilities = new Capabilities(FLOW_STATS, GROUP_STATS, IP_REASM,
582 PORT_BLOCKED, PORT_STATS, QUEUE_STATS, TABLE_STATS);
586 public class ExperimenterMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
588 public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
589 LOG.debug("Received a packet in Experimenter Service");
590 ConnectionConductorImplTest.this.incrExperimenterMessageCounter();
595 public class PacketInMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
597 public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
598 LOG.debug("Received a packet in PacketIn Service");
599 ConnectionConductorImplTest.this.incrPacketinMessageCounter();
604 public class FlowRemovedMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
606 public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
607 LOG.debug("Received a packet in FlowRemoved Service");
608 ConnectionConductorImplTest.this.incrFlowremovedMessageCounter();
613 public class PortStatusMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
615 public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
616 LOG.debug("Received a packet in PortStatus Service");
617 if ( (((PortStatusMessage)msg).getReason().equals(PortReason.OFPPRADD)) ) {
618 ConnectionConductorImplTest.this.incrPortstatusAddMessageCounter();
619 } else if (((PortStatusMessage)msg).getReason().equals(PortReason.OFPPRDELETE)){
620 ConnectionConductorImplTest.this.incrPortstatusDeleteMessageCounter();
621 } else if (((PortStatusMessage)msg).getReason().equals(PortReason.OFPPRMODIFY)) {
622 ConnectionConductorImplTest.this.incrPortstatusModifyMessageCounter();
628 public class ErrorMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
630 public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
631 LOG.debug("Received a packet in Experimenter Service");
632 ConnectionConductorImplTest.this.incrErrorMessageCounter();
639 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage)}
641 * @throws InterruptedException
644 public void testOnExperimenterMessage() throws InterruptedException {
645 simulateV13PostHandshakeState(connectionConductor);
647 ExperimenterMessageBuilder builder1 = new ExperimenterMessageBuilder();
648 builder1.setVersion((short) 4);
649 builder1.setExperimenter(84L).setExpType(4L);
650 connectionConductor.onExperimenterMessage(builder1.build());
651 synchronized (popListener) {
652 popListener.wait(maxProcessingTimeout);
654 Assert.assertEquals(1, experimenterMessageCounter);
656 builder1.setExperimenter(85L).setExpType(4L);
657 connectionConductor.onExperimenterMessage(builder1.build());
658 synchronized (popListener) {
659 popListener.wait(maxProcessingTimeout);
661 Assert.assertEquals(2, experimenterMessageCounter);
666 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage)}
668 * @throws InterruptedException
671 public void testOnErrorMessage() throws InterruptedException {
672 simulateV13PostHandshakeState(connectionConductor);
674 ErrorMessageBuilder builder1 = new ErrorMessageBuilder();
675 builder1.setVersion((short) 4);
676 builder1.setCode(100);
677 connectionConductor.onErrorMessage(builder1.build());
678 synchronized (popListener) {
679 popListener.wait(maxProcessingTimeout);
681 Assert.assertEquals(1, errorMessageCounter);
682 builder1.setCode(200);
683 connectionConductor.onErrorMessage(builder1.build());
684 synchronized (popListener) {
685 popListener.wait(maxProcessingTimeout);
687 Assert.assertEquals(2, errorMessageCounter);
691 * @return listener mapping for:
693 * <li>experimenter</li>
697 private Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> assembleTranslatorMapping() {
698 Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping = new HashMap<>();
701 IMDMessageTranslator<OfHeader, List<DataObject>> objEms = new ExperimenterMessageService() ;
702 Collection<IMDMessageTranslator<OfHeader, List<DataObject>>> existingValues = new ArrayList<>();
703 existingValues.add(objEms);
704 tKey = new TranslatorKey(4, ExperimenterMessage.class.getName());
705 translatorMapping.put(tKey, existingValues);
706 IMDMessageTranslator<OfHeader, List<DataObject>> objErms = new ErrorMessageService() ;
707 existingValues.add(objErms);
708 tKey = new TranslatorKey(4, ErrorMessage.class.getName());
709 translatorMapping.put(tKey, existingValues);
710 return translatorMapping;
715 * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#processPortStatusMsg(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage)}
717 * Tests for getting features from port status message by port version
719 * <li>features are malformed - one of them is null</li>
720 * <li>mismatch between port version and port features</li>
721 * <li>mismatch between port version and port features</li>
722 * <li>non-existing port version</li>
723 * <li>port version OF 1.0</li>
724 * <li>port version OF 1.3</li>
729 public void testProcessPortStatusMsg() {
730 simulateV13PostHandshakeState(connectionConductor);
732 long portNumber = 90L;
733 long portNumberV10 = 91L;
734 PortStatusMessage msg;
736 PortStatusMessageBuilder builder = new PortStatusMessageBuilder();
737 PortFeatures features = new PortFeatures(true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false);
738 PortFeatures featuresMal = new PortFeatures(true,false,false,false,null,false,false,false,false,false,false,false,false,false,false,false);
739 PortFeaturesV10 featuresV10 = new PortFeaturesV10(true,false,false,false,false,false,false,false,false,false,false,false);
742 builder.setVersion((short) 1).setPortNo(portNumber).setReason(PortReason.OFPPRADD).setCurrentFeatures(featuresMal);
743 connectionConductor.processPortStatusMsg(builder.build());
744 Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
745 Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
747 //Version-features mismatch
748 builder.setCurrentFeatures(features);
749 connectionConductor.processPortStatusMsg(builder.build());
750 Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
751 Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
753 //Non existing version
754 builder.setVersion((short) 0);
755 connectionConductor.processPortStatusMsg(builder.build());
756 Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
757 Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
760 builder.setVersion((short) 4);
761 msg = builder.build();
762 connectionConductor.processPortStatusMsg(builder.build());
763 Assert.assertTrue(connectionConductor.getSessionContext().getPortBandwidth(portNumber));
764 Assert.assertEquals(connectionConductor.getSessionContext().getPhysicalPort(portNumber), msg);
767 builder.setVersion((short) 1).setPortNo(portNumberV10).setCurrentFeatures(null).setCurrentFeaturesV10(featuresV10);
768 msg = builder.build();
769 connectionConductor.processPortStatusMsg(builder.build());
770 Assert.assertTrue(connectionConductor.getSessionContext().getPortBandwidth(portNumberV10));
771 Assert.assertEquals(connectionConductor.getSessionContext().getPhysicalPort(portNumberV10), msg);
774 private void simulateV13PostHandshakeState(ConnectionConductorImpl conductor) {
775 GetFeaturesOutputBuilder featureOutput = getFeatureResponseMsg();
776 conductor.postHandshakeBasic(featureOutput.build(), OFConstants.OFP_VERSION_1_3);