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