Merge "copyright header added"
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / session / MessageDispatchServiceImpl.java
1 /**
2  * Copyright IBM Corporation, 2013.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.openflowplugin.openflow.md.core.session;
9
10 import java.math.BigInteger;
11 import java.util.Collection;
12 import java.util.Collections;
13 import java.util.concurrent.Future;
14
15 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
16  import org.opendaylight.controller.sal.common.util.Rpcs;
17 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
18 import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
19 import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutputBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutputBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutput;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutputBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInputBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncOutput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetConfigInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetConfigOutput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetQueueConfigInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetQueueConfigOutput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupModInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupModInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MeterModInput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MeterModInputBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortModInput;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestInput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutput;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SetAsyncInput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SetConfigInput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.TableModInput;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortOutput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortOutputBuilder;
55 import org.opendaylight.yangtools.yang.common.RpcError;
56 import org.opendaylight.yangtools.yang.common.RpcResult;
57 import org.slf4j.Logger;
58 import org.slf4j.LoggerFactory;
59
60 import com.google.common.util.concurrent.Futures;
61
62 /**
63  * message dispatch service to send the message to switch.
64  *
65  * @author AnilGujele
66  *
67  */
68 public class MessageDispatchServiceImpl implements IMessageDispatchService {
69
70     private static final Logger LOG = LoggerFactory.getLogger(MessageDispatchServiceImpl.class);
71
72     private SessionContext session;    
73
74     /**
75      * constructor
76      *
77      * @param session
78      *            - MessageDispatchService for this session
79      */
80     public MessageDispatchServiceImpl(SessionContext session) {
81         this.session = session;        
82     }
83
84     /**
85      * get proper connection adapter to send the message to switch.
86      *
87      * @param cookie to identify the right connection, it can be null also.
88      * @return connectionAdapter associated with cookie, otherwise return best
89      *         suitable connection.
90      *
91      */
92
93     private ConnectionAdapter getConnectionAdapter(SwitchConnectionDistinguisher cookie) {
94
95         if (!session.isValid()) {
96             LOG.warn("Session for the cookie {} is invalid.", cookie);
97             throw new IllegalArgumentException("Session for the cookie is invalid.");
98         }
99         LOG.debug("finding connecton for cookie value {}. ", cookie);
100         // set main connection as default
101         ConnectionAdapter connectionAdapter = session.getPrimaryConductor().getConnectionAdapter();
102         if (null != cookie) {
103             ConnectionConductor conductor = session.getAuxiliaryConductor(cookie);
104             // check if auxiliary connection exist
105             if (null != conductor) {
106                 LOG.debug("found auxiliary connection for the cookie.");
107                 connectionAdapter = conductor.getConnectionAdapter();
108             }
109         } else {
110             // TODO: pick connection to utilize all the available connection.
111         }
112         return connectionAdapter;
113     }
114
115     @Override
116     public Future<RpcResult<BarrierOutput>> barrier(BarrierInput input, SwitchConnectionDistinguisher cookie) {  
117         return getConnectionAdapter(cookie).barrier(input);
118     }
119
120     @Override
121     public Future<RpcResult<Void>> experimenter(ExperimenterInput input, SwitchConnectionDistinguisher cookie) {
122         return getConnectionAdapter(cookie).experimenter(input);
123     }
124
125     @Override
126     public Future<RpcResult<UpdateFlowOutput>> flowMod(FlowModInput input, SwitchConnectionDistinguisher cookie) {
127         LOG.debug("Calling OFLibrary flowMod");
128         Future<RpcResult<Void>> response = getConnectionAdapter(cookie).flowMod(input);
129
130         // Send the same Xid back to caller - MessageDrivenSwitch
131         UpdateFlowOutputBuilder flowModOutput = new UpdateFlowOutputBuilder();        
132         BigInteger bigIntXid = BigInteger.valueOf(input.getXid()) ;
133         flowModOutput.setTransactionId(new TransactionId(bigIntXid));
134
135         UpdateFlowOutput result = flowModOutput.build();
136         Collection<RpcError> errors = Collections.emptyList();
137         RpcResult<UpdateFlowOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
138
139         // solution 1: sending directly and hooking listener to get error
140         // hookup listener to catch the possible error with no reference to returned future-object
141         LOG.debug("Returning to ModelDrivenSwitch for flowMod RPC");
142         return Futures.immediateFuture(rpcResult);
143
144     }
145
146     @Override
147     public Future<RpcResult<GetAsyncOutput>> getAsync(GetAsyncInput input, SwitchConnectionDistinguisher cookie) {
148         return getConnectionAdapter(cookie).getAsync(input);
149     }
150
151     @Override
152     public Future<RpcResult<GetConfigOutput>> getConfig(GetConfigInput input, SwitchConnectionDistinguisher cookie) {
153         return getConnectionAdapter(cookie).getConfig(input);
154     }
155
156     @Override
157     public Future<RpcResult<GetFeaturesOutput>> getFeatures(GetFeaturesInput input, SwitchConnectionDistinguisher cookie) {
158         return getConnectionAdapter(cookie).getFeatures(input);
159     }
160
161     @Override
162     public Future<RpcResult<GetQueueConfigOutput>> getQueueConfig(GetQueueConfigInput input,
163             SwitchConnectionDistinguisher cookie) {
164         return getConnectionAdapter(cookie).getQueueConfig(input);
165     }
166
167     @Override
168     public Future<RpcResult<UpdateGroupOutput>> groupMod(GroupModInput input, SwitchConnectionDistinguisher cookie) {        
169         LOG.debug("Calling OFLibrary groupMod");
170         Future<RpcResult<Void>> response = getConnectionAdapter(cookie).groupMod(input);
171
172         // Send the same Xid back to caller - MessageDrivenSwitch
173         UpdateGroupOutputBuilder groupModOutput = new UpdateGroupOutputBuilder();      
174         BigInteger bigIntXid = BigInteger.valueOf(input.getXid());
175         groupModOutput.setTransactionId(new TransactionId(bigIntXid));
176        
177         UpdateGroupOutput result = groupModOutput.build();
178         Collection<RpcError> errors = Collections.emptyList();
179         RpcResult<UpdateGroupOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
180
181         // solution 1: sending directly and hooking listener to get error
182         // hookup listener to catch the possible error with no reference to returned future-object
183         LOG.debug("Returning to ModelDrivenSwitch for groupMod RPC");
184         return Futures.immediateFuture(rpcResult);
185
186     }
187
188     @Override
189     public Future<RpcResult<UpdateMeterOutput>> meterMod(MeterModInput input, SwitchConnectionDistinguisher cookie) {
190         LOG.debug("Calling OFLibrary meterMod");
191         Future<RpcResult<Void>> response = getConnectionAdapter(cookie).meterMod(input);
192
193         // Send the same Xid back to caller - MessageDrivenSwitch
194         UpdateMeterOutputBuilder meterModOutput = new UpdateMeterOutputBuilder();       
195         BigInteger bigIntXid =BigInteger.valueOf(input.getXid());
196         meterModOutput.setTransactionId(new TransactionId(bigIntXid));
197         
198         UpdateMeterOutput result = meterModOutput.build();
199         Collection<RpcError> errors = Collections.emptyList();
200         RpcResult<UpdateMeterOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
201
202         // solution 1: sending directly and hooking listener to get error
203         // hookup listener to catch the possible error with no reference to returned future-object
204         LOG.debug("Returning to ModelDrivenSwitch for meterMod RPC");
205         return Futures.immediateFuture(rpcResult);
206
207     }
208
209     @Override
210     public Future<RpcResult<java.lang.Void>> multipartRequest(MultipartRequestInput input, SwitchConnectionDistinguisher cookie) {
211         return getConnectionAdapter(cookie).multipartRequest(input);
212     }
213
214     @Override
215     public Future<RpcResult<Void>> packetOut(PacketOutInput input, SwitchConnectionDistinguisher cookie) {
216         return getConnectionAdapter(cookie).packetOut(input);
217     }
218
219     @Override
220     public Future<RpcResult<UpdatePortOutput>> portMod(PortModInput input, SwitchConnectionDistinguisher cookie) {
221
222         LOG.debug("Calling OFLibrary portMod");
223         Future<RpcResult<Void>> response = getConnectionAdapter(cookie).portMod(input);
224
225         // Send the same Xid back to caller - ModelDrivenSwitch
226         UpdatePortOutputBuilder portModOutput = new UpdatePortOutputBuilder();
227         String stringXid =input.getXid().toString();
228         BigInteger bigIntXid = new BigInteger( stringXid );
229         portModOutput.setTransactionId(new TransactionId(bigIntXid));
230         UpdatePortOutput result = portModOutput.build();
231         Collection<RpcError> errors = Collections.emptyList();
232         RpcResult<UpdatePortOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
233
234         LOG.debug("Returning to ModelDrivenSwitch for portMod RPC");
235         return Futures.immediateFuture(rpcResult);
236     }
237
238     @Override
239     public Future<RpcResult<RoleRequestOutput>> roleRequest(RoleRequestInput input, SwitchConnectionDistinguisher cookie) {
240         return getConnectionAdapter(cookie).roleRequest(input);
241     }
242
243     @Override
244     public Future<RpcResult<Void>> setAsync(SetAsyncInput input, SwitchConnectionDistinguisher cookie) {
245         return getConnectionAdapter(cookie).setAsync(input);
246     }
247
248     @Override
249     public Future<RpcResult<Void>> setConfig(SetConfigInput input, SwitchConnectionDistinguisher cookie) {
250         return getConnectionAdapter(cookie).setConfig(input);
251     }
252
253     @Override
254     public Future<RpcResult<Void>> tableMod(TableModInput input, SwitchConnectionDistinguisher cookie) {
255         return getConnectionAdapter(cookie).tableMod(input);
256     }
257 }