2 * Copyright (c) 2016, 2017 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.genius.itm.rpc;
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.SettableFuture;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.List;
19 import java.util.concurrent.Future;
20 import javax.annotation.PostConstruct;
21 import javax.annotation.PreDestroy;
22 import javax.inject.Inject;
23 import javax.inject.Singleton;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
28 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker;
29 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelDeleteWorker;
30 import org.opendaylight.genius.itm.globals.ITMConstants;
31 import org.opendaylight.genius.itm.impl.ItmUtils;
32 import org.opendaylight.genius.mdsalutil.MDSALUtil;
33 import org.opendaylight.genius.mdsalutil.MatchInfo;
34 import org.opendaylight.genius.mdsalutil.NwConstants;
35 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
36 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVteps;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVtepsBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVtepsKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwMlagDeviceInput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.BuildExternalTunnelFromDpnsInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsInput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwDeviceInput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwMlagDeviceInput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutputBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameInput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutput;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutputBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutputBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeInput;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeOutput;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentInput;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutput;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutputBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalInput;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutput;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutputBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInput;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsInput;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInput;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdEnableOnTunnelInput;
96 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
97 import org.opendaylight.yangtools.yang.common.RpcError;
98 import org.opendaylight.yangtools.yang.common.RpcResult;
99 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
100 import org.slf4j.Logger;
101 import org.slf4j.LoggerFactory;
104 public class ItmManagerRpcService implements ItmRpcService {
106 private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
107 private final DataBroker dataBroker;
108 private final IMdsalApiManager mdsalManager;
109 private final DPNTEPsInfoCache dpnTEPsInfoCache;
110 private final ItmExternalTunnelAddWorker externalTunnelAddWorker;
113 public ItmManagerRpcService(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
114 final ItmConfig itmConfig, final DPNTEPsInfoCache dpnTEPsInfoCache) {
115 this.dataBroker = dataBroker;
116 this.mdsalManager = mdsalManager;
117 this.dpnTEPsInfoCache = dpnTEPsInfoCache;
118 this.externalTunnelAddWorker = new ItmExternalTunnelAddWorker(dataBroker, itmConfig, dpnTEPsInfoCache);
122 public void start() {
123 LOG.info("ItmManagerRpcService Started");
127 public void close() {
128 LOG.info("ItmManagerRpcService Closed");
132 public Future<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(GetTunnelInterfaceNameInput input) {
133 RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
134 BigInteger sourceDpn = input.getSourceDpid();
135 BigInteger destinationDpn = input.getDestinationDpid();
136 Optional<InternalTunnel> optTunnel = Optional.absent();
138 if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
139 optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn,
140 TunnelTypeLogicalGroup.class, dataBroker);
141 LOG.debug("MULTIPLE_VxLAN_TUNNELS: getTunnelInterfaceName {}", optTunnel);
143 if (!optTunnel.isPresent()) {
144 optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn, input.getTunnelType(), dataBroker);
146 if (optTunnel.isPresent()) {
147 InternalTunnel tunnel = optTunnel.get();
148 GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
149 List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
150 if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
151 output.setInterfaceName(tunnelInterfaces.get(0));
152 resultBld = RpcResultBuilder.success();
153 resultBld.withResult(output.build());
155 resultBld = RpcResultBuilder.failed();
159 resultBld = RpcResultBuilder.failed();
161 return Futures.immediateFuture(resultBld.build());
165 public Future<RpcResult<GetEgressActionsForTunnelOutput>> getEgressActionsForTunnel(
166 GetEgressActionsForTunnelInput input) {
172 public Future<RpcResult<GetTunnelTypeOutput>> getTunnelType(GetTunnelTypeInput input) {
178 public Future<RpcResult<Void>> setBfdEnableOnTunnel(SetBfdEnableOnTunnelInput input) {
185 public Future<RpcResult<Void>> removeExternalTunnelEndpoint(
186 RemoveExternalTunnelEndpointInput input) {
187 //Ignore the Futures for now
188 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
189 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
190 ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, meshedDpnList,
191 input.getDestinationIp(), input.getTunnelType());
192 InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
193 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
194 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
195 transaction.delete(LogicalDatastoreType.CONFIGURATION, extPath);
196 ListenableFuture<Void> futureCheck = transaction.submit();
197 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
199 @Override public void onSuccess(Void voidInstance) {
200 result.set(RpcResultBuilder.<Void>success().build());
203 @Override public void onFailure(Throwable error) {
204 String msg = "Unable to delete DcGatewayIp " + input.getDestinationIp()
205 + " in datastore and tunnel type " + input.getTunnelType();
207 result.set(RpcResultBuilder.<Void>failed()
208 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
215 public Future<RpcResult<Void>> removeExternalTunnelFromDpns(
216 RemoveExternalTunnelFromDpnsInput input) {
217 //Ignore the Futures for now
218 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
219 List<DPNTEPsInfo> cfgDpnList = ItmUtils.getDpnTepListFromDpnId(dpnTEPsInfoCache, input.getDpnId()) ;
220 ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, cfgDpnList,
221 input.getDestinationIp(), input.getTunnelType());
222 result.set(RpcResultBuilder.<Void>success().build());
227 public Future<RpcResult<Void>> buildExternalTunnelFromDpns(
228 BuildExternalTunnelFromDpnsInput input) {
229 //Ignore the Futures for now
230 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
231 List<ListenableFuture<Void>> extTunnelResultList = externalTunnelAddWorker
232 .buildTunnelsFromDpnToExternalEndPoint(input.getDpnId(), input.getDestinationIp(),input.getTunnelType());
233 for (ListenableFuture<Void> extTunnelResult : extTunnelResultList) {
234 Futures.addCallback(extTunnelResult, new FutureCallback<Void>() {
237 public void onSuccess(Void voidInstance) {
238 result.set(RpcResultBuilder.<Void>success().build());
242 public void onFailure(Throwable error) {
243 String msg = "Unable to create ext tunnel";
244 LOG.error("create ext tunnel failed. {}. {}", msg, error);
245 result.set(RpcResultBuilder.<Void>failed()
246 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
254 public Future<RpcResult<Void>> addExternalTunnelEndpoint(
255 AddExternalTunnelEndpointInput input) {
256 // TODO Auto-generated method stub
258 //Ignore the Futures for now
259 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
260 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
261 externalTunnelAddWorker.buildTunnelsToExternalEndPoint(meshedDpnList,
262 input.getDestinationIp(), input.getTunnelType());
263 InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
264 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
265 DcGatewayIp dcGatewayIp =
266 new DcGatewayIpBuilder().setIpAddress(input.getDestinationIp())
267 .setTunnnelType(input.getTunnelType()).build();
268 WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
269 writeTransaction.put(LogicalDatastoreType.CONFIGURATION, extPath,dcGatewayIp, true);
270 ListenableFuture<Void> futureCheck = writeTransaction.submit();
271 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
273 @Override public void onSuccess(Void voidInstance) {
274 result.set(RpcResultBuilder.<Void>success().build());
277 @Override public void onFailure(Throwable error) {
279 "Unable to create DcGatewayIp {} in datastore for ip " + input.getDestinationIp() + "and "
280 + "tunnel type " + input.getTunnelType();
283 result.set(RpcResultBuilder.<Void>failed()
284 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
291 public Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
292 GetExternalTunnelInterfaceNameInput input) {
293 SettableFuture.create();
294 RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
295 String sourceNode = input.getSourceNode();
296 String dstNode = input.getDestinationNode();
297 ExternalTunnelKey externalTunnelKey = new ExternalTunnelKey(dstNode, sourceNode, input.getTunnelType());
298 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
299 ExternalTunnelList.class)
300 .child(ExternalTunnel.class, externalTunnelKey);
301 ExternalTunnel exTunnel =
302 ItmUtils.getExternalTunnelbyExternalTunnelKey(externalTunnelKey, path, this.dataBroker);
303 if (exTunnel != null) {
304 GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder();
305 output.setInterfaceName(exTunnel.getTunnelInterfaceName());
306 resultBld = RpcResultBuilder.success();
307 resultBld.withResult(output.build());
309 resultBld = RpcResultBuilder.failed();
312 return Futures.immediateFuture(resultBld.build());
316 public Future<RpcResult<java.lang.Void>>
317 createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
318 LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}",
319 input.getDpnId() , input.getServiceId(), input.getInstruction());
320 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
321 int serviceId = input.getServiceId() ;
322 final List<MatchInfo> mkMatches = getTunnelMatchesForServiceId(serviceId);
323 byte[] vxLANHeader = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
325 byte flags = (byte) 0x08;
326 vxLANHeader[0] = flags;
328 // Extract the serviceId details and imprint on the VxLAN Header
329 vxLANHeader[4] = (byte) (serviceId >> 16);
330 vxLANHeader[5] = (byte) (serviceId >> 8);
331 vxLANHeader[6] = (byte) (serviceId >> 0);
333 Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
334 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,serviceId), 5,
335 String.format("%s:%d","ITM Flow Entry ",serviceId), 0, 0,
336 ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(serviceId)),mkMatches, input.getInstruction());
338 ListenableFuture<Void> installFlowResult =
339 mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow);
340 Futures.addCallback(installFlowResult, new FutureCallback<Void>() {
343 public void onSuccess(Void voidInstance) {
344 result.set(RpcResultBuilder.<Void>success().build());
348 public void onFailure(Throwable error) {
349 String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
350 LOG.error("create terminating service actions failed. {}. {}", msg, error);
351 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error)
355 // result.set(RpcResultBuilder.<Void>success().build());
360 public Future<RpcResult<java.lang.Void>>
361 removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
362 LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}",
363 input.getDpnId(), input.getServiceId());
364 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
365 Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
366 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,input.getServiceId()), 5,
367 String.format("%s:%d","ITM Flow Entry ",input.getServiceId()), 0, 0,
368 ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(input.getServiceId())),
369 getTunnelMatchesForServiceId(input.getServiceId()), null);
371 ListenableFuture<Void> installFlowResult =
372 mdsalManager.removeFlow(input.getDpnId(), terminatingServiceTableFlow);
373 Futures.addCallback(installFlowResult, new FutureCallback<Void>() {
376 public void onSuccess(Void voidInstance) {
377 result.set(RpcResultBuilder.<Void>success().build());
381 public void onFailure(Throwable error) {
382 String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
383 LOG.error("remove terminating service actions failed. {}. {}", msg, error);
384 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error)
388 //result.set(RpcResultBuilder.<Void>success().build());
394 public List<MatchInfo> getTunnelMatchesForServiceId(int serviceId) {
395 final List<MatchInfo> mkMatches = new ArrayList<>();
396 byte[] vxLANHeader = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
399 byte flag = (byte) 0x08;
400 vxLANHeader[0] = flag;
402 // Extract the serviceId details and imprint on the VxLAN Header
403 vxLANHeader[4] = (byte) (serviceId >> 16);
404 vxLANHeader[5] = (byte) (serviceId >> 8);
405 vxLANHeader[6] = (byte) (serviceId >> 0);
408 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(serviceId)));
413 private String getFlowRef(long termSvcTable, int svcId) {
414 return String.valueOf(termSvcTable) + svcId;
418 public Future<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
419 GetInternalOrExternalInterfaceNameInput input) {
420 RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = RpcResultBuilder.failed();
421 BigInteger srcDpn = input.getSourceDpid() ;
423 IpAddress dstIp = input.getDestinationIp() ;
424 InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(ExternalTunnelList.class)
425 .child(ExternalTunnel.class,
426 new ExternalTunnelKey(String.valueOf(dstIp), srcDpn.toString(), input.getTunnelType()));
428 Optional<ExternalTunnel> optExtTunnel = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
430 if (optExtTunnel != null && optExtTunnel.isPresent()) {
431 ExternalTunnel extTunnel = optExtTunnel.get();
432 GetInternalOrExternalInterfaceNameOutputBuilder output =
433 new GetInternalOrExternalInterfaceNameOutputBuilder()
434 .setInterfaceName(extTunnel.getTunnelInterfaceName());
435 resultBld = RpcResultBuilder.success();
436 resultBld.withResult(output.build()) ;
438 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
439 if (meshedDpnList == null) {
440 LOG.error("There are no tunnel mesh info in config DS");
441 return Futures.immediateFuture(resultBld.build());
443 // Look for external tunnels if not look for internal tunnel
444 for (DPNTEPsInfo teps : meshedDpnList) {
445 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
446 if (dstIp.equals(firstEndPt.getIpAddress())) {
447 Optional<InternalTunnel> optTunnel = Optional.absent();
448 if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
449 optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
450 TunnelTypeLogicalGroup.class, dataBroker);
451 LOG.debug("MULTIPLE_VxLAN_TUNNELS: getInternalOrExternalInterfaceName {}", optTunnel);
453 if (!optTunnel.isPresent()) {
454 optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
455 input.getTunnelType(), dataBroker);
457 if (optTunnel.isPresent()) {
458 InternalTunnel tunnel = optTunnel.get();
459 List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
460 if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
461 GetInternalOrExternalInterfaceNameOutputBuilder
463 new GetInternalOrExternalInterfaceNameOutputBuilder()
464 .setInterfaceName(tunnelInterfaces.get(0));
465 resultBld = RpcResultBuilder.success();
466 resultBld.withResult(output.build());
468 LOG.error("No tunnel interface found between source DPN {} ans destination IP {}", srcDpn,
473 LOG.error("Tunnel not found for source DPN {} ans destination IP {}", srcDpn, dstIp);
478 return Futures.immediateFuture(resultBld.build());
481 @SuppressWarnings("checkstyle:IllegalCatch")
483 public Future<RpcResult<java.lang.Void>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
484 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
485 boolean foundVxlanTzone = false;
487 final IpAddress hwIp = input.getIpAddress();
488 final String nodeId = input.getNodeId();
489 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
490 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
491 containerPath, dataBroker);
492 if (transportZonesOptional.isPresent()) {
493 TransportZones transportZones = transportZonesOptional.get();
494 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
495 LOG.error("No teps configured");
496 result.set(RpcResultBuilder.<Void>failed()
497 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
500 for (TransportZone tzone : transportZones.getTransportZone()) {
501 if (!tzone.getTunnelType().equals(TunnelTypeVxlan.class)) {
504 foundVxlanTzone = true;
505 String transportZone = tzone.getZoneName();
506 if (tzone.getSubnets() == null || tzone.getSubnets().isEmpty()) {
507 result.set(RpcResultBuilder.<Void>failed()
508 .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
511 SubnetsKey subnetsKey = tzone.getSubnets().get(0).getKey();
512 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
513 InstanceIdentifier<DeviceVteps> path = InstanceIdentifier.builder(TransportZones.class)
514 .child(TransportZone.class, new TransportZoneKey(transportZone))
515 .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey)
517 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
518 //TO DO: add retry if it fails
520 transaction.delete(LogicalDatastoreType.CONFIGURATION, path);
522 ListenableFuture<Void> futureCheck = transaction.submit();
523 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
525 @Override public void onSuccess(Void voidInstance) {
526 result.set(RpcResultBuilder.<Void>success().build());
529 @Override public void onFailure(Throwable error) {
530 String msg = String.format("Unable to delete HwVtep %s from datastore", nodeId);
531 LOG.error("Unable to delete HwVtep {}, {} from datastore", nodeId, hwIp);
532 result.set(RpcResultBuilder.<Void>failed()
533 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
539 result.set(RpcResultBuilder.<Void>failed()
540 .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
544 if (!foundVxlanTzone) {
545 result.set(RpcResultBuilder.<Void>failed()
546 .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
551 } catch (Exception e) {
552 RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed()
553 .withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
554 return Futures.immediateFuture(resultBuilder.build());
558 @SuppressWarnings("checkstyle:IllegalCatch")
560 public Future<RpcResult<java.lang.Void>> addL2GwDevice(AddL2GwDeviceInput input) {
562 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
563 boolean foundVxlanTzone = false;
565 final IpAddress hwIp = input.getIpAddress();
566 final String nodeId = input.getNodeId();
567 //iterate through all transport zones and put TORs under vxlan
568 //if no vxlan tzone is cnfigured, return an error.
569 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
570 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
571 containerPath, dataBroker);
572 if (transportZonesOptional.isPresent()) {
573 TransportZones transportZones = transportZonesOptional.get();
574 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
575 LOG.error("No transportZone configured");
576 result.set(RpcResultBuilder.<Void>failed()
577 .withError(RpcError.ErrorType.APPLICATION, "No transportZone Configured").build());
580 for (TransportZone tzone : transportZones.getTransportZone()) {
581 if (!tzone.getTunnelType().equals(TunnelTypeVxlan.class)) {
584 String transportZone = tzone.getZoneName();
585 if (tzone.getSubnets() == null || tzone.getSubnets().isEmpty()) {
588 foundVxlanTzone = true;
589 SubnetsKey subnetsKey = tzone.getSubnets().get(0).getKey();
590 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
591 InstanceIdentifier<DeviceVteps> path = InstanceIdentifier.builder(TransportZones.class)
592 .child(TransportZone.class, new TransportZoneKey(transportZone))
593 .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey)
595 DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp)
596 .setNodeId(nodeId).setTopologyId(input.getTopologyId()).build();
597 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
598 //TO DO: add retry if it fails
599 transaction.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
601 ListenableFuture<Void> futureCheck = transaction.submit();
602 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
604 @Override public void onSuccess(Void voidInstance) {
605 result.set(RpcResultBuilder.<Void>success().build());
608 @Override public void onFailure(Throwable error) {
609 String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
610 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId, hwIp);
611 result.set(RpcResultBuilder.<Void>failed()
612 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
618 result.set(RpcResultBuilder.<Void>failed()
619 .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
623 if (!foundVxlanTzone) {
624 result.set(RpcResultBuilder.<Void>failed()
625 .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
630 } catch (Exception e) {
631 RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed()
632 .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
633 return Futures.immediateFuture(resultBuilder.build());
637 @SuppressWarnings("checkstyle:IllegalCatch")
639 public Future<RpcResult<java.lang.Void>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input) {
641 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
643 final IpAddress hwIp = input.getIpAddress();
644 final List<String> nodeId = input.getNodeId();
645 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
646 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
647 containerPath, dataBroker);
648 if (transportZonesOptional.isPresent()) {
649 TransportZones transportZones = transportZonesOptional.get();
650 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
651 LOG.error("No teps configured");
652 result.set(RpcResultBuilder.<Void>failed()
653 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
656 String transportZone = transportZones.getTransportZone().get(0).getZoneName();
657 if (transportZones.getTransportZone().get(0).getSubnets() == null
658 || transportZones.getTransportZone().get(0).getSubnets().isEmpty()) {
659 result.set(RpcResultBuilder.<Void>failed()
660 .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
663 SubnetsKey subnetsKey = transportZones.getTransportZone().get(0).getSubnets().get(0).getKey();
664 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
665 InstanceIdentifier<DeviceVteps> path =
666 InstanceIdentifier.builder(TransportZones.class)
667 .child(TransportZone.class, new TransportZoneKey(transportZone))
668 .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build();
669 DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp)
670 .setNodeId(nodeId.get(0)).setTopologyId(input.getTopologyId()).build();
671 WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
672 //TO DO: add retry if it fails
673 LOG.trace("writing hWvtep{}",deviceVtep);
674 writeTransaction.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
676 if (nodeId.size() == 2) {
677 LOG.trace("second node-id {}",nodeId.get(1));
678 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
679 InstanceIdentifier<DeviceVteps> path2 = InstanceIdentifier.builder(TransportZones.class)
680 .child(TransportZone.class, new TransportZoneKey(transportZone))
681 .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey2).build();
682 DeviceVteps deviceVtep2 = new DeviceVtepsBuilder().setKey(deviceVtepKey2).setIpAddress(hwIp)
683 .setNodeId(nodeId.get(1))
684 .setTopologyId(input.getTopologyId()).build();
685 //TO DO: add retry if it fails
686 LOG.trace("writing {}",deviceVtep2);
687 writeTransaction.put(LogicalDatastoreType.CONFIGURATION, path2, deviceVtep2, true);
689 ListenableFuture<Void> futureCheck = writeTransaction.submit();
690 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
693 public void onSuccess(Void voidInstance) {
694 result.set(RpcResultBuilder.<Void>success().build());
698 public void onFailure(Throwable error) {
699 String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
700 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
701 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error)
707 } catch (Exception e) {
708 RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed()
709 .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
710 return Futures.immediateFuture(resultBuilder.build());
714 @SuppressWarnings("checkstyle:IllegalCatch")
716 public Future<RpcResult<Void>> deleteL2GwMlagDevice(DeleteL2GwMlagDeviceInput input) {
718 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
720 final IpAddress hwIp = input.getIpAddress();
721 final List<String> nodeId = input.getNodeId();
722 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
723 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
724 containerPath, dataBroker);
725 if (transportZonesOptional.isPresent()) {
726 TransportZones tzones = transportZonesOptional.get();
727 if (tzones.getTransportZone() == null || tzones.getTransportZone().isEmpty()) {
728 LOG.error("No teps configured");
729 result.set(RpcResultBuilder.<Void>failed()
730 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
733 String transportZone = tzones.getTransportZone().get(0).getZoneName();
734 if (tzones.getTransportZone().get(0).getSubnets() == null || tzones.getTransportZone()
735 .get(0).getSubnets().isEmpty()) {
736 result.set(RpcResultBuilder.<Void>failed()
737 .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
740 SubnetsKey subnetsKey = tzones.getTransportZone().get(0).getSubnets().get(0).getKey();
741 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
742 InstanceIdentifier<DeviceVteps> path =
743 InstanceIdentifier.builder(TransportZones.class)
744 .child(TransportZone.class, new TransportZoneKey(transportZone))
745 .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
746 deviceVtepKey).build();
747 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
748 //TO DO: add retry if it fails
749 transaction.delete(LogicalDatastoreType.CONFIGURATION, path);
751 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
752 InstanceIdentifier<DeviceVteps> path2 =
753 InstanceIdentifier.builder(TransportZones.class)
754 .child(TransportZone.class, new TransportZoneKey(transportZone))
755 .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
756 deviceVtepKey2).build();
757 //TO DO: add retry if it fails
758 transaction.delete(LogicalDatastoreType.CONFIGURATION, path2);
760 ListenableFuture<Void> futureCheck = transaction.submit();
761 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
764 public void onSuccess(Void voidInstance) {
765 result.set(RpcResultBuilder.<Void>success().build());
769 public void onFailure(Throwable error) {
770 String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
771 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
772 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error)
778 } catch (Exception e) {
779 RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed()
780 .withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
781 return Futures.immediateFuture(resultBuilder.build());
786 public Future<RpcResult<IsTunnelInternalOrExternalOutput>> isTunnelInternalOrExternal(
787 IsTunnelInternalOrExternalInput input) {
788 RpcResultBuilder<IsTunnelInternalOrExternalOutput> resultBld;
789 String tunIfName = input.getTunnelInterfaceName();
791 IsTunnelInternalOrExternalOutputBuilder output = new IsTunnelInternalOrExternalOutputBuilder()
792 .setTunnelType(tunVal);
794 if (ItmUtils.ITM_CACHE.getInternalTunnel(tunIfName) != null) {
796 } else if (ItmUtils.ITM_CACHE.getExternalTunnel(tunIfName) != null) {
799 output.setTunnelType(tunVal);
800 resultBld = RpcResultBuilder.success();
801 resultBld.withResult(output.build());
802 return Futures.immediateFuture(resultBld.build());
806 public Future<RpcResult<IsDcgwPresentOutput>> isDcgwPresent(IsDcgwPresentInput input) {
807 RpcResultBuilder<IsDcgwPresentOutput> resultBld = RpcResultBuilder.success();
809 List<DcGatewayIp> dcGatewayIpList = ItmUtils.getDcGatewayIpList(dataBroker);
810 String dcgwIpStr = input.getDcgwIp();
811 IpAddress dcgwIpAddr = new IpAddress(dcgwIpStr.toCharArray());
814 if (dcGatewayIpList != null
815 && !dcGatewayIpList.isEmpty()
816 && dcGatewayIpList.contains(dcgwIpAddr)) {
819 IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
820 resultBld.withResult(output.build());
824 IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
825 resultBld.withResult(output.build());
827 return Futures.immediateFuture(resultBld.build());
831 public Future<RpcResult<GetDpnEndpointIpsOutput>> getDpnEndpointIps(GetDpnEndpointIpsInput input) {
832 BigInteger srcDpn = input.getSourceDpid() ;
833 RpcResultBuilder<GetDpnEndpointIpsOutput> resultBld = RpcResultBuilder.failed();
834 InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
835 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class,
836 new DPNTEPsInfoKey(srcDpn)).build();
837 Optional<DPNTEPsInfo> tunnelInfo = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tunnelInfoId, dataBroker);
838 if (!tunnelInfo.isPresent()) {
839 LOG.error("tunnelInfo is not present");
840 return Futures.immediateFuture(resultBld.build());
843 List<TunnelEndPoints> tunnelEndPointList = tunnelInfo.get().getTunnelEndPoints();
844 if (tunnelEndPointList == null || tunnelEndPointList.isEmpty()) {
845 LOG.error("tunnelEndPointList is null or empty");
846 return Futures.immediateFuture(resultBld.build());
849 List<IpAddress> nexthopIpList = new ArrayList<>();
850 tunnelEndPointList.forEach(tunnelEndPoint -> {
851 nexthopIpList.add(tunnelEndPoint.getIpAddress());
854 GetDpnEndpointIpsOutputBuilder output = new GetDpnEndpointIpsOutputBuilder().setNexthopipList(nexthopIpList);
855 resultBld = RpcResultBuilder.success();
856 resultBld.withResult(output.build()) ;
857 return Futures.immediateFuture(resultBld.build());