2 * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. 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.vpnservice.itm.rpc;
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.concurrent.Future;
15 import org.opendaylight.vpnservice.mdsalutil.*;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
22 import org.opendaylight.vpnservice.itm.confighelpers.ItmExternalTunnelAddWorker;
23 import org.opendaylight.vpnservice.itm.confighelpers.ItmExternalTunnelDeleteWorker;
24 import org.opendaylight.vpnservice.itm.globals.ITMConstants;
25 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
26 import org.opendaylight.vpnservice.itm.impl.ItmUtils;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.AddExternalTunnelEndpointInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.BuildExternalTunnelFromDpnsInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.CreateTerminatingServiceActionsInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameOutput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameOutputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetInternalOrExternalInterfaceNameInput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetInternalOrExternalInterfaceNameOutput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetInternalOrExternalInterfaceNameOutputBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameInput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutput;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutputBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.RemoveExternalTunnelEndpointInput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.RemoveExternalTunnelFromDpnsInput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.RemoveTerminatingServiceActionsInput;
53 import org.opendaylight.yangtools.yang.common.RpcResult;
54 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
56 import com.google.common.util.concurrent.FutureCallback;
57 import com.google.common.util.concurrent.Futures;
58 import com.google.common.util.concurrent.ListenableFuture;
59 import com.google.common.util.concurrent.SettableFuture;
61 import org.opendaylight.yangtools.yang.common.RpcError;
62 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
64 import com.google.common.base.Optional;
66 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
68 public class ItmManagerRpcService implements ItmRpcService {
70 private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
71 DataBroker dataBroker;
72 private IMdsalApiManager mdsalManager;
75 public void setMdsalManager(IMdsalApiManager mdsalManager) {
76 this.mdsalManager = mdsalManager;
79 IdManagerService idManagerService;
81 public ItmManagerRpcService(DataBroker dataBroker, IdManagerService idManagerService) {
82 this.dataBroker = dataBroker;
83 this.idManagerService = idManagerService;
87 public Future<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(GetTunnelInterfaceNameInput input) {
88 RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
89 BigInteger sourceDpn = input.getSourceDpid() ;
90 BigInteger destinationDpn = input.getDestinationDpid() ;
91 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
93 .child(InternalTunnel.class, new InternalTunnelKey(destinationDpn, sourceDpn));
95 Optional<InternalTunnel> tnl = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
97 if( tnl != null && tnl.isPresent())
99 InternalTunnel tunnel = tnl.get();
100 GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
101 output.setInterfaceName(tunnel.getTunnelInterfaceName()) ;
102 resultBld = RpcResultBuilder.success();
103 resultBld.withResult(output.build()) ;
105 resultBld = RpcResultBuilder.failed();
108 return Futures.immediateFuture(resultBld.build());
113 public Future<RpcResult<Void>> removeExternalTunnelEndpoint(
114 RemoveExternalTunnelEndpointInput input) {
115 //Ignore the Futures for now
116 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
117 List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
118 ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, idManagerService,meshedDpnList , input.getDestinationIp(), input.getTunnelType());
119 result.set(RpcResultBuilder.<Void>success().build());
124 public Future<RpcResult<Void>> removeExternalTunnelFromDpns(
125 RemoveExternalTunnelFromDpnsInput input) {
126 //Ignore the Futures for now
127 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
128 List<DPNTEPsInfo> cfgDpnList = ItmUtils.getDPNTEPListFromDPNId(dataBroker, input.getDpnId()) ;
129 ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, idManagerService, cfgDpnList, input.getDestinationIp(), input.getTunnelType());
130 result.set(RpcResultBuilder.<Void>success().build());
135 public Future<RpcResult<Void>> buildExternalTunnelFromDpns(
136 BuildExternalTunnelFromDpnsInput input) {
137 //Ignore the Futures for now
138 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
139 List<ListenableFuture<Void>> extTunnelResultList = ItmExternalTunnelAddWorker.buildTunnelsFromDpnToExternalEndPoint(dataBroker, idManagerService,input.getDpnId(), input.getDestinationIp(), input.getTunnelType());
140 for (ListenableFuture<Void> extTunnelResult : extTunnelResultList) {
141 Futures.addCallback(extTunnelResult, new FutureCallback<Void>(){
144 public void onSuccess(Void aVoid) {
145 result.set(RpcResultBuilder.<Void>success().build());
149 public void onFailure(Throwable error) {
150 String msg = String.format("Unable to create ext tunnel");
151 LOG.error("create ext tunnel failed. {}. {}", msg, error);
152 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
156 result.set(RpcResultBuilder.<Void>success().build());
161 public Future<RpcResult<Void>> addExternalTunnelEndpoint(
162 AddExternalTunnelEndpointInput input) {
163 // TODO Auto-generated method stub
165 //Ignore the Futures for now
166 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
167 List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
168 ItmExternalTunnelAddWorker.buildTunnelsToExternalEndPoint(dataBroker, idManagerService,meshedDpnList, input.getDestinationIp(), input.getTunnelType()) ;
169 result.set(RpcResultBuilder.<Void>success().build());
174 public Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
175 GetExternalTunnelInterfaceNameInput input) {
176 final SettableFuture<RpcResult<GetExternalTunnelInterfaceNameOutput>> result = SettableFuture.create() ;
177 RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
178 BigInteger sourceDpn = input.getSourceDpid() ;
179 IpAddress destinationIp = input.getDestinationIp() ;
180 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
181 ExternalTunnelList.class)
182 .child(ExternalTunnel.class, new ExternalTunnelKey(destinationIp, sourceDpn));
184 Optional<ExternalTunnel> ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
186 if( ext != null && ext.isPresent())
188 ExternalTunnel exTunnel = ext.get();
189 GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder() ;
190 output.setInterfaceName(exTunnel.getTunnelInterfaceName()) ;
191 resultBld = RpcResultBuilder.success();
192 resultBld.withResult(output.build()) ;
194 resultBld = RpcResultBuilder.failed();
197 return Futures.immediateFuture(resultBld.build());
201 public Future<RpcResult<java.lang.Void>> createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
202 LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}", input.getDpnId() , input.getServiceId(), input.getInstruction());
203 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
204 int serviceId = input.getServiceId() ;
205 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
206 byte[] vxLANHeader = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
208 byte Flags = (byte) 0x08;
209 vxLANHeader[0] = Flags;
211 // Extract the serviceId details and imprint on the VxLAN Header
212 vxLANHeader[4] = (byte) (serviceId >> 16);
213 vxLANHeader[5] = (byte) (serviceId >> 8);
214 vxLANHeader[6] = (byte) (serviceId >> 0);
217 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
218 new BigInteger(1, vxLANHeader),
219 MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID }));
221 Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
222 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,serviceId), 5, String.format("%s:%d","ITM Flow Entry ",serviceId),
223 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(serviceId)),mkMatches, input.getInstruction());
225 ListenableFuture<Void> installFlowResult = mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow);
226 Futures.addCallback(installFlowResult, new FutureCallback<Void>(){
229 public void onSuccess(Void aVoid) {
230 result.set(RpcResultBuilder.<Void>success().build());
234 public void onFailure(Throwable error) {
235 String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
236 LOG.error("create terminating service actions failed. {}. {}", msg, error);
237 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
240 result.set(RpcResultBuilder.<Void>success().build());
245 public Future<RpcResult<java.lang.Void>> removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
246 LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}", input.getDpnId(), input.getServiceId());
247 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
248 Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
249 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,input.getServiceId()), 5, String.format("%s:%d","ITM Flow Entry ",input.getServiceId()),
250 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(input.getServiceId())),getTunnelMatchesForServiceId(input.getServiceId()), null );
252 ListenableFuture<Void> installFlowResult = mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow);
253 Futures.addCallback(installFlowResult, new FutureCallback<Void>(){
256 public void onSuccess(Void aVoid) {
257 result.set(RpcResultBuilder.<Void>success().build());
261 public void onFailure(Throwable error) {
262 String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
263 LOG.error("remove terminating service actions failed. {}. {}", msg, error);
264 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
267 result.set(RpcResultBuilder.<Void>success().build());
272 public List<MatchInfo> getTunnelMatchesForServiceId(int serviceId) {
273 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
274 byte[] vxLANHeader = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
277 byte Flags = (byte) 0x08;
278 vxLANHeader[0] = Flags;
280 // Extract the serviceId details and imprint on the VxLAN Header
281 vxLANHeader[4] = (byte) (serviceId >> 16);
282 vxLANHeader[5] = (byte) (serviceId >> 8);
283 vxLANHeader[6] = (byte) (serviceId >> 0);
286 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[]{
287 new BigInteger(1, vxLANHeader),
288 MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID}));
293 private String getFlowRef(long termSvcTable, int svcId) {
294 return new StringBuffer().append(termSvcTable).append(svcId).toString();
298 public Future<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
299 GetInternalOrExternalInterfaceNameInput input) {
300 RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = null;
301 BigInteger srcDpn = input.getSourceDpid() ;
302 IpAddress dstIp = input.getDestinationIp() ;
303 List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
304 // Look for external tunnels if not look for internal tunnel
305 for( DPNTEPsInfo teps : meshedDpnList) {
306 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0) ;
307 if( dstIp.equals(firstEndPt.getIpAddress())) {
308 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
310 .child(InternalTunnel.class, new InternalTunnelKey(srcDpn, teps.getDPNID()));
312 Optional<InternalTunnel> tnl = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
313 if( tnl != null && tnl.isPresent())
315 InternalTunnel tunnel = tnl.get();
316 GetInternalOrExternalInterfaceNameOutputBuilder output = new GetInternalOrExternalInterfaceNameOutputBuilder().setInterfaceName(tunnel.getTunnelInterfaceName() );
317 resultBld = RpcResultBuilder.success();
318 resultBld.withResult(output.build()) ;
320 //resultBld = RpcResultBuilder.failed();
321 InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(
322 ExternalTunnelList.class)
323 .child(ExternalTunnel.class, new ExternalTunnelKey(dstIp, srcDpn));
325 Optional<ExternalTunnel> ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
327 if( ext != null && ext.isPresent())
329 ExternalTunnel extTunnel = ext.get();
330 GetInternalOrExternalInterfaceNameOutputBuilder output = new GetInternalOrExternalInterfaceNameOutputBuilder().setInterfaceName(extTunnel.getTunnelInterfaceName() );
331 resultBld = RpcResultBuilder.success();
332 resultBld.withResult(output.build()) ;
334 resultBld = RpcResultBuilder.failed();
339 return Futures.immediateFuture(resultBld.build());