2 * Copyright (c) 2013 IBM Corporation. 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.openflow.md.core.session;
10 import java.math.BigInteger;
11 import java.net.InetSocketAddress;
12 import java.util.HashMap;
13 import java.util.Iterator;
14 import java.util.List;
16 import java.util.Map.Entry;
18 import java.util.concurrent.Future;
19 import org.junit.Assert;
20 import org.junit.Before;
21 import org.junit.Test;
22 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
23 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionReadyListener;
24 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandler;
25 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
26 import org.opendaylight.openflowplugin.api.OFConstants;
27 import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitchRegistration;
28 import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
29 import org.opendaylight.openflowplugin.api.openflow.md.core.ErrorHandler;
30 import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationEnqueuer;
31 import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationQueueWrapper;
32 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
33 import org.opendaylight.openflowplugin.api.openflow.md.core.session.IMessageDispatchService;
34 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
35 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SwitchSessionKeyOF;
36 import org.opendaylight.openflowplugin.api.openflow.md.queue.QueueProcessor;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ControllerRole;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInputBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoReplyInput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterInput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterInputBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncInput;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncInputBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncOutput;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetConfigInput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetConfigInputBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetConfigOutput;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesInput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesInputBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetQueueConfigInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetQueueConfigInputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetQueueConfigOutput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupModInput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MeterModInput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OpenflowProtocolListener;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInputBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortModInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestInput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestInputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SetAsyncInput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SetConfigInput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.TableModInput;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.TableModInputBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
78 import org.opendaylight.yangtools.yang.binding.DataObject;
79 import org.opendaylight.yangtools.yang.common.RpcError;
80 import org.opendaylight.yangtools.yang.common.RpcResult;
83 * test for {@link MessageDispatchServiceImpl}
85 public class MessageDispatchServiceImplTest {
87 MockSessionContext session;
90 * @throws java.lang.Exception
93 public void setUp() throws Exception {
94 session = new MockSessionContext(0);
99 * Test barrier message for null cookie
104 public void testBarrierMessageForPrimary() throws Exception {
105 MockConnectionConductor conductor = new MockConnectionConductor(1);
106 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
107 BarrierInputBuilder barrierMsg = new BarrierInputBuilder();
108 session.getMessageDispatchService().barrier(barrierMsg.build(), cookie);
109 Assert.assertEquals(MessageType.BARRIER, session.getPrimaryConductor()
114 * Test experimenter message for null cookie
117 public void testExperimenter() {
118 MockConnectionConductor conductor = new MockConnectionConductor(1);
119 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
120 ExperimenterInputBuilder experimenterInputBuilder = new ExperimenterInputBuilder();
121 session.getMessageDispatchService().experimenter(
122 experimenterInputBuilder.build(), cookie);
123 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor()
128 * Test get async input with null cookie
131 public void testGetAsync() {
132 MockConnectionConductor conductor = new MockConnectionConductor(1);
133 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
134 GetAsyncInputBuilder getAsyncInputBuilder = new GetAsyncInputBuilder();
135 session.getMessageDispatchService().getAsync(
136 getAsyncInputBuilder.build(), cookie);
137 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor()
142 * Test get async output with null cookie
145 public void testGetConfig() {
146 MockConnectionConductor conductor = new MockConnectionConductor(1);
147 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
148 GetConfigInputBuilder getConfigInputBuilder = new GetConfigInputBuilder();
149 session.getMessageDispatchService().getConfig(
150 getConfigInputBuilder.build(), cookie);
151 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor()
156 * Test get features with null cookie
159 public void testGetFeatures() {
160 MockConnectionConductor conductor = new MockConnectionConductor(1);
161 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
162 GetFeaturesInputBuilder getFeaturesInputBuilder = new GetFeaturesInputBuilder();
163 session.getMessageDispatchService().getFeatures(
164 getFeaturesInputBuilder.build(), cookie);
165 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor()
170 * Test get queue config with null cookie
173 public void testGetQueueConfig() {
174 MockConnectionConductor conductor = new MockConnectionConductor(1);
175 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
176 GetQueueConfigInputBuilder getQueueConfigInputBuilder = new GetQueueConfigInputBuilder();
177 session.getMessageDispatchService().getQueueConfig(
178 getQueueConfigInputBuilder.build(), cookie);
179 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor()
184 * Test multipart request with null cookie
187 public void testGetMultipart() {
188 MockConnectionConductor conductor = new MockConnectionConductor(1);
189 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
190 MultipartRequestInputBuilder multipartRequestInputBuilder = new MultipartRequestInputBuilder();
191 session.getMessageDispatchService().multipartRequest(
192 multipartRequestInputBuilder.build(), cookie);
193 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor()
198 * Test role request with null cookie
201 public void testRoleRequest() {
202 MockConnectionConductor conductor = new MockConnectionConductor(1);
203 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
204 RoleRequestInputBuilder roleRequestInputBuilder = new RoleRequestInputBuilder();
205 session.getMessageDispatchService().roleRequest(
206 roleRequestInputBuilder.build(), cookie);
207 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor()
212 * Test table mod with null cookie
215 public void testTableMod() {
216 MockConnectionConductor conductor = new MockConnectionConductor(1);
217 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
218 TableModInputBuilder tableModInputBuilder = new TableModInputBuilder();
219 session.getMessageDispatchService().tableMod(
220 tableModInputBuilder.build(), cookie);
221 Assert.assertEquals(MessageType.TABLEMOD, session.getPrimaryConductor()
226 * Test packet out message for primary connection
231 public void testPacketOutMessageForPrimary() throws Exception {
232 session.getMessageDispatchService().packetOut(null, null);
233 Assert.assertEquals(MessageType.PACKETOUT, session
234 .getPrimaryConductor().getMessageType());
238 * Test packet out message for auxiliary connection
243 public void testPacketOutMessageForAuxiliary() throws Exception {
244 MockConnectionConductor conductor = new MockConnectionConductor(1);
245 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
246 session.addAuxiliaryConductor(cookie, conductor);
247 session.getMessageDispatchService().packetOut(null, cookie);
248 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor()
250 conductor = (MockConnectionConductor) session
251 .getAuxiliaryConductor(cookie);
252 Assert.assertEquals(MessageType.PACKETOUT, conductor.getMessageType());
256 * Test packet out message when multiple auxiliary connection exist
261 public void testPacketOutMessageForMultipleAuxiliary() throws Exception {
262 MockConnectionConductor conductor1 = new MockConnectionConductor(1);
263 SwitchConnectionDistinguisher cookie1 = conductor1.getAuxiliaryKey();
264 session.addAuxiliaryConductor(cookie1, conductor1);
265 MockConnectionConductor conductor2 = new MockConnectionConductor(2);
266 SwitchConnectionDistinguisher cookie2 = conductor2.getAuxiliaryKey();
267 session.addAuxiliaryConductor(cookie2, conductor2);
268 MockConnectionConductor conductor3 = new MockConnectionConductor(3);
269 SwitchConnectionDistinguisher cookie3 = conductor3.getAuxiliaryKey();
270 session.addAuxiliaryConductor(cookie3, conductor3);
271 PacketOutInputBuilder builder = new PacketOutInputBuilder();
273 session.getMessageDispatchService().packetOut(builder.build(), cookie2);
275 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor()
278 conductor3 = (MockConnectionConductor) session
279 .getAuxiliaryConductor(cookie3);
280 Assert.assertEquals(MessageType.NONE, conductor3.getMessageType());
282 conductor2 = (MockConnectionConductor) session
283 .getAuxiliaryConductor(cookie2);
284 Assert.assertEquals(MessageType.PACKETOUT, conductor2.getMessageType());
286 conductor1 = (MockConnectionConductor) session
287 .getAuxiliaryConductor(cookie1);
288 Assert.assertEquals(MessageType.NONE, conductor1.getMessageType());
293 * Test for invalid session
298 public void testInvalidSession() throws Exception {
299 session.setValid(false);
300 Future<RpcResult<Void>> resultFuture = session
301 .getMessageDispatchService().packetOut(null, null);
302 if (resultFuture.isDone()) {
303 RpcResult<Void> rpcResult = resultFuture.get();
304 Assert.assertTrue(!rpcResult.getErrors().isEmpty());
306 Iterator<RpcError> it = rpcResult.getErrors().iterator();
307 RpcError rpcError = it.next();
309 Assert.assertTrue(rpcError.getApplicationTag().equals(
310 OFConstants.APPLICATION_TAG));
311 Assert.assertTrue(rpcError.getTag().equals(
312 OFConstants.ERROR_TAG_TIMEOUT));
313 Assert.assertTrue(rpcError.getErrorType().equals(
314 RpcError.ErrorType.TRANSPORT));
320 class MockSessionContext implements SessionContext {
321 private MockConnectionConductor conductor;
322 private Map<SwitchConnectionDistinguisher, ConnectionConductor> map;
323 private IMessageDispatchService messageService;
324 private boolean isValid = true;
325 private ModelDrivenSwitchRegistration registration;
327 private SwitchSessionKeyOF sessionKey;
329 MockSessionContext(int conductorNum) {
330 conductor = new MockConnectionConductor(conductorNum);
331 map = new HashMap<>();
332 messageService = new MessageDispatchServiceImpl(this);
333 sessionKey = new SwitchSessionKeyOF();
334 sessionKey.setDatapathId(new BigInteger("0"));
338 public MockConnectionConductor getPrimaryConductor() {
339 // TODO Auto-generated method stub
344 public GetFeaturesOutput getFeatures() {
345 // TODO Auto-generated method stub
350 public ConnectionConductor getAuxiliaryConductor(
351 SwitchConnectionDistinguisher auxiliaryKey) {
353 return map.get(auxiliaryKey);
357 public Set<Entry<SwitchConnectionDistinguisher, ConnectionConductor>> getAuxiliaryConductors() {
358 // TODO Auto-generated method stub
363 public void addAuxiliaryConductor(
364 SwitchConnectionDistinguisher auxiliaryKey,
365 ConnectionConductor conductorArg) {
366 map.put(auxiliaryKey, conductorArg);
370 public ConnectionConductor removeAuxiliaryConductor(
371 SwitchConnectionDistinguisher connectionCookie) {
372 return map.remove(connectionCookie);
376 public boolean isValid() {
377 // TODO Auto-generated method stub
382 public void setValid(boolean valid) {
387 public SwitchSessionKeyOF getSessionKey() {
392 public IMessageDispatchService getMessageDispatchService() {
393 // TODO Auto-generated method stub
394 return messageService;
398 public Long getNextXid() {
399 // TODO Auto-generated method stub
404 public Map<Long, PortGrouping> getPhysicalPorts() {
405 // TODO Auto-generated method stub
410 public Set<Long> getPorts() {
411 // TODO Auto-generated method stub
416 public PortGrouping getPhysicalPort(Long portNumber) {
417 // TODO Auto-generated method stub
422 public Boolean getPortBandwidth(Long portNumber) {
423 // TODO Auto-generated method stub
428 public boolean isPortEnabled(long portNumber) {
429 // TODO Auto-generated method stub
434 public boolean isPortEnabled(PortGrouping port) {
435 // TODO Auto-generated method stub
440 public List<PortGrouping> getEnabledPorts() {
441 // TODO Auto-generated method stub
446 public Map<Long, Boolean> getPortsBandwidth() {
447 // TODO Auto-generated method stub
452 public ModelDrivenSwitchRegistration getProviderRegistration() {
457 public void setProviderRegistration(ModelDrivenSwitchRegistration registration) {
458 this.registration = registration;
462 public int getSeed() {
470 public void setSeed(int seed) {
475 public NotificationEnqueuer getNotificationEnqueuer() {
480 public ControllerRole getRoleOnDevice() {
485 public void setRoleOnDevice(ControllerRole roleOnDevice) {
490 class MockConnectionConductor implements ConnectionConductor,
491 NotificationEnqueuer {
493 private int conductorNum;
494 private MockConnectionAdapter adapter;
496 public MockConnectionConductor(int conductorNumber) {
497 conductorNum = conductorNumber;
498 adapter = new MockConnectionAdapter();
503 // TODO Auto-generated method stub
508 public Short getVersion() {
509 // TODO Auto-generated method stub
514 public CONDUCTOR_STATE getConductorState() {
515 // TODO Auto-generated method stub
520 public void setConductorState(CONDUCTOR_STATE conductorState) {
521 // TODO Auto-generated method stub
526 public Future<Boolean> disconnect() {
527 // TODO Auto-generated method stub
532 public void setSessionContext(SessionContext context) {
533 // TODO Auto-generated method stub
538 public void setConnectionCookie(SwitchConnectionDistinguisher auxiliaryKey) {
539 // TODO Auto-generated method stub
544 public SessionContext getSessionContext() {
545 // TODO Auto-generated method stub
550 public SwitchConnectionDistinguisher getAuxiliaryKey() {
551 if (0 != conductorNum) {
552 SwitchConnectionCookieOFImpl key = new SwitchConnectionCookieOFImpl();
553 key.setAuxiliaryId((short) conductorNum);
561 public ConnectionAdapter getConnectionAdapter() {
562 // TODO Auto-generated method stub
566 public MessageType getMessageType() {
567 return adapter.getMessageType();
571 public void setQueueProcessor(
572 QueueProcessor<OfHeader, DataObject> queueKeeper) {
577 public void setErrorHandler(ErrorHandler errorHandler) {
582 public void setId(int conductorId) {
587 public void enqueueNotification(NotificationQueueWrapper notification) {
593 NONE, BARRIER, FLOWMOD, TABLEMOD, PACKETOUT;
596 class MockConnectionAdapter implements ConnectionAdapter {
598 private MessageType messageType;
599 private ConnectionReadyListener connectionReadyListener;
600 private boolean packetInFiltering;
602 public MockConnectionAdapter() {
603 setMessageType(MessageType.NONE);
607 public Future<RpcResult<BarrierOutput>> barrier(BarrierInput input) {
608 setMessageType(MessageType.BARRIER);
613 public Future<RpcResult<EchoOutput>> echo(EchoInput input) {
614 // TODO Auto-generated method stub
619 public Future<RpcResult<Void>> echoReply(EchoReplyInput input) {
620 // TODO Auto-generated method stub
625 public Future<RpcResult<Void>> experimenter(ExperimenterInput input) {
626 // TODO Auto-generated method stub
631 public Future<RpcResult<Void>> flowMod(FlowModInput input) {
632 setMessageType(MessageType.FLOWMOD);
637 public Future<RpcResult<GetAsyncOutput>> getAsync(GetAsyncInput input) {
638 // TODO Auto-generated method stub
643 public Future<RpcResult<GetConfigOutput>> getConfig(GetConfigInput input) {
644 // TODO Auto-generated method stub
649 public Future<RpcResult<GetFeaturesOutput>> getFeatures(
650 GetFeaturesInput input) {
651 // TODO Auto-generated method stub
656 public Future<RpcResult<GetQueueConfigOutput>> getQueueConfig(
657 GetQueueConfigInput input) {
658 // TODO Auto-generated method stub
663 public Future<RpcResult<Void>> groupMod(GroupModInput input) {
664 // TODO Auto-generated method stub
669 public Future<RpcResult<Void>> hello(HelloInput input) {
670 // TODO Auto-generated method stub
675 public Future<RpcResult<Void>> meterMod(MeterModInput input) {
676 // TODO Auto-generated method stub
681 public Future<RpcResult<Void>> packetOut(PacketOutInput input) {
682 setMessageType(MessageType.PACKETOUT);
687 public Future<RpcResult<Void>> portMod(PortModInput input) {
688 // TODO Auto-generated method stub
693 public Future<RpcResult<RoleRequestOutput>> roleRequest(
694 RoleRequestInput input) {
695 // TODO Auto-generated method stub
700 public Future<RpcResult<Void>> setAsync(SetAsyncInput input) {
701 // TODO Auto-generated method stub
706 public Future<RpcResult<Void>> setConfig(SetConfigInput input) {
707 // TODO Auto-generated method stub
712 public Future<RpcResult<Void>> tableMod(TableModInput input) {
713 setMessageType(MessageType.TABLEMOD);
718 public Future<Boolean> disconnect() {
719 // TODO Auto-generated method stub
724 public boolean isAlive() {
725 // TODO Auto-generated method stub
730 public void setMessageListener(OpenflowProtocolListener messageListener) {
731 // TODO Auto-generated method stub
736 public void setSystemListener(SystemNotificationsListener systemListener) {
737 // TODO Auto-generated method stub
742 public void checkListeners() {
743 // TODO Auto-generated method stub
748 * @return the messageType
750 public MessageType getMessageType() {
756 * the messageType to set
758 public void setMessageType(MessageType messageType) {
759 this.messageType = messageType;
763 public void fireConnectionReadyNotification() {
764 connectionReadyListener.onConnectionReady();
768 public void setConnectionReadyListener(
769 ConnectionReadyListener connectionReadyListener) {
770 this.connectionReadyListener = connectionReadyListener;
774 public Future<RpcResult<Void>> multipartRequest(MultipartRequestInput input) {
775 // TODO Auto-generated method stub
783 * org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter
784 * #getRemoteAddress()
787 public InetSocketAddress getRemoteAddress() {
788 // TODO Auto-generated method stub
793 public boolean isAutoRead() {
794 // TODO Auto-generated method stub
799 public <T extends OutboundQueueHandler> OutboundQueueHandlerRegistration<T> registerOutboundQueueHandler(final T t, final int i, final long l) {
804 public void setAutoRead(boolean arg0) {
805 // TODO Auto-generated method stub
810 public void setPacketInFiltering(boolean packetInFiltering) {
811 this.packetInFiltering = packetInFiltering;