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 static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
11 import static org.opendaylight.serviceutils.tools.rpc.FutureRpcResults.fromListenableFuture;
12 import static org.opendaylight.yangtools.yang.common.RpcResultBuilder.failed;
14 import com.google.common.base.Objects;
15 import com.google.common.util.concurrent.FluentFuture;
16 import com.google.common.util.concurrent.FutureCallback;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import com.google.common.util.concurrent.MoreExecutors;
20 import com.google.common.util.concurrent.SettableFuture;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.List;
27 import java.util.Optional;
28 import java.util.concurrent.ExecutionException;
29 import java.util.stream.Collectors;
30 import javax.annotation.PostConstruct;
31 import javax.annotation.PreDestroy;
32 import javax.inject.Inject;
33 import javax.inject.Singleton;
34 import org.eclipse.jdt.annotation.NonNull;
35 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
36 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
37 import org.opendaylight.genius.interfacemanager.interfaces.InterfaceManagerService;
38 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
39 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
40 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
41 import org.opendaylight.genius.itm.cache.TunnelStateCache;
42 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker;
43 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelDeleteWorker;
44 import org.opendaylight.genius.itm.globals.ITMConstants;
45 import org.opendaylight.genius.itm.impl.ItmUtils;
46 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
47 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
48 import org.opendaylight.genius.mdsalutil.ActionInfo;
49 import org.opendaylight.genius.mdsalutil.MDSALUtil;
50 import org.opendaylight.genius.mdsalutil.MatchInfo;
51 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
52 import org.opendaylight.genius.mdsalutil.NwConstants;
53 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
54 import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
55 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
56 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
57 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
58 import org.opendaylight.mdsal.binding.api.DataBroker;
59 import org.opendaylight.mdsal.binding.util.Datastore;
60 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
61 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
62 import org.opendaylight.mdsal.binding.util.RetryingManagedNewTransactionRunner;
63 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
64 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
65 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
66 import org.opendaylight.mdsal.common.api.ReadFailedException;
67 import org.opendaylight.serviceutils.tools.rpc.FutureRpcResults;
68 import org.opendaylight.serviceutils.tools.rpc.FutureRpcResults.LogLevel;
69 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
70 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntry;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnTepsState;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTepsKey;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpns;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpnsBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpnsKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpKey;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.DeviceVteps;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.DeviceVtepsBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.DeviceVtepsKey;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointOutput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceOutput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwMlagDeviceInput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwMlagDeviceOutput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.BuildExternalTunnelFromDpnsInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.BuildExternalTunnelFromDpnsOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsInput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsOutput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwDeviceInput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwDeviceOutput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwMlagDeviceInput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwMlagDeviceOutput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsInput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutputBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoInput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoOutput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoOutputBuilder;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutputBuilder;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutputBuilder;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameInput;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutput;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutputBuilder;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInput;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutputBuilder;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeInput;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeOutput;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeOutputBuilder;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetWatchPortForTunnelInput;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetWatchPortForTunnelOutput;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentInput;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutput;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutputBuilder;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalInput;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutput;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutputBuilder;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInput;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointOutput;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsInput;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsOutput;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInput;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsOutput;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdParamOnTunnelInput;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdParamOnTunnelOutput;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.get.dpn.info.output.Computes;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.get.dpn.info.output.ComputesBuilder;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
162 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
163 import org.opendaylight.yangtools.yang.common.OperationFailedException;
164 import org.opendaylight.yangtools.yang.common.RpcError;
165 import org.opendaylight.yangtools.yang.common.RpcResult;
166 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
167 import org.opendaylight.yangtools.yang.common.Uint16;
168 import org.opendaylight.yangtools.yang.common.Uint64;
169 import org.slf4j.Logger;
170 import org.slf4j.LoggerFactory;
173 public class ItmManagerRpcService implements ItmRpcService {
175 private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
177 private final DataBroker dataBroker;
178 private final IMdsalApiManager mdsalManager;
179 private final DPNTEPsInfoCache dpnTEPsInfoCache;
180 private final ItmExternalTunnelAddWorker externalTunnelAddWorker;
181 private final SingleTransactionDataBroker singleTransactionDataBroker;
182 private final IInterfaceManager interfaceManager;
183 private final InterfaceManagerService interfaceManagerService;
184 private final DpnTepStateCache dpnTepStateCache;
185 private final TunnelStateCache tunnelStateCache;
186 private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache;
187 private final DirectTunnelUtils directTunnelUtils;
188 private final ManagedNewTransactionRunner txRunner;
189 private final RetryingManagedNewTransactionRunner retryingTxRunner;
190 private final ItmConfig itmConfig;
193 public ItmManagerRpcService(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
194 final ItmConfig itmConfig, final DPNTEPsInfoCache dpnTEPsInfoCache,
195 final IInterfaceManager interfaceManager, final DpnTepStateCache dpnTepStateCache,
196 final TunnelStateCache tunnelStateCache,
197 final InterfaceManagerService interfaceManagerService,
198 final OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
199 final DirectTunnelUtils directTunnelUtils) {
200 this.dataBroker = dataBroker;
201 this.mdsalManager = mdsalManager;
202 this.dpnTEPsInfoCache = dpnTEPsInfoCache;
203 this.externalTunnelAddWorker = new ItmExternalTunnelAddWorker(itmConfig, dpnTEPsInfoCache);
204 this.singleTransactionDataBroker = new SingleTransactionDataBroker(dataBroker);
205 this.interfaceManager = interfaceManager;
206 this.interfaceManagerService = interfaceManagerService;
207 this.dpnTepStateCache = dpnTepStateCache;
208 this.tunnelStateCache = tunnelStateCache;
209 this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache;
210 this.directTunnelUtils = directTunnelUtils;
211 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
212 this.retryingTxRunner = new RetryingManagedNewTransactionRunner(dataBroker);
213 this.itmConfig = itmConfig;
217 public void start() {
218 LOG.info("ItmManagerRpcService Started");
222 public void close() {
223 LOG.info("ItmManagerRpcService Closed");
227 public ListenableFuture<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(
228 GetTunnelInterfaceNameInput input) {
229 RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
230 Uint64 sourceDpn = input.getSourceDpid();
231 Uint64 destinationDpn = input.getDestinationDpid();
232 Optional<InternalTunnel> optTunnel = Optional.empty();
234 if (interfaceManager.isItmDirectTunnelsEnabled()) {
235 DpnTepInterfaceInfo interfaceInfo = dpnTepStateCache.getDpnTepInterface(sourceDpn, destinationDpn);
236 if (interfaceInfo != null) {
237 resultBld = RpcResultBuilder.success();
238 resultBld.withResult(new GetTunnelInterfaceNameOutputBuilder()
239 .setInterfaceName(interfaceInfo.getTunnelName())).build();
240 return Futures.immediateFuture(resultBld.build());
243 if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
244 optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn,
245 TunnelTypeLogicalGroup.class, dataBroker);
246 LOG.debug("MULTIPLE_VxLAN_TUNNELS: getTunnelInterfaceName {}", optTunnel);
248 if (!optTunnel.isPresent()) {
249 optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn, input.getTunnelType(), dataBroker);
251 if (optTunnel.isPresent()) {
252 InternalTunnel tunnel = optTunnel.get();
253 GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
254 List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
255 if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
256 output.setInterfaceName(tunnelInterfaces.get(0));
257 resultBld = RpcResultBuilder.success();
258 resultBld.withResult(output.build());
260 resultBld = failed();
264 resultBld = failed();
266 return Futures.immediateFuture(resultBld.build());
270 public ListenableFuture<RpcResult<GetEgressActionsForTunnelOutput>>
271 getEgressActionsForTunnel(GetEgressActionsForTunnelInput input) {
272 String tunnelName = input.getIntfName();
273 if (tunnelName == null) {
274 return Futures.immediateFuture(RpcResultBuilder.<GetEgressActionsForTunnelOutput>failed()
275 .withError(RpcError.ErrorType.APPLICATION,
276 "tunnel name not set for GetEgressActionsForTunnel call").build());
278 if (!dpnTepStateCache.isInternal(tunnelName) || !interfaceManager.isItmDirectTunnelsEnabled()) {
279 // Re-direct the RPC to Interface Manager
280 // From the rpc input and get the output and copy to output
281 org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
282 .GetEgressActionsForInterfaceInputBuilder inputIfmBuilder =
283 new org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
284 .GetEgressActionsForInterfaceInputBuilder().setIntfName(input.getIntfName())
285 .setTunnelKey(input.getTunnelKey()).setActionKey(input.getActionKey());
286 SettableFuture<RpcResult<GetEgressActionsForTunnelOutput>> settableFuture = SettableFuture.create();
287 Futures.addCallback(interfaceManagerService.getEgressActionsForInterface(inputIfmBuilder.build()),
288 new FutureCallback<org.opendaylight.yang.gen.v1.urn.opendaylight.genius
289 .interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput>() {
291 public void onSuccess(org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs
292 .rev160406.@NonNull GetEgressActionsForInterfaceOutput result) {
293 GetEgressActionsForTunnelOutputBuilder output =
294 new GetEgressActionsForTunnelOutputBuilder().setAction(result.getAction());
295 settableFuture.set(RpcResultBuilder.<GetEgressActionsForTunnelOutput>success()
296 .withResult(output.build()).build());
300 public void onFailure(Throwable throwable) {
301 LOG.debug("RPC Call to Get egress actions failed for interface {}", tunnelName);
302 String errMsg = String.format("RPC call to get egress actions failed for interface %s",
304 settableFuture.set(RpcResultBuilder.<GetEgressActionsForTunnelOutput>failed()
305 .withError(RpcError.ErrorType.APPLICATION, errMsg, throwable).build());
307 } ,MoreExecutors.directExecutor());
308 return settableFuture;
310 return fromListenableFuture(LOG, input, () -> getEgressActionsForInternalTunnels(input.getIntfName(),
311 input.getTunnelKey() != null ? input.getTunnelKey().toJava() : null,
312 input.getActionKey())).onFailureLogLevel(LogLevel.ERROR).build();
317 public ListenableFuture<RpcResult<GetTunnelTypeOutput>> getTunnelType(GetTunnelTypeInput input) {
318 String tunnelName = input.getIntfName();
319 if (tunnelName == null) {
320 return Futures.immediateFuture(RpcResultBuilder.<GetTunnelTypeOutput>failed()
321 .withError(RpcError.ErrorType.APPLICATION,
322 "tunnel name not set for getTunnelType call").build());
325 if (!dpnTepStateCache.isInternal(tunnelName) || !interfaceManager.isItmDirectTunnelsEnabled()) {
326 org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
327 .GetTunnelTypeInputBuilder inputBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight
328 .genius.interfacemanager.rpcs.rev160406.GetTunnelTypeInputBuilder()
329 .setIntfName(input.getIntfName());
330 SettableFuture<RpcResult<GetTunnelTypeOutput>> settableFuture = SettableFuture.create();
331 Futures.addCallback(interfaceManagerService.getTunnelType(inputBuilder.build()),
332 new FutureCallback<org.opendaylight.yang.gen.v1.urn.opendaylight.genius
333 .interfacemanager.rpcs.rev160406.GetTunnelTypeOutput>() {
335 public void onSuccess(org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs
336 .rev160406.@NonNull GetTunnelTypeOutput result) {
337 GetTunnelTypeOutputBuilder output = new GetTunnelTypeOutputBuilder()
338 .setTunnelType(result.getTunnelType());
339 settableFuture.set(RpcResultBuilder.<GetTunnelTypeOutput>success()
340 .withResult(output.build()).build());
344 public void onFailure(Throwable throwable) {
345 LOG.debug("RPC Call to Get tunnel type failed for interface {}", tunnelName);
346 String errMsg = String.format("RPC to Get tunnel type failed for interface %s",
348 settableFuture.set(RpcResultBuilder.<GetTunnelTypeOutput>failed()
349 .withError(RpcError.ErrorType.APPLICATION, errMsg, throwable).build());
351 },MoreExecutors.directExecutor());
352 return settableFuture;
354 LOG.debug("get tunnel type from ITM for interface name {}", input.getIntfName());
355 return FutureRpcResults.fromBuilder(LOG, input, () -> {
356 DpnTepInterfaceInfo ifInfo = dpnTepStateCache.getTunnelFromCache(input.getIntfName());
357 return new GetTunnelTypeOutputBuilder().setTunnelType(ifInfo.getTunnelType());
363 public ListenableFuture<RpcResult<SetBfdParamOnTunnelOutput>> setBfdParamOnTunnel(
364 SetBfdParamOnTunnelInput input) {
365 final Uint64 srcDpnId = Uint64.valueOf(input.getSourceNode());
366 final Uint64 destDpnId = Uint64.valueOf(input.getDestinationNode());
367 LOG.debug("setBfdParamOnTunnel srcDpnId: {}, destDpnId: {}", srcDpnId, destDpnId);
368 final SettableFuture<RpcResult<SetBfdParamOnTunnelOutput>> result = SettableFuture.create();
369 FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
370 enableBFD(tx, srcDpnId, destDpnId, input.isMonitoringEnabled(), input.getMonitoringInterval().toJava());
371 enableBFD(tx, destDpnId, srcDpnId, input.isMonitoringEnabled(), input.getMonitoringInterval().toJava());
374 future.addCallback(new FutureCallback<Object>() {
376 public void onSuccess(Object voidInstance) {
377 result.set(RpcResultBuilder.<SetBfdParamOnTunnelOutput>success().build());
381 public void onFailure(Throwable error) {
382 String msg = "Unable to remove external tunnel from DPN";
383 LOG.error("remove ext tunnel failed. {}.", msg, error);
384 result.set(RpcResultBuilder.<SetBfdParamOnTunnelOutput>failed()
385 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
387 }, MoreExecutors.directExecutor());
391 private void enableBFD(TypedWriteTransaction<Datastore.Configuration> tx, Uint64 srcDpnId, Uint64 destDpnId,
392 final Boolean enabled, final Integer interval) throws ReadFailedException {
393 DpnTepInterfaceInfo dpnTepInterfaceInfo = dpnTepStateCache.getDpnTepInterface(srcDpnId, destDpnId);
394 RemoteDpnsBuilder remoteDpnsBuilder = new RemoteDpnsBuilder();
395 remoteDpnsBuilder.withKey(new RemoteDpnsKey(destDpnId)).setDestinationDpnId(destDpnId)
396 .setTunnelName(dpnTepInterfaceInfo.getTunnelName()).setInternal(dpnTepInterfaceInfo.isInternal())
397 .setMonitoringEnabled(enabled);
398 if (enabled && interval != null) {
399 remoteDpnsBuilder.setMonitoringInterval(interval);
401 RemoteDpns remoteDpn = remoteDpnsBuilder.build();
402 Optional<OvsBridgeRefEntry> ovsBridgeRefEntry = ovsBridgeRefEntryCache.get(srcDpnId);
403 LOG.debug("setBfdParamOnTunnel TunnelName: {}, ovsBridgeRefEntry: {}", dpnTepInterfaceInfo.getTunnelName(),
405 directTunnelUtils.updateBfdConfiguration(srcDpnId, remoteDpn, ovsBridgeRefEntry);
406 InstanceIdentifier<RemoteDpns> iid = InstanceIdentifier.builder(DpnTepsState.class)
407 .child(DpnsTeps.class, new DpnsTepsKey(srcDpnId))
408 .child(RemoteDpns.class,
409 new RemoteDpnsKey(destDpnId)).build();
410 tx.mergeParentStructureMerge(iid, remoteDpn);
414 public ListenableFuture<RpcResult<RemoveExternalTunnelEndpointOutput>> removeExternalTunnelEndpoint(
415 RemoveExternalTunnelEndpointInput input) {
416 //Ignore the Futures for now
417 final SettableFuture<RpcResult<RemoveExternalTunnelEndpointOutput>> result = SettableFuture.create();
418 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
419 FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
421 ItmExternalTunnelDeleteWorker.deleteTunnels(meshedDpnList, input.getDestinationIp(),
422 input.getTunnelType(), tx);
423 InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
424 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
428 future.addCallback(new FutureCallback<Object>() {
429 @Override public void onSuccess(Object voidInstance) {
430 result.set(RpcResultBuilder.<RemoveExternalTunnelEndpointOutput>success().build());
433 @Override public void onFailure(Throwable error) {
434 String msg = "Unable to delete DcGatewayIp " + input.getDestinationIp()
435 + " in datastore and tunnel type " + input.getTunnelType();
436 LOG.error("Unable to delete DcGatewayIp {} in datastore and tunnel type {}", input.getDestinationIp(),
437 input.getTunnelType());
438 result.set(RpcResultBuilder.<RemoveExternalTunnelEndpointOutput>failed()
439 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
441 }, MoreExecutors.directExecutor());
446 public ListenableFuture<RpcResult<RemoveExternalTunnelFromDpnsOutput>> removeExternalTunnelFromDpns(
447 RemoveExternalTunnelFromDpnsInput input) {
448 //Ignore the Futures for now
449 final SettableFuture<RpcResult<RemoveExternalTunnelFromDpnsOutput>> result = SettableFuture.create();
450 List<DPNTEPsInfo> cfgDpnList = ItmUtils.getDpnTepListFromDpnId(dpnTEPsInfoCache, input.getDpnId());
451 FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
452 tx -> ItmExternalTunnelDeleteWorker.deleteTunnels(cfgDpnList, input.getDestinationIp(),
453 input.getTunnelType(), tx));
455 future.addCallback(new FutureCallback<Object>() {
457 public void onSuccess(Object voidInstance) {
458 result.set(RpcResultBuilder.<RemoveExternalTunnelFromDpnsOutput>success().build());
462 public void onFailure(Throwable error) {
463 String msg = "Unable to remove external tunnel from DPN";
464 LOG.error("remove ext tunnel failed. {}.", msg, error);
465 result.set(RpcResultBuilder.<RemoveExternalTunnelFromDpnsOutput>failed()
466 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
468 }, MoreExecutors.directExecutor());
473 public ListenableFuture<RpcResult<BuildExternalTunnelFromDpnsOutput>> buildExternalTunnelFromDpns(
474 BuildExternalTunnelFromDpnsInput input) {
475 //Ignore the Futures for now
476 final SettableFuture<RpcResult<BuildExternalTunnelFromDpnsOutput>> result = SettableFuture.create();
477 FluentFuture<?> extTunnelResultList =
478 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
479 tx -> externalTunnelAddWorker.buildTunnelsFromDpnToExternalEndPoint(input.getDpnId(),
480 input.getDestinationIp(),input.getTunnelType(), tx));
482 extTunnelResultList.addCallback(new FutureCallback<Object>() {
484 public void onSuccess(Object voidInstance) {
485 result.set(RpcResultBuilder.<BuildExternalTunnelFromDpnsOutput>success().build());
489 public void onFailure(Throwable error) {
490 String msg = "Unable to create ext tunnel";
491 LOG.error("create ext tunnel failed. {}.", msg, error);
492 result.set(RpcResultBuilder.<BuildExternalTunnelFromDpnsOutput>failed()
493 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
495 }, MoreExecutors.directExecutor());
500 public ListenableFuture<RpcResult<AddExternalTunnelEndpointOutput>> addExternalTunnelEndpoint(
501 AddExternalTunnelEndpointInput input) {
502 // TODO Auto-generated method stub
504 //Ignore the Futures for now
505 final SettableFuture<RpcResult<AddExternalTunnelEndpointOutput>> result = SettableFuture.create();
506 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
507 InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
508 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
509 DcGatewayIp dcGatewayIp =
510 new DcGatewayIpBuilder().setIpAddress(input.getDestinationIp())
511 .setTunnnelType(input.getTunnelType()).build();
513 FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
515 externalTunnelAddWorker.buildTunnelsToExternalEndPoint(meshedDpnList, input.getDestinationIp(),
516 input.getTunnelType(), tx);
517 tx.mergeParentStructurePut(extPath, dcGatewayIp);
520 future.addCallback(new FutureCallback<Object>() {
521 @Override public void onSuccess(Object voidInstance) {
522 result.set(RpcResultBuilder.<AddExternalTunnelEndpointOutput>success().build());
525 @Override public void onFailure(Throwable error) {
527 "Unable to create DcGatewayIp {} in datastore for ip " + input.getDestinationIp() + "and "
528 + "tunnel type " + input.getTunnelType();
530 LOG.error("Unable to create DcGatewayIp in datastore for ip {} and tunnel type {}",
531 input.getDestinationIp() , input.getTunnelType());
532 result.set(RpcResultBuilder.<AddExternalTunnelEndpointOutput>failed()
533 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
535 }, MoreExecutors.directExecutor());
540 public ListenableFuture<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
541 GetExternalTunnelInterfaceNameInput input) {
542 SettableFuture.create();
543 RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
544 String sourceNode = input.getSourceNode();
545 String dstNode = input.getDestinationNode();
546 ExternalTunnelKey externalTunnelKey = new ExternalTunnelKey(dstNode, sourceNode, input.getTunnelType());
547 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
548 ExternalTunnelList.class)
549 .child(ExternalTunnel.class, externalTunnelKey);
550 ExternalTunnel exTunnel =
551 ItmUtils.getExternalTunnelbyExternalTunnelKey(externalTunnelKey, path, this.dataBroker);
552 if (exTunnel != null) {
553 GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder();
554 output.setInterfaceName(exTunnel.getTunnelInterfaceName());
555 resultBld = RpcResultBuilder.success();
556 resultBld.withResult(output.build());
558 resultBld = failed();
561 return Futures.immediateFuture(resultBld.build());
565 public ListenableFuture<RpcResult<CreateTerminatingServiceActionsOutput>>
566 createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
567 LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}",
568 input.getDpnId() , input.getServiceId(), input.getInstruction());
569 final SettableFuture<RpcResult<CreateTerminatingServiceActionsOutput>> result = SettableFuture.create();
570 Uint16 serviceId = input.getServiceId();
571 final List<MatchInfo> mkMatches = getTunnelMatchesForServiceId(serviceId);
573 Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
574 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, serviceId), 5,
575 "ITM Flow Entry :" + serviceId, 0, 0,
576 Uint64.fromLongBits(ITMConstants.COOKIE_ITM.longValue() + serviceId.toJava()), mkMatches,
577 input.getInstruction());
579 ListenableFuture<?> installFlowResult = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
580 tx -> mdsalManager.addFlow(tx, input.getDpnId(), terminatingServiceTableFlow));
581 Futures.addCallback(installFlowResult, new FutureCallback<Object>() {
584 public void onSuccess(Object voidInstance) {
585 result.set(RpcResultBuilder.<CreateTerminatingServiceActionsOutput>success().build());
589 public void onFailure(Throwable error) {
590 String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
591 LOG.error("create terminating service actions failed. {}", msg, error);
592 result.set(RpcResultBuilder.<CreateTerminatingServiceActionsOutput>failed()
593 .withError(RpcError.ErrorType.APPLICATION, msg, error)
596 }, MoreExecutors.directExecutor());
597 // result.set(RpcResultBuilder.<Void>success().build());
602 public ListenableFuture<RpcResult<RemoveTerminatingServiceActionsOutput>>
603 removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
604 LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}",
605 input.getDpnId(), input.getServiceId());
606 final SettableFuture<RpcResult<RemoveTerminatingServiceActionsOutput>> result = SettableFuture.create();
608 ListenableFuture<?> removeFlowResult = txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
609 tx -> mdsalManager.removeFlow(tx, input.getDpnId(),
610 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, input.getServiceId()),
611 NwConstants.INTERNAL_TUNNEL_TABLE));
612 Futures.addCallback(removeFlowResult, new FutureCallback<Object>() {
615 public void onSuccess(Object voidInstance) {
616 result.set(RpcResultBuilder.<RemoveTerminatingServiceActionsOutput>success().build());
620 public void onFailure(Throwable error) {
621 String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
622 LOG.error("remove terminating service actions failed. {}", msg, error);
623 result.set(RpcResultBuilder.<RemoveTerminatingServiceActionsOutput>failed()
624 .withError(RpcError.ErrorType.APPLICATION, msg, error)
627 }, MoreExecutors.directExecutor());
628 //result.set(RpcResultBuilder.<Void>success().build());
633 public List<MatchInfo> getTunnelMatchesForServiceId(Uint16 serviceId) {
634 final List<MatchInfo> mkMatches = new ArrayList<>();
637 mkMatches.add(new MatchTunnelId(Uint64.valueOf(serviceId)));
642 private String getFlowRef(long termSvcTable, Uint16 svcId) {
643 return String.valueOf(termSvcTable) + svcId;
647 public ListenableFuture<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
648 GetInternalOrExternalInterfaceNameInput input) {
649 RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = failed();
650 Uint64 srcDpn = input.getSourceDpid();
651 IpAddress dstIp = input.getDestinationIp() ;
652 InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(ExternalTunnelList.class)
653 .child(ExternalTunnel.class,
654 new ExternalTunnelKey(dstIp.stringValue(), srcDpn.toString(), input.getTunnelType()));
656 Optional<ExternalTunnel> optExtTunnel = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
658 if (optExtTunnel != null && optExtTunnel.isPresent()) {
659 ExternalTunnel extTunnel = optExtTunnel.get();
660 GetInternalOrExternalInterfaceNameOutputBuilder output =
661 new GetInternalOrExternalInterfaceNameOutputBuilder()
662 .setInterfaceName(extTunnel.getTunnelInterfaceName());
663 resultBld = RpcResultBuilder.success();
664 resultBld.withResult(output.build()) ;
666 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
668 // Look for external tunnels if not look for internal tunnel
669 for (DPNTEPsInfo teps : meshedDpnList) {
670 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
671 if (dstIp.equals(firstEndPt.getIpAddress())) {
672 Optional<InternalTunnel> optTunnel = Optional.empty();
673 if (interfaceManager.isItmDirectTunnelsEnabled()) {
674 DpnTepInterfaceInfo interfaceInfo =
675 dpnTepStateCache.getDpnTepInterface(srcDpn, teps.getDPNID());
676 if (interfaceInfo != null) {
677 resultBld = RpcResultBuilder.success();
678 resultBld.withResult(new GetInternalOrExternalInterfaceNameOutputBuilder()
679 .setInterfaceName(interfaceInfo.getTunnelName())).build();
680 return Futures.immediateFuture(resultBld.build());
684 if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
685 optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
686 TunnelTypeLogicalGroup.class, dataBroker);
687 LOG.debug("MULTIPLE_VxLAN_TUNNELS: getInternalOrExternalInterfaceName {}", optTunnel);
689 if (!optTunnel.isPresent()) {
690 optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
691 input.getTunnelType(), dataBroker);
693 if (optTunnel.isPresent()) {
694 InternalTunnel tunnel = optTunnel.get();
695 List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
696 if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
697 GetInternalOrExternalInterfaceNameOutputBuilder
699 new GetInternalOrExternalInterfaceNameOutputBuilder()
700 .setInterfaceName(tunnelInterfaces.get(0));
701 resultBld = RpcResultBuilder.success();
702 resultBld.withResult(output.build());
704 LOG.error("No tunnel interface found between source DPN {} ans destination IP {}", srcDpn,
709 LOG.error("Tunnel not found for source DPN {} ans destination IP {}", srcDpn, dstIp);
714 return Futures.immediateFuture(resultBld.build());
717 @SuppressWarnings("checkstyle:IllegalCatch")
719 public ListenableFuture<RpcResult<DeleteL2GwDeviceOutput>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
720 final SettableFuture<RpcResult<DeleteL2GwDeviceOutput>> result = SettableFuture.create();
721 boolean foundVxlanTzone = false;
723 final IpAddress hwIp = input.getIpAddress();
724 final String nodeId = input.getNodeId();
725 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
726 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
727 containerPath, dataBroker);
728 if (transportZonesOptional.isPresent()) {
729 TransportZones transportZones = transportZonesOptional.get();
730 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
731 LOG.error("No teps configured");
732 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
733 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
736 for (TransportZone tzone : transportZones.getTransportZone()) {
737 if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
740 foundVxlanTzone = true;
741 String transportZone = tzone.getZoneName();
742 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
743 InstanceIdentifier<DeviceVteps> path = InstanceIdentifier
744 .builder(TransportZones.class)
745 .child(TransportZone.class,
746 new TransportZoneKey(transportZone))
747 .child(DeviceVteps.class, deviceVtepKey)
749 FluentFuture<?> future =
750 retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> tx.delete(path));
751 future.addCallback(new FutureCallback<Object>() {
752 @Override public void onSuccess(Object voidInstance) {
753 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>success().build());
756 @Override public void onFailure(Throwable error) {
757 String msg = String.format("Unable to delete HwVtep %s from datastore", nodeId);
758 LOG.error("Unable to delete HwVtep {}, {} from datastore", nodeId, hwIp);
759 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
760 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
762 }, MoreExecutors.directExecutor());
765 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
766 .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
770 if (!foundVxlanTzone) {
771 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
772 .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
777 } catch (Exception e) {
778 RpcResultBuilder<DeleteL2GwDeviceOutput> resultBuilder = RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
779 .withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
780 return Futures.immediateFuture(resultBuilder.build());
784 @SuppressWarnings("checkstyle:IllegalCatch")
786 public ListenableFuture<RpcResult<AddL2GwDeviceOutput>> addL2GwDevice(AddL2GwDeviceInput input) {
788 final SettableFuture<RpcResult<AddL2GwDeviceOutput>> result = SettableFuture.create();
789 boolean foundVxlanTzone = false;
791 final IpAddress hwIp = input.getIpAddress();
792 final String nodeId = input.getNodeId();
793 //iterate through all transport zones and put TORs under vxlan
794 //if no vxlan tzone is cnfigured, return an error.
795 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
796 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
797 containerPath, dataBroker);
798 if (transportZonesOptional.isPresent()) {
799 TransportZones transportZones = transportZonesOptional.get();
800 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
801 LOG.error("No transportZone configured");
802 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
803 .withError(RpcError.ErrorType.APPLICATION, "No transportZone Configured").build());
806 for (TransportZone tzone : transportZones.getTransportZone()) {
807 if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
810 String transportZone = tzone.getZoneName();
811 foundVxlanTzone = true;
812 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
813 InstanceIdentifier<DeviceVteps> path = InstanceIdentifier
814 .builder(TransportZones.class)
815 .child(TransportZone.class,
816 new TransportZoneKey(transportZone))
817 .child(DeviceVteps.class, deviceVtepKey)
819 DeviceVteps deviceVtep = new DeviceVtepsBuilder().withKey(deviceVtepKey).setIpAddress(hwIp)
820 .setNodeId(nodeId).setTopologyId(input.getTopologyId()).build();
821 //TO DO: add retry if it fails
822 FluentFuture<?> future = retryingTxRunner
823 .callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
824 tx -> tx.mergeParentStructurePut(path, deviceVtep));
826 future.addCallback(new FutureCallback<Object>() {
828 @Override public void onSuccess(Object voidInstance) {
829 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>success().build());
832 @Override public void onFailure(Throwable error) {
833 String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
834 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId, hwIp);
835 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
836 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
838 }, MoreExecutors.directExecutor());
842 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
843 .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
847 if (!foundVxlanTzone) {
848 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
849 .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
854 } catch (Exception e) {
855 RpcResultBuilder<AddL2GwDeviceOutput> resultBuilder = RpcResultBuilder.<AddL2GwDeviceOutput>failed()
856 .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
857 return Futures.immediateFuture(resultBuilder.build());
862 public ListenableFuture<RpcResult<GetWatchPortForTunnelOutput>> getWatchPortForTunnel(
863 GetWatchPortForTunnelInput input) {
864 throw new UnsupportedOperationException("TODO");
867 @SuppressWarnings("checkstyle:IllegalCatch")
869 public ListenableFuture<RpcResult<AddL2GwMlagDeviceOutput>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input) {
871 final SettableFuture<RpcResult<AddL2GwMlagDeviceOutput>> result = SettableFuture.create();
873 final IpAddress hwIp = input.getIpAddress();
874 final List<String> nodeId = input.getNodeId();
875 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
876 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
877 containerPath, dataBroker);
878 if (transportZonesOptional.isPresent()) {
879 TransportZones transportZones = transportZonesOptional.get();
880 if (transportZones.getTransportZone() == null || transportZones.getTransportZone()
882 LOG.error("No teps configured");
883 result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
884 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
887 for (TransportZone tzone : transportZones.getTransportZone()) {
888 if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
891 String transportZone = tzone.getZoneName();
892 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
893 InstanceIdentifier<DeviceVteps> path =
894 InstanceIdentifier.builder(TransportZones.class)
895 .child(TransportZone.class, new TransportZoneKey(transportZone))
896 .child(DeviceVteps.class, deviceVtepKey).build();
897 DeviceVteps deviceVtep = new DeviceVtepsBuilder().withKey(deviceVtepKey)
899 .setNodeId(nodeId.get(0)).setTopologyId(input.getTopologyId()).build();
900 LOG.trace("writing hWvtep{}", deviceVtep);
901 FluentFuture<?> future =
902 retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
904 tx.mergeParentStructurePut(path, deviceVtep);
905 if (nodeId.size() == 2) {
906 LOG.trace("second node-id {}", nodeId.get(1));
907 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp,
909 InstanceIdentifier<DeviceVteps> path2 = InstanceIdentifier
910 .builder(TransportZones.class)
911 .child(TransportZone.class, new TransportZoneKey(transportZone))
912 .child(DeviceVteps.class, deviceVtepKey2).build();
913 DeviceVteps deviceVtep2 = new DeviceVtepsBuilder()
914 .withKey(deviceVtepKey2)
915 .setIpAddress(hwIp).setNodeId(nodeId.get(1))
916 .setTopologyId(input.getTopologyId()).build();
917 LOG.trace("writing {}", deviceVtep2);
918 tx.mergeParentStructurePut(path2, deviceVtep2);
921 future.addCallback(new FutureCallback<Object>() {
923 public void onSuccess(Object voidInstance) {
924 result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>success().build());
928 public void onFailure(Throwable error) {
930 .format("Unable to write HwVtep %s to datastore", nodeId);
931 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId, hwIp);
932 result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
933 .withError(RpcError.ErrorType.APPLICATION, msg, error)
936 }, MoreExecutors.directExecutor());
940 } catch (RuntimeException e) {
941 RpcResultBuilder<AddL2GwMlagDeviceOutput> resultBuilder = RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
942 .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
943 return Futures.immediateFuture(resultBuilder.build());
947 @SuppressWarnings("checkstyle:IllegalCatch")
949 public ListenableFuture<RpcResult<DeleteL2GwMlagDeviceOutput>> deleteL2GwMlagDevice(
950 DeleteL2GwMlagDeviceInput input) {
951 final SettableFuture<RpcResult<DeleteL2GwMlagDeviceOutput>> result = SettableFuture.create();
953 final IpAddress hwIp = input.getIpAddress();
954 final List<String> nodeId = input.getNodeId();
955 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
956 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
957 containerPath, dataBroker);
958 if (transportZonesOptional.isPresent()) {
959 TransportZones tzones = transportZonesOptional.get();
960 if (tzones.getTransportZone() == null || tzones.getTransportZone().isEmpty()) {
961 LOG.error("No teps configured");
962 result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed()
963 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
966 String transportZone = tzones.getTransportZone().get(0).getZoneName();
967 FluentFuture<?> future =
968 retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
970 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
971 InstanceIdentifier<DeviceVteps> path =
972 InstanceIdentifier.builder(TransportZones.class)
973 .child(TransportZone.class, new TransportZoneKey(transportZone))
974 .child(DeviceVteps.class,
975 deviceVtepKey).build();
977 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
978 InstanceIdentifier<DeviceVteps> path2 =
979 InstanceIdentifier.builder(TransportZones.class)
980 .child(TransportZone.class, new TransportZoneKey(transportZone))
981 .child(DeviceVteps.class,
982 deviceVtepKey2).build();
987 future.addCallback(new FutureCallback<Object>() {
990 public void onSuccess(Object voidInstance) {
991 result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>success().build());
995 public void onFailure(Throwable error) {
996 String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
997 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
998 result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed()
999 .withError(RpcError.ErrorType.APPLICATION, msg, error)
1002 }, MoreExecutors.directExecutor());
1005 } catch (Exception e) {
1006 RpcResultBuilder<DeleteL2GwMlagDeviceOutput> resultBuilder =
1007 RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed().withError(RpcError.ErrorType.APPLICATION,
1008 "Deleting l2 Gateway to DS Failed", e);
1009 return Futures.immediateFuture(resultBuilder.build());
1014 public ListenableFuture<RpcResult<IsTunnelInternalOrExternalOutput>> isTunnelInternalOrExternal(
1015 IsTunnelInternalOrExternalInput input) {
1016 RpcResultBuilder<IsTunnelInternalOrExternalOutput> resultBld;
1017 String tunIfName = input.getTunnelInterfaceName();
1019 IsTunnelInternalOrExternalOutputBuilder output = new IsTunnelInternalOrExternalOutputBuilder()
1020 .setTunnelType(tunVal);
1022 if (ItmUtils.ITM_CACHE.getInternalTunnel(tunIfName) != null) {
1024 } else if (ItmUtils.ITM_CACHE.getExternalTunnel(tunIfName) != null) {
1027 output.setTunnelType(tunVal);
1028 resultBld = RpcResultBuilder.success();
1029 resultBld.withResult(output.build());
1030 return Futures.immediateFuture(resultBld.build());
1034 public ListenableFuture<RpcResult<IsDcgwPresentOutput>> isDcgwPresent(IsDcgwPresentInput input) {
1035 RpcResultBuilder<IsDcgwPresentOutput> resultBld = RpcResultBuilder.success();
1037 Map<DcGatewayIpKey, DcGatewayIp> dcGatewayIpList = new HashMap<>();
1038 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
1039 tx -> dcGatewayIpList.putAll(getDcGatewayIpList(tx))).isDone();
1040 String dcgwIpStr = input.getDcgwIp();
1041 IpAddress dcgwIpAddr = IpAddressBuilder.getDefaultInstance(dcgwIpStr);
1044 if (!dcGatewayIpList.isEmpty()
1045 && dcGatewayIpList.values().stream().anyMatch(gwIp -> Objects.equal(gwIp.getIpAddress(), dcgwIpAddr))) {
1048 IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
1049 resultBld.withResult(output.build());
1053 IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
1054 resultBld.withResult(output.build());
1056 return Futures.immediateFuture(resultBld.build());
1060 public ListenableFuture<RpcResult<GetDpnEndpointIpsOutput>> getDpnEndpointIps(GetDpnEndpointIpsInput input) {
1061 Uint64 srcDpn = input.getSourceDpid();
1062 RpcResultBuilder<GetDpnEndpointIpsOutput> resultBld = failed();
1063 InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
1064 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class,
1065 new DPNTEPsInfoKey(srcDpn)).build();
1066 Optional<DPNTEPsInfo> tunnelInfo = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tunnelInfoId, dataBroker);
1067 if (!tunnelInfo.isPresent()) {
1068 LOG.error("tunnelInfo is not present");
1069 return Futures.immediateFuture(resultBld.build());
1072 List<TunnelEndPoints> tunnelEndPointList = tunnelInfo.get().getTunnelEndPoints();
1073 if (tunnelEndPointList == null || tunnelEndPointList.isEmpty()) {
1074 LOG.error("tunnelEndPointList is null or empty");
1075 return Futures.immediateFuture(resultBld.build());
1078 List<IpAddress> nexthopIpList = new ArrayList<>();
1079 tunnelEndPointList.forEach(tunnelEndPoint -> nexthopIpList.add(tunnelEndPoint.getIpAddress()));
1081 GetDpnEndpointIpsOutputBuilder output = new GetDpnEndpointIpsOutputBuilder().setNexthopipList(nexthopIpList);
1082 resultBld = RpcResultBuilder.success();
1083 resultBld.withResult(output.build()) ;
1084 return Futures.immediateFuture(resultBld.build());
1088 public ListenableFuture<RpcResult<GetDpnInfoOutput>> getDpnInfo(GetDpnInfoInput input) {
1089 return FutureRpcResults.fromListenableFuture(LOG, "getDpnInfo", input,
1090 () -> Futures.immediateFuture(getDpnInfoInternal(input))).build();
1093 private GetDpnInfoOutput getDpnInfoInternal(GetDpnInfoInput input) throws ReadFailedException {
1094 Map<String, Uint64> computeNamesVsDpnIds
1095 = getDpnIdByComputeNodeNameFromOpInventoryNodes(input.getComputeNames());
1096 Map<Uint64, ComputesBuilder> dpnIdVsVtepsComputes
1097 = getTunnelEndPointByDpnIdFromTranPortZone(computeNamesVsDpnIds.values());
1098 List<Computes> computes = computeNamesVsDpnIds.entrySet().stream()
1099 .map(entry -> dpnIdVsVtepsComputes.get(entry.getValue()).setComputeName(entry.getKey()).build())
1100 .collect(Collectors.toList());
1101 return new GetDpnInfoOutputBuilder().setComputes(computes).build();
1104 private Map<Uint64, ComputesBuilder> getTunnelEndPointByDpnIdFromTranPortZone(Collection<Uint64> dpnIds)
1105 throws ReadFailedException {
1106 TransportZones transportZones = singleTransactionDataBroker.syncRead(
1107 LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(TransportZones.class).build());
1108 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
1109 throw new IllegalStateException("Failed to find transport zones in config datastore");
1111 Map<Uint64, ComputesBuilder> result = new HashMap<>();
1112 for (TransportZone transportZone : transportZones.getTransportZone()) {
1113 for (Vteps vtep : transportZone.getVteps().values()) {
1114 if (dpnIds.contains(vtep.getDpnId())) {
1115 result.putIfAbsent(vtep.getDpnId(),
1116 new ComputesBuilder()
1117 .setZoneName(transportZone.getZoneName())
1118 .setDpnId(vtep.getDpnId())
1119 .setNodeId(getNodeId(vtep.getDpnId()))
1120 .setTepIp(Collections.singletonList(vtep.getIpAddress())));
1124 for (Uint64 dpnId : dpnIds) {
1125 if (!result.containsKey(dpnId)) {
1126 throw new IllegalStateException("Failed to find dpn id " + dpnId + " in transport zone");
1132 private Map<String, Uint64> getDpnIdByComputeNodeNameFromOpInventoryNodes(List<String> nodeNames)
1133 throws ReadFailedException {
1134 Nodes operInventoryNodes = singleTransactionDataBroker.syncRead(
1135 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(Nodes.class).build());
1136 if (operInventoryNodes.getNode() == null || operInventoryNodes.getNode().isEmpty()) {
1137 throw new IllegalStateException("Failed to find operational inventory nodes datastore");
1139 Map<String, Uint64> result = new HashMap<>();
1140 for (Node node : operInventoryNodes.getNode().values()) {
1141 String name = node.augmentation(FlowCapableNode.class).getDescription();
1142 if (nodeNames.contains(name)) {
1143 String[] nodeId = node.getId().getValue().split(":");
1144 result.put(name, Uint64.valueOf(nodeId[1]));
1147 for (String nodeName : nodeNames) {
1148 if (!result.containsKey(nodeName)) {
1149 throw new IllegalStateException("Failed to find dpn id of compute node name from oper inventory "
1156 private String getNodeId(Uint64 dpnId) throws ReadFailedException {
1157 InstanceIdentifier<BridgeRefEntry> path = InstanceIdentifier
1158 .builder(BridgeRefInfo.class)
1159 .child(BridgeRefEntry.class, new BridgeRefEntryKey(dpnId)).build();
1160 BridgeRefEntry bridgeRefEntry =
1161 singleTransactionDataBroker.syncRead(LogicalDatastoreType.OPERATIONAL, path);
1162 return bridgeRefEntry.getBridgeReference().getValue()
1163 .firstKeyOf(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021
1164 .network.topology.topology.Node.class).getNodeId().getValue();
1167 private ListenableFuture<GetEgressActionsForTunnelOutput>
1168 getEgressActionsForInternalTunnels(String interfaceName, Long tunnelKey, Integer actionKey)
1169 throws ExecutionException, InterruptedException, OperationFailedException {
1171 DpnTepInterfaceInfo interfaceInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
1172 if (interfaceInfo == null) {
1173 throw new IllegalStateException("Interface information not present in config DS for" + interfaceName);
1176 String tunnelType = ItmUtils.convertTunnelTypetoString(interfaceInfo.getTunnelType());
1177 if (!tunnelType.equalsIgnoreCase(ITMConstants.TUNNEL_TYPE_VXLAN)) {
1178 throw new IllegalArgumentException(tunnelType + " tunnel not handled by ITM");
1181 Optional<DPNTEPsInfo> dpntePsInfoOptional = dpnTEPsInfoCache.get(InstanceIdentifier.builder(DpnEndpoints.class)
1182 .child(DPNTEPsInfo.class, new DPNTEPsInfoKey(
1183 // FIXME: the cache should be caching this value, not just as a String
1184 Uint64.valueOf(dpnTepStateCache.getTunnelEndPointInfoFromCache(interfaceInfo.getTunnelName())
1185 .getDstEndPointInfo())))
1188 if (dpntePsInfoOptional.isPresent()) {
1189 dstId = dpntePsInfoOptional.get().getDstId();
1191 dstId = directTunnelUtils.allocateId(ITMConstants.ITM_IDPOOL_NAME, interfaceInfo.getRemoteDPN().toString());
1194 List<ActionInfo> result = new ArrayList<>();
1195 long regValue = MetaDataUtil.getRemoteDpnMetadatForEgressTunnelTable(dstId);
1196 int actionKeyStart = actionKey == null ? 0 : actionKey;
1197 result.add(new ActionSetFieldTunnelId(actionKeyStart++,
1198 Uint64.valueOf(tunnelKey != null ? tunnelKey : 0L)));
1199 result.add(new ActionRegLoad(actionKeyStart++, NxmNxReg6.class, MetaDataUtil.REG6_START_INDEX,
1200 MetaDataUtil.REG6_END_INDEX, regValue));
1201 result.add(new ActionNxResubmit(actionKeyStart, NwConstants.EGRESS_TUNNEL_TABLE));
1203 return Futures.immediateFuture(new GetEgressActionsForTunnelOutputBuilder()
1204 .setAction(result.stream().map(ActionInfo::buildAction).collect(Collectors.toList())).build());
1207 public static Map<DcGatewayIpKey, DcGatewayIp>
1208 getDcGatewayIpList(TypedReadWriteTransaction<Datastore.Configuration> tx)
1209 throws ExecutionException, InterruptedException {
1210 Map<DcGatewayIpKey, DcGatewayIp> dcGatewayIpMap = new HashMap<>();
1211 FluentFuture<Optional<DcGatewayIpList>> future =
1212 tx.read(InstanceIdentifier.builder(DcGatewayIpList.class).build());
1213 future.addCallback(new FutureCallback<Optional<DcGatewayIpList>>() {
1215 public void onSuccess(Optional<DcGatewayIpList> optional) {
1217 // FIXME: why not just use the provided optional?
1218 Optional<DcGatewayIpList> opt = future.get();
1219 if (opt.isPresent()) {
1220 DcGatewayIpList list = opt.get();
1222 dcGatewayIpMap.putAll(list.getDcGatewayIp());
1225 } catch (ExecutionException | InterruptedException e) {
1226 LOG.error("DcGateway IpList read failed", e);
1231 public void onFailure(Throwable error) {
1232 LOG.error("DcGateway IpList read failed", error);
1234 }, MoreExecutors.directExecutor());
1235 return dcGatewayIpMap;