066e5059226d4a9f6b8f2d6740cae0c94b595a6c
[vpnservice.git] / itm / itm-impl / src / main / java / org / opendaylight / vpnservice / itm / rpc / ItmManagerRpcService.java
1 /*
2  * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  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.vpnservice.itm.rpc;
9
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.concurrent.Future;
14
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
21 import org.opendaylight.vpnservice.itm.confighelpers.ItmExternalTunnelAddWorker;
22 import org.opendaylight.vpnservice.itm.confighelpers.ItmExternalTunnelDeleteWorker;
23 import org.opendaylight.vpnservice.itm.globals.ITMConstants;
24 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
25 import org.opendaylight.vpnservice.itm.impl.ItmUtils;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.AddExternalTunnelEndpointInput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.BuildExternalTunnelFromDpnsInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.CreateTerminatingServiceActionsInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameOutput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameOutputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetInternalOrExternalInterfaceNameInput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetInternalOrExternalInterfaceNameOutput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetInternalOrExternalInterfaceNameOutputBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameInput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutputBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.RemoveExternalTunnelEndpointInput;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.RemoveExternalTunnelFromDpnsInput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.RemoveTerminatingServiceActionsInput;
52 import org.opendaylight.yangtools.yang.common.RpcResult;
53 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
54
55 import com.google.common.util.concurrent.FutureCallback;
56 import com.google.common.util.concurrent.Futures;
57 import com.google.common.util.concurrent.ListenableFuture;
58 import com.google.common.util.concurrent.SettableFuture;
59
60 import org.opendaylight.yangtools.yang.common.RpcError;
61 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
62 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
63 import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
64 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
65 import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
66 import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
67 import org.opendaylight.vpnservice.mdsalutil.ActionType;
68
69 import com.google.common.base.Optional;
70
71 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
72
73 public class ItmManagerRpcService implements ItmRpcService {
74
75    private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
76         DataBroker dataBroker;
77         private IMdsalApiManager mdsalManager;
78
79
80     public void setMdsalManager(IMdsalApiManager mdsalManager) {
81             this.mdsalManager = mdsalManager;
82     }
83
84         IdManagerService idManagerService;
85
86         public ItmManagerRpcService(DataBroker dataBroker, IdManagerService idManagerService) {
87           this.dataBroker = dataBroker;
88           this.idManagerService = idManagerService;
89         }
90
91      @Override
92      public Future<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(GetTunnelInterfaceNameInput input) {
93          RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
94          BigInteger sourceDpn = input.getSourceDpid() ;
95          BigInteger destinationDpn = input.getDestinationDpid() ;
96          InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
97                  TunnelList.class)
98                      .child(InternalTunnel.class, new InternalTunnelKey(destinationDpn, sourceDpn));      
99          
100          Optional<InternalTunnel> tnl = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
101
102          if( tnl != null && tnl.isPresent())
103          {
104               InternalTunnel tunnel = tnl.get();
105               GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
106               output.setInterfaceName(tunnel.getTunnelInterfaceName()) ;
107               resultBld = RpcResultBuilder.success();
108               resultBld.withResult(output.build()) ;
109          }else {
110              resultBld = RpcResultBuilder.failed();
111          }
112          
113          return Futures.immediateFuture(resultBld.build());
114      }
115
116
117     @Override
118     public Future<RpcResult<Void>> removeExternalTunnelEndpoint(
119             RemoveExternalTunnelEndpointInput input) {
120          //Ignore the Futures for now
121         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
122         List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
123         ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, idManagerService,meshedDpnList , input.getDestinationIp(), input.getTunnelType());
124         result.set(RpcResultBuilder.<Void>success().build());
125         return result;
126     }
127
128     @Override
129     public Future<RpcResult<Void>> removeExternalTunnelFromDpns(
130             RemoveExternalTunnelFromDpnsInput input) {
131         //Ignore the Futures for now
132         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
133         List<DPNTEPsInfo> cfgDpnList = ItmUtils.getDPNTEPListFromDPNId(dataBroker, input.getDpnId()) ;
134         ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, idManagerService, cfgDpnList, input.getDestinationIp(), input.getTunnelType());
135         result.set(RpcResultBuilder.<Void>success().build());
136         return result;
137     }
138
139     @Override
140     public Future<RpcResult<Void>> buildExternalTunnelFromDpns(
141             BuildExternalTunnelFromDpnsInput input) {
142         //Ignore the Futures for now
143         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
144         List<ListenableFuture<Void>> extTunnelResultList = ItmExternalTunnelAddWorker.buildTunnelsFromDpnToExternalEndPoint(dataBroker, idManagerService,input.getDpnId(), input.getDestinationIp(), input.getTunnelType());
145         for (ListenableFuture<Void> extTunnelResult : extTunnelResultList) {
146             Futures.addCallback(extTunnelResult, new FutureCallback<Void>(){
147
148                 @Override
149                 public void onSuccess(Void aVoid) {
150                     result.set(RpcResultBuilder.<Void>success().build());
151                 }
152
153                 @Override
154                 public void onFailure(Throwable error) {
155                     String msg = String.format("Unable to create ext tunnel");
156                     LOG.error("create ext tunnel failed. {}. {}", msg, error);
157                     result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
158                 }
159             });
160         }
161         result.set(RpcResultBuilder.<Void>success().build());
162         return result;
163     }
164
165     @Override
166     public Future<RpcResult<Void>> addExternalTunnelEndpoint(
167             AddExternalTunnelEndpointInput input) {
168         // TODO Auto-generated method stub
169
170         //Ignore the Futures for now
171         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
172         List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
173         ItmExternalTunnelAddWorker.buildTunnelsToExternalEndPoint(dataBroker, idManagerService,meshedDpnList, input.getDestinationIp(), input.getTunnelType()) ;
174         result.set(RpcResultBuilder.<Void>success().build());
175         return result;
176     }
177
178     @Override
179     public Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
180             GetExternalTunnelInterfaceNameInput input) {
181         final SettableFuture<RpcResult<GetExternalTunnelInterfaceNameOutput>> result = SettableFuture.create() ;
182         RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
183         BigInteger sourceDpn = input.getSourceDpid() ;
184         IpAddress destinationIp = input.getDestinationIp() ;
185         InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
186                 ExternalTunnelList.class)
187                     .child(ExternalTunnel.class, new ExternalTunnelKey(destinationIp, sourceDpn));      
188         
189         Optional<ExternalTunnel> ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
190
191         if( ext != null && ext.isPresent())
192         {
193              ExternalTunnel exTunnel = ext.get();
194              GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder() ;
195              output.setInterfaceName(exTunnel.getTunnelInterfaceName()) ;
196              resultBld = RpcResultBuilder.success();
197              resultBld.withResult(output.build()) ;
198         }else {
199             resultBld = RpcResultBuilder.failed();
200         }
201         
202         return Futures.immediateFuture(resultBld.build());
203     }
204
205     @Override
206     public Future<RpcResult<java.lang.Void>> createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
207         LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}", input.getDpnId() , input.getServiceId(), input.getInstruction());
208        final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
209        int serviceId = input.getServiceId() ;
210        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
211        byte[] vxLANHeader = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
212     // Flags Byte
213        byte Flags = (byte) 0x08;
214        vxLANHeader[0] = Flags;
215
216        // Extract the serviceId details and imprint on the VxLAN Header
217        vxLANHeader[4] = (byte) (serviceId >> 16);
218        vxLANHeader[5] = (byte) (serviceId >> 8);
219        vxLANHeader[6] = (byte) (serviceId >> 0);
220
221        // Matching metadata
222        mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
223                                new BigInteger(1, vxLANHeader),
224                                MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID }));
225
226        Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(ITMConstants.INTERNAL_TUNNEL_TABLE,
227                        getFlowRef(ITMConstants.INTERNAL_TUNNEL_TABLE,serviceId), 5, String.format("%s:%d","ITM Flow Entry ",serviceId),
228                        0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(serviceId)),mkMatches, input.getInstruction());
229
230        ListenableFuture<Void> installFlowResult = mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow);
231        Futures.addCallback(installFlowResult, new FutureCallback<Void>(){
232
233            @Override
234            public void onSuccess(Void aVoid) {
235                result.set(RpcResultBuilder.<Void>success().build());
236            }
237
238            @Override
239            public void onFailure(Throwable error) {
240                String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
241                LOG.error("create terminating service actions failed. {}. {}", msg, error);
242                result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
243            }
244        });
245        result.set(RpcResultBuilder.<Void>success().build());
246        return result;
247     }
248
249     @Override
250     public Future<RpcResult<java.lang.Void>> removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
251         LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}", input.getDpnId(), input.getServiceId());
252         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
253         Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(ITMConstants.INTERNAL_TUNNEL_TABLE,
254                 getFlowRef(ITMConstants.INTERNAL_TUNNEL_TABLE,input.getServiceId()), 5, String.format("%s:%d","ITM Flow Entry ",input.getServiceId()),
255                 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(input.getServiceId())),getTunnelMatchesForServiceId(input.getServiceId()), null );
256
257         ListenableFuture<Void> installFlowResult = mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow);
258         Futures.addCallback(installFlowResult, new FutureCallback<Void>(){
259
260             @Override
261             public void onSuccess(Void aVoid) {
262                 result.set(RpcResultBuilder.<Void>success().build());
263             }
264
265             @Override
266             public void onFailure(Throwable error) {
267                 String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
268                 LOG.error("remove terminating service actions failed. {}. {}", msg, error);
269                 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
270             }
271         });
272         result.set(RpcResultBuilder.<Void>success().build());
273
274        return result ;
275     }
276
277     public List<MatchInfo> getTunnelMatchesForServiceId(int serviceId) {
278         List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
279         byte[] vxLANHeader = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
280
281         // Flags Byte
282         byte Flags = (byte) 0x08;
283         vxLANHeader[0] = Flags;
284
285         // Extract the serviceId details and imprint on the VxLAN Header
286         vxLANHeader[4] = (byte) (serviceId >> 16);
287         vxLANHeader[5] = (byte) (serviceId >> 8);
288         vxLANHeader[6] = (byte) (serviceId >> 0);
289
290         // Matching metadata
291         mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[]{
292                 new BigInteger(1, vxLANHeader),
293                 MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID}));
294
295         return mkMatches;
296     }
297
298     private String getFlowRef(long termSvcTable, int svcId) {
299         return new StringBuffer().append(termSvcTable).append(svcId).toString();
300     }
301
302     @Override
303     public Future<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
304        GetInternalOrExternalInterfaceNameInput input) {
305        RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = null;
306        BigInteger srcDpn = input.getSourceDpid() ;
307        IpAddress dstIp = input.getDestinationIp() ;
308        List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
309        // Look for external tunnels if not look for internal tunnel
310        for( DPNTEPsInfo teps : meshedDpnList) {
311            TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0) ;
312            if( dstIp.equals(firstEndPt.getIpAddress())) {
313               InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
314                        TunnelList.class)
315                            .child(InternalTunnel.class, new InternalTunnelKey(srcDpn, teps.getDPNID()));      
316                
317                Optional<InternalTunnel> tnl = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
318                if( tnl != null && tnl.isPresent())
319                {
320                     InternalTunnel tunnel = tnl.get();
321                     GetInternalOrExternalInterfaceNameOutputBuilder output = new GetInternalOrExternalInterfaceNameOutputBuilder().setInterfaceName(tunnel.getTunnelInterfaceName() );
322                     resultBld = RpcResultBuilder.success();
323                     resultBld.withResult(output.build()) ;
324                }else {
325                    //resultBld = RpcResultBuilder.failed();
326                    InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(
327                            ExternalTunnelList.class)
328                                .child(ExternalTunnel.class, new ExternalTunnelKey(dstIp, srcDpn));      
329                    
330                    Optional<ExternalTunnel> ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
331
332                    if( ext != null && ext.isPresent())
333                    {
334                         ExternalTunnel extTunnel = ext.get();
335                         GetInternalOrExternalInterfaceNameOutputBuilder output = new GetInternalOrExternalInterfaceNameOutputBuilder().setInterfaceName(extTunnel.getTunnelInterfaceName() );
336                         resultBld = RpcResultBuilder.success();
337                         resultBld.withResult(output.build()) ;
338                    }else {
339                        resultBld = RpcResultBuilder.failed();
340                    }
341                }
342            }
343        }
344        return Futures.immediateFuture(resultBld.build());
345     }
346
347 }