2 * Copyright IBM Corporation, 2013. 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.ExecutionException;
19 import java.util.concurrent.Future;
21 import org.junit.Assert;
22 import org.junit.Before;
23 import org.junit.Test;
24 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
25 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionReadyListener;
26 import org.opendaylight.openflowplugin.api.openflow.md.core.session.IMessageDispatchService;
27 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
28 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SwitchSessionKeyOF;
29 import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitch;
30 import org.opendaylight.openflowplugin.api.OFConstants;
31 import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
32 import org.opendaylight.openflowplugin.api.openflow.md.core.ErrorHandler;
33 import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationEnqueuer;
34 import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationQueueWrapper;
35 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
36 import org.opendaylight.openflowplugin.api.openflow.md.queue.QueueProcessor;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInputBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoReplyInput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterInput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterInputBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncInput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncInputBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncOutput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetConfigInput;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetConfigInputBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetConfigOutput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesInput;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesInputBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetQueueConfigInput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetQueueConfigInputBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetQueueConfigOutput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupModInput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloInput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MeterModInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OpenflowProtocolListener;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInputBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortModInput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestInputBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutput;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SetAsyncInput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SetConfigInput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.TableModInput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.TableModInputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
77 import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
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().getMessageType());
113 * Test experimenter message for null cookie
116 public void testExperimenter() {
117 MockConnectionConductor conductor = new MockConnectionConductor(1);
118 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
119 ExperimenterInputBuilder experimenterInputBuilder = new ExperimenterInputBuilder();
120 session.getMessageDispatchService().experimenter(experimenterInputBuilder.build(), cookie);
121 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor().getMessageType());
125 * Test get async input with null cookie
128 public void testGetAsync() throws ExecutionException, InterruptedException {
129 MockConnectionConductor conductor = new MockConnectionConductor(1);
130 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
131 GetAsyncInputBuilder getAsyncInputBuilder = new GetAsyncInputBuilder();
132 session.getMessageDispatchService().getAsync(getAsyncInputBuilder.build(), cookie);
133 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor().getMessageType());
137 * Test get async output with null cookie
140 public void testGetConfig() {
141 MockConnectionConductor conductor = new MockConnectionConductor(1);
142 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
143 GetConfigInputBuilder getConfigInputBuilder = new GetConfigInputBuilder();
144 session.getMessageDispatchService().getConfig(getConfigInputBuilder.build(), cookie);
145 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor().getMessageType());
149 * Test get features with null cookie
152 public void testGetFeatures() {
153 MockConnectionConductor conductor = new MockConnectionConductor(1);
154 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
155 GetFeaturesInputBuilder getFeaturesInputBuilder = new GetFeaturesInputBuilder();
156 session.getMessageDispatchService().getFeatures(getFeaturesInputBuilder.build(), cookie);
157 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor().getMessageType());
161 * Test get queue config with null cookie
164 public void testGetQueueConfig() {
165 MockConnectionConductor conductor = new MockConnectionConductor(1);
166 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
167 GetQueueConfigInputBuilder getQueueConfigInputBuilder = new GetQueueConfigInputBuilder();
168 session.getMessageDispatchService().getQueueConfig(getQueueConfigInputBuilder.build(), cookie);
169 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor().getMessageType());
173 * Test multipart request with null cookie
176 public void testGetMultipart() {
177 MockConnectionConductor conductor = new MockConnectionConductor(1);
178 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
179 MultipartRequestInputBuilder multipartRequestInputBuilder = new MultipartRequestInputBuilder();
180 session.getMessageDispatchService().multipartRequest(multipartRequestInputBuilder.build(), cookie);
181 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor().getMessageType());
185 * Test role request with null cookie
188 public void testRoleRequest() {
189 MockConnectionConductor conductor = new MockConnectionConductor(1);
190 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
191 RoleRequestInputBuilder roleRequestInputBuilder = new RoleRequestInputBuilder();
192 session.getMessageDispatchService().roleRequest(roleRequestInputBuilder.build(), cookie);
193 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor().getMessageType());
197 * Test table mod with null cookie
200 public void testTableMod() {
201 MockConnectionConductor conductor = new MockConnectionConductor(1);
202 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
203 TableModInputBuilder tableModInputBuilder = new TableModInputBuilder();
204 session.getMessageDispatchService().tableMod(tableModInputBuilder.build(), cookie);
205 Assert.assertEquals(MessageType.TABLEMOD, session.getPrimaryConductor().getMessageType());
210 * Test packet out message for primary connection
215 public void testPacketOutMessageForPrimary() throws Exception {
216 session.getMessageDispatchService().packetOut(null, null);
217 Assert.assertEquals(MessageType.PACKETOUT, session.getPrimaryConductor().getMessageType());
221 * Test packet out message for auxiliary connection
226 public void testPacketOutMessageForAuxiliary() throws Exception {
227 MockConnectionConductor conductor = new MockConnectionConductor(1);
228 SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
229 session.addAuxiliaryConductor(cookie, conductor);
230 session.getMessageDispatchService().packetOut(null, cookie);
231 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor().getMessageType());
232 conductor = (MockConnectionConductor) session.getAuxiliaryConductor(cookie);
233 Assert.assertEquals(MessageType.PACKETOUT, conductor.getMessageType());
237 * Test packet out message when multiple auxiliary connection exist
242 public void testPacketOutMessageForMultipleAuxiliary() throws Exception {
243 MockConnectionConductor conductor1 = new MockConnectionConductor(1);
244 SwitchConnectionDistinguisher cookie1 = conductor1.getAuxiliaryKey();
245 session.addAuxiliaryConductor(cookie1, conductor1);
246 MockConnectionConductor conductor2 = new MockConnectionConductor(2);
247 SwitchConnectionDistinguisher cookie2 = conductor2.getAuxiliaryKey();
248 session.addAuxiliaryConductor(cookie2, conductor2);
249 MockConnectionConductor conductor3 = new MockConnectionConductor(3);
250 SwitchConnectionDistinguisher cookie3 = conductor3.getAuxiliaryKey();
251 session.addAuxiliaryConductor(cookie3, conductor3);
252 PacketOutInputBuilder builder = new PacketOutInputBuilder();
254 session.getMessageDispatchService().packetOut(builder.build(), cookie2);
256 Assert.assertEquals(MessageType.NONE, session.getPrimaryConductor().getMessageType());
258 conductor3 = (MockConnectionConductor) session.getAuxiliaryConductor(cookie3);
259 Assert.assertEquals(MessageType.NONE, conductor3.getMessageType());
261 conductor2 = (MockConnectionConductor) session.getAuxiliaryConductor(cookie2);
262 Assert.assertEquals(MessageType.PACKETOUT, conductor2.getMessageType());
264 conductor1 = (MockConnectionConductor) session.getAuxiliaryConductor(cookie1);
265 Assert.assertEquals(MessageType.NONE, conductor1.getMessageType());
270 * Test for invalid session
275 public void testInvalidSession() throws Exception {
276 session.setValid(false);
277 Future<RpcResult<Void>> resultFuture = session.getMessageDispatchService().packetOut(null, null);
278 if (resultFuture.isDone()) {
279 RpcResult<Void> rpcResult = resultFuture.get();
280 Assert.assertTrue(!rpcResult.getErrors().isEmpty());
282 Iterator<RpcError> it = rpcResult.getErrors().iterator();
283 RpcError rpcError = it.next();
285 Assert.assertTrue(rpcError.getApplicationTag().equals(OFConstants.APPLICATION_TAG));
286 Assert.assertTrue(rpcError.getTag().equals(OFConstants.ERROR_TAG_TIMEOUT));
287 Assert.assertTrue(rpcError.getErrorType().equals(RpcError.ErrorType.TRANSPORT));
293 class MockSessionContext implements SessionContext {
294 private MockConnectionConductor conductor;
295 private Map<SwitchConnectionDistinguisher, ConnectionConductor> map;
296 private IMessageDispatchService messageService;
297 private boolean isValid = true;
298 private CompositeObjectRegistration<ModelDrivenSwitch> registration;
300 private SwitchSessionKeyOF sessionKey;
302 MockSessionContext(int conductorNum) {
303 conductor = new MockConnectionConductor(conductorNum);
304 map = new HashMap<SwitchConnectionDistinguisher, ConnectionConductor>();
305 messageService = new MessageDispatchServiceImpl(this);
306 sessionKey = new SwitchSessionKeyOF();
307 sessionKey.setDatapathId(new BigInteger("0"));
311 public MockConnectionConductor getPrimaryConductor() {
312 // TODO Auto-generated method stub
317 public GetFeaturesOutput getFeatures() {
318 // TODO Auto-generated method stub
323 public ConnectionConductor getAuxiliaryConductor(SwitchConnectionDistinguisher auxiliaryKey) {
325 return map.get(auxiliaryKey);
329 public Set<Entry<SwitchConnectionDistinguisher, ConnectionConductor>> getAuxiliaryConductors() {
330 // TODO Auto-generated method stub
335 public void addAuxiliaryConductor(SwitchConnectionDistinguisher auxiliaryKey, ConnectionConductor conductorArg) {
336 map.put(auxiliaryKey, conductorArg);
340 public ConnectionConductor removeAuxiliaryConductor(SwitchConnectionDistinguisher connectionCookie) {
341 return map.remove(connectionCookie);
345 public boolean isValid() {
346 // TODO Auto-generated method stub
351 public void setValid(boolean valid) {
356 public SwitchSessionKeyOF getSessionKey() {
361 public IMessageDispatchService getMessageDispatchService() {
362 // TODO Auto-generated method stub
363 return messageService;
367 public Long getNextXid() {
368 // TODO Auto-generated method stub
373 public Map<Long, PortGrouping> getPhysicalPorts() {
374 // TODO Auto-generated method stub
379 public Set<Long> getPorts() {
380 // TODO Auto-generated method stub
385 public PortGrouping getPhysicalPort(Long portNumber) {
386 // TODO Auto-generated method stub
391 public Boolean getPortBandwidth(Long portNumber) {
392 // TODO Auto-generated method stub
397 public boolean isPortEnabled(long portNumber) {
398 // TODO Auto-generated method stub
403 public boolean isPortEnabled(PortGrouping port) {
404 // TODO Auto-generated method stub
409 public List<PortGrouping> getEnabledPorts() {
410 // TODO Auto-generated method stub
415 public Map<Long, Boolean> getPortsBandwidth() {
416 // TODO Auto-generated method stub
421 public CompositeObjectRegistration<ModelDrivenSwitch> getProviderRegistration() {
426 public void setProviderRegistration(
427 CompositeObjectRegistration<ModelDrivenSwitch> registration) {
428 this.registration = registration;
432 public int getSeed() {
437 * @param seed the seed to set
439 public void setSeed(int seed) {
444 public NotificationEnqueuer getNotificationEnqueuer() {
449 class MockConnectionConductor implements ConnectionConductor, NotificationEnqueuer {
451 private int conductorNum;
452 private MockConnectionAdapter adapter;
454 public MockConnectionConductor(int conductorNumber) {
455 conductorNum = conductorNumber;
456 adapter = new MockConnectionAdapter();
461 // TODO Auto-generated method stub
466 public Short getVersion() {
467 // TODO Auto-generated method stub
472 public CONDUCTOR_STATE getConductorState() {
473 // TODO Auto-generated method stub
478 public void setConductorState(CONDUCTOR_STATE conductorState) {
479 // TODO Auto-generated method stub
484 public Future<Boolean> disconnect() {
485 // TODO Auto-generated method stub
490 public void setSessionContext(SessionContext context) {
491 // TODO Auto-generated method stub
496 public void setConnectionCookie(SwitchConnectionDistinguisher auxiliaryKey) {
497 // TODO Auto-generated method stub
502 public SessionContext getSessionContext() {
503 // TODO Auto-generated method stub
508 public SwitchConnectionDistinguisher getAuxiliaryKey() {
509 if (0 != conductorNum) {
510 SwitchConnectionCookieOFImpl key = new SwitchConnectionCookieOFImpl();
511 key.setAuxiliaryId((short) conductorNum);
519 public ConnectionAdapter getConnectionAdapter() {
520 // TODO Auto-generated method stub
524 public MessageType getMessageType() {
525 return adapter.getMessageType();
529 public void setQueueProcessor(QueueProcessor<OfHeader, DataObject> queueKeeper) {
534 public void setErrorHandler(ErrorHandler errorHandler) {
539 public void setId(int conductorId) {
544 public void enqueueNotification(NotificationQueueWrapper notification) {
550 NONE, BARRIER, FLOWMOD, TABLEMOD, PACKETOUT;
553 class MockConnectionAdapter implements ConnectionAdapter {
555 private MessageType messageType;
556 private ConnectionReadyListener connectionReadyListener;
558 public MockConnectionAdapter() {
559 setMessageType(MessageType.NONE);
563 public Future<RpcResult<BarrierOutput>> barrier(BarrierInput input) {
564 setMessageType(MessageType.BARRIER);
569 public Future<RpcResult<EchoOutput>> echo(EchoInput input) {
570 // TODO Auto-generated method stub
575 public Future<RpcResult<Void>> echoReply(EchoReplyInput input) {
576 // TODO Auto-generated method stub
581 public Future<RpcResult<Void>> experimenter(ExperimenterInput input) {
582 // TODO Auto-generated method stub
587 public Future<RpcResult<Void>> flowMod(FlowModInput input) {
588 setMessageType(MessageType.FLOWMOD);
593 public Future<RpcResult<GetAsyncOutput>> getAsync(GetAsyncInput input) {
594 // TODO Auto-generated method stub
599 public Future<RpcResult<GetConfigOutput>> getConfig(GetConfigInput input) {
600 // TODO Auto-generated method stub
605 public Future<RpcResult<GetFeaturesOutput>> getFeatures(GetFeaturesInput input) {
606 // TODO Auto-generated method stub
611 public Future<RpcResult<GetQueueConfigOutput>> getQueueConfig(GetQueueConfigInput input) {
612 // TODO Auto-generated method stub
617 public Future<RpcResult<Void>> groupMod(GroupModInput input) {
618 // TODO Auto-generated method stub
623 public Future<RpcResult<Void>> hello(HelloInput input) {
624 // TODO Auto-generated method stub
629 public Future<RpcResult<Void>> meterMod(MeterModInput input) {
630 // TODO Auto-generated method stub
635 public Future<RpcResult<Void>> packetOut(PacketOutInput input) {
636 setMessageType(MessageType.PACKETOUT);
641 public Future<RpcResult<Void>> portMod(PortModInput input) {
642 // TODO Auto-generated method stub
647 public Future<RpcResult<RoleRequestOutput>> roleRequest(RoleRequestInput input) {
648 // TODO Auto-generated method stub
653 public Future<RpcResult<Void>> setAsync(SetAsyncInput input) {
654 // TODO Auto-generated method stub
659 public Future<RpcResult<Void>> setConfig(SetConfigInput input) {
660 // TODO Auto-generated method stub
665 public Future<RpcResult<Void>> tableMod(TableModInput input) {
666 setMessageType(MessageType.TABLEMOD);
671 public Future<Boolean> disconnect() {
672 // TODO Auto-generated method stub
677 public boolean isAlive() {
678 // TODO Auto-generated method stub
683 public void setMessageListener(OpenflowProtocolListener messageListener) {
684 // TODO Auto-generated method stub
689 public void setSystemListener(SystemNotificationsListener systemListener) {
690 // TODO Auto-generated method stub
695 public void checkListeners() {
696 // TODO Auto-generated method stub
701 * @return the messageType
703 public MessageType getMessageType() {
708 * @param messageType the messageType to set
710 public void setMessageType(MessageType messageType) {
711 this.messageType = messageType;
715 public void fireConnectionReadyNotification() {
716 connectionReadyListener.onConnectionReady();
720 public void setConnectionReadyListener(
721 ConnectionReadyListener connectionReadyListener) {
722 this.connectionReadyListener = connectionReadyListener;
726 public Future<RpcResult<Void>> multipartRequest(
727 MultipartRequestInput input) {
728 // TODO Auto-generated method stub
733 * @see org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter#getRemoteAddress()
736 public InetSocketAddress getRemoteAddress() {
737 // TODO Auto-generated method stub