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.genius.infra.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.infra.Datastore;
37 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
38 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
39 import org.opendaylight.genius.infra.RetryingManagedNewTransactionRunner;
40 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
41 import org.opendaylight.genius.infra.TypedWriteTransaction;
42 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
43 import org.opendaylight.genius.interfacemanager.interfaces.InterfaceManagerService;
44 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
45 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
46 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
47 import org.opendaylight.genius.itm.cache.TunnelStateCache;
48 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker;
49 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelDeleteWorker;
50 import org.opendaylight.genius.itm.globals.ITMConstants;
51 import org.opendaylight.genius.itm.impl.ItmUtils;
52 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
53 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
54 import org.opendaylight.genius.mdsalutil.ActionInfo;
55 import org.opendaylight.genius.mdsalutil.MDSALUtil;
56 import org.opendaylight.genius.mdsalutil.MatchInfo;
57 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
58 import org.opendaylight.genius.mdsalutil.NwConstants;
59 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
60 import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
61 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
62 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
63 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
64 import org.opendaylight.mdsal.binding.api.DataBroker;
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<Void> 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<Void>() {
376 public void onSuccess(Void 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<Void> 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<Void>() {
429 @Override public void onSuccess(Void 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<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
452 tx -> ItmExternalTunnelDeleteWorker.deleteTunnels(cfgDpnList, input.getDestinationIp(),
453 input.getTunnelType(), tx));
455 future.addCallback(new FutureCallback<Void>() {
457 public void onSuccess(Void 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<Void> extTunnelResultList =
478 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
479 tx -> externalTunnelAddWorker.buildTunnelsFromDpnToExternalEndPoint(input.getDpnId(),
480 input.getDestinationIp(),input.getTunnelType(), tx));
482 extTunnelResultList.addCallback(new FutureCallback<Void>() {
485 public void onSuccess(Void voidInstance) {
486 result.set(RpcResultBuilder.<BuildExternalTunnelFromDpnsOutput>success().build());
490 public void onFailure(Throwable error) {
491 String msg = "Unable to create ext tunnel";
492 LOG.error("create ext tunnel failed. {}.", msg, error);
493 result.set(RpcResultBuilder.<BuildExternalTunnelFromDpnsOutput>failed()
494 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
496 }, MoreExecutors.directExecutor());
501 public ListenableFuture<RpcResult<AddExternalTunnelEndpointOutput>> addExternalTunnelEndpoint(
502 AddExternalTunnelEndpointInput input) {
503 // TODO Auto-generated method stub
505 //Ignore the Futures for now
506 final SettableFuture<RpcResult<AddExternalTunnelEndpointOutput>> result = SettableFuture.create();
507 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
508 InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
509 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
510 DcGatewayIp dcGatewayIp =
511 new DcGatewayIpBuilder().setIpAddress(input.getDestinationIp())
512 .setTunnnelType(input.getTunnelType()).build();
514 FluentFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
516 externalTunnelAddWorker.buildTunnelsToExternalEndPoint(meshedDpnList, input.getDestinationIp(),
517 input.getTunnelType(), tx);
518 tx.mergeParentStructurePut(extPath, dcGatewayIp);
521 future.addCallback(new FutureCallback<Void>() {
522 @Override public void onSuccess(Void voidInstance) {
523 result.set(RpcResultBuilder.<AddExternalTunnelEndpointOutput>success().build());
526 @Override public void onFailure(Throwable error) {
528 "Unable to create DcGatewayIp {} in datastore for ip " + input.getDestinationIp() + "and "
529 + "tunnel type " + input.getTunnelType();
531 LOG.error("Unable to create DcGatewayIp in datastore for ip {} and tunnel type {}",
532 input.getDestinationIp() , input.getTunnelType());
533 result.set(RpcResultBuilder.<AddExternalTunnelEndpointOutput>failed()
534 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
536 }, MoreExecutors.directExecutor());
541 public ListenableFuture<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
542 GetExternalTunnelInterfaceNameInput input) {
543 SettableFuture.create();
544 RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
545 String sourceNode = input.getSourceNode();
546 String dstNode = input.getDestinationNode();
547 ExternalTunnelKey externalTunnelKey = new ExternalTunnelKey(dstNode, sourceNode, input.getTunnelType());
548 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
549 ExternalTunnelList.class)
550 .child(ExternalTunnel.class, externalTunnelKey);
551 ExternalTunnel exTunnel =
552 ItmUtils.getExternalTunnelbyExternalTunnelKey(externalTunnelKey, path, this.dataBroker);
553 if (exTunnel != null) {
554 GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder();
555 output.setInterfaceName(exTunnel.getTunnelInterfaceName());
556 resultBld = RpcResultBuilder.success();
557 resultBld.withResult(output.build());
559 resultBld = failed();
562 return Futures.immediateFuture(resultBld.build());
566 public ListenableFuture<RpcResult<CreateTerminatingServiceActionsOutput>>
567 createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
568 LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}",
569 input.getDpnId() , input.getServiceId(), input.getInstruction());
570 final SettableFuture<RpcResult<CreateTerminatingServiceActionsOutput>> result = SettableFuture.create();
571 Uint16 serviceId = input.getServiceId();
572 final List<MatchInfo> mkMatches = getTunnelMatchesForServiceId(serviceId);
574 Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
575 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, serviceId), 5,
576 "ITM Flow Entry :" + serviceId, 0, 0,
577 Uint64.fromLongBits(ITMConstants.COOKIE_ITM.longValue() + serviceId.toJava()), mkMatches,
578 input.getInstruction());
580 ListenableFuture<Void> installFlowResult = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
581 tx -> mdsalManager.addFlow(tx, input.getDpnId(), terminatingServiceTableFlow));
582 Futures.addCallback(installFlowResult, new FutureCallback<Void>() {
585 public void onSuccess(Void voidInstance) {
586 result.set(RpcResultBuilder.<CreateTerminatingServiceActionsOutput>success().build());
590 public void onFailure(Throwable error) {
591 String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
592 LOG.error("create terminating service actions failed. {}", msg, error);
593 result.set(RpcResultBuilder.<CreateTerminatingServiceActionsOutput>failed()
594 .withError(RpcError.ErrorType.APPLICATION, msg, error)
597 }, MoreExecutors.directExecutor());
598 // result.set(RpcResultBuilder.<Void>success().build());
603 public ListenableFuture<RpcResult<RemoveTerminatingServiceActionsOutput>>
604 removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
605 LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}",
606 input.getDpnId(), input.getServiceId());
607 final SettableFuture<RpcResult<RemoveTerminatingServiceActionsOutput>> result = SettableFuture.create();
609 ListenableFuture<Void> removeFlowResult = txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
610 tx -> mdsalManager.removeFlow(tx, input.getDpnId(),
611 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, input.getServiceId()),
612 NwConstants.INTERNAL_TUNNEL_TABLE));
613 Futures.addCallback(removeFlowResult, new FutureCallback<Void>() {
616 public void onSuccess(Void voidInstance) {
617 result.set(RpcResultBuilder.<RemoveTerminatingServiceActionsOutput>success().build());
621 public void onFailure(Throwable error) {
622 String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
623 LOG.error("remove terminating service actions failed. {}", msg, error);
624 result.set(RpcResultBuilder.<RemoveTerminatingServiceActionsOutput>failed()
625 .withError(RpcError.ErrorType.APPLICATION, msg, error)
628 }, MoreExecutors.directExecutor());
629 //result.set(RpcResultBuilder.<Void>success().build());
634 public List<MatchInfo> getTunnelMatchesForServiceId(Uint16 serviceId) {
635 final List<MatchInfo> mkMatches = new ArrayList<>();
638 mkMatches.add(new MatchTunnelId(Uint64.valueOf(serviceId)));
643 private String getFlowRef(long termSvcTable, Uint16 svcId) {
644 return String.valueOf(termSvcTable) + svcId;
648 public ListenableFuture<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
649 GetInternalOrExternalInterfaceNameInput input) {
650 RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = failed();
651 Uint64 srcDpn = input.getSourceDpid();
652 IpAddress dstIp = input.getDestinationIp() ;
653 InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(ExternalTunnelList.class)
654 .child(ExternalTunnel.class,
655 new ExternalTunnelKey(dstIp.stringValue(), srcDpn.toString(), input.getTunnelType()));
657 Optional<ExternalTunnel> optExtTunnel = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
659 if (optExtTunnel != null && optExtTunnel.isPresent()) {
660 ExternalTunnel extTunnel = optExtTunnel.get();
661 GetInternalOrExternalInterfaceNameOutputBuilder output =
662 new GetInternalOrExternalInterfaceNameOutputBuilder()
663 .setInterfaceName(extTunnel.getTunnelInterfaceName());
664 resultBld = RpcResultBuilder.success();
665 resultBld.withResult(output.build()) ;
667 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
669 // Look for external tunnels if not look for internal tunnel
670 for (DPNTEPsInfo teps : meshedDpnList) {
671 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
672 if (dstIp.equals(firstEndPt.getIpAddress())) {
673 Optional<InternalTunnel> optTunnel = Optional.empty();
674 if (interfaceManager.isItmDirectTunnelsEnabled()) {
675 DpnTepInterfaceInfo interfaceInfo =
676 dpnTepStateCache.getDpnTepInterface(srcDpn, teps.getDPNID());
677 if (interfaceInfo != null) {
678 resultBld = RpcResultBuilder.success();
679 resultBld.withResult(new GetInternalOrExternalInterfaceNameOutputBuilder()
680 .setInterfaceName(interfaceInfo.getTunnelName())).build();
681 return Futures.immediateFuture(resultBld.build());
685 if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
686 optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
687 TunnelTypeLogicalGroup.class, dataBroker);
688 LOG.debug("MULTIPLE_VxLAN_TUNNELS: getInternalOrExternalInterfaceName {}", optTunnel);
690 if (!optTunnel.isPresent()) {
691 optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
692 input.getTunnelType(), dataBroker);
694 if (optTunnel.isPresent()) {
695 InternalTunnel tunnel = optTunnel.get();
696 List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
697 if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
698 GetInternalOrExternalInterfaceNameOutputBuilder
700 new GetInternalOrExternalInterfaceNameOutputBuilder()
701 .setInterfaceName(tunnelInterfaces.get(0));
702 resultBld = RpcResultBuilder.success();
703 resultBld.withResult(output.build());
705 LOG.error("No tunnel interface found between source DPN {} ans destination IP {}", srcDpn,
710 LOG.error("Tunnel not found for source DPN {} ans destination IP {}", srcDpn, dstIp);
715 return Futures.immediateFuture(resultBld.build());
718 @SuppressWarnings("checkstyle:IllegalCatch")
720 public ListenableFuture<RpcResult<DeleteL2GwDeviceOutput>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
721 final SettableFuture<RpcResult<DeleteL2GwDeviceOutput>> result = SettableFuture.create();
722 boolean foundVxlanTzone = false;
724 final IpAddress hwIp = input.getIpAddress();
725 final String nodeId = input.getNodeId();
726 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
727 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
728 containerPath, dataBroker);
729 if (transportZonesOptional.isPresent()) {
730 TransportZones transportZones = transportZonesOptional.get();
731 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
732 LOG.error("No teps configured");
733 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
734 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
737 for (TransportZone tzone : transportZones.getTransportZone()) {
738 if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
741 foundVxlanTzone = true;
742 String transportZone = tzone.getZoneName();
743 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
744 InstanceIdentifier<DeviceVteps> path = InstanceIdentifier
745 .builder(TransportZones.class)
746 .child(TransportZone.class,
747 new TransportZoneKey(transportZone))
748 .child(DeviceVteps.class, deviceVtepKey)
750 FluentFuture<Void> future =
751 retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> tx.delete(path));
752 future.addCallback(new FutureCallback<Void>() {
753 @Override public void onSuccess(Void voidInstance) {
754 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>success().build());
757 @Override public void onFailure(Throwable error) {
758 String msg = String.format("Unable to delete HwVtep %s from datastore", nodeId);
759 LOG.error("Unable to delete HwVtep {}, {} from datastore", nodeId, hwIp);
760 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
761 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
763 }, MoreExecutors.directExecutor());
766 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
767 .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
771 if (!foundVxlanTzone) {
772 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
773 .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
778 } catch (Exception e) {
779 RpcResultBuilder<DeleteL2GwDeviceOutput> resultBuilder = RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
780 .withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
781 return Futures.immediateFuture(resultBuilder.build());
785 @SuppressWarnings("checkstyle:IllegalCatch")
787 public ListenableFuture<RpcResult<AddL2GwDeviceOutput>> addL2GwDevice(AddL2GwDeviceInput input) {
789 final SettableFuture<RpcResult<AddL2GwDeviceOutput>> result = SettableFuture.create();
790 boolean foundVxlanTzone = false;
792 final IpAddress hwIp = input.getIpAddress();
793 final String nodeId = input.getNodeId();
794 //iterate through all transport zones and put TORs under vxlan
795 //if no vxlan tzone is cnfigured, return an error.
796 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
797 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
798 containerPath, dataBroker);
799 if (transportZonesOptional.isPresent()) {
800 TransportZones transportZones = transportZonesOptional.get();
801 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
802 LOG.error("No transportZone configured");
803 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
804 .withError(RpcError.ErrorType.APPLICATION, "No transportZone Configured").build());
807 for (TransportZone tzone : transportZones.getTransportZone()) {
808 if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
811 String transportZone = tzone.getZoneName();
812 foundVxlanTzone = true;
813 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
814 InstanceIdentifier<DeviceVteps> path = InstanceIdentifier
815 .builder(TransportZones.class)
816 .child(TransportZone.class,
817 new TransportZoneKey(transportZone))
818 .child(DeviceVteps.class, deviceVtepKey)
820 DeviceVteps deviceVtep = new DeviceVtepsBuilder().withKey(deviceVtepKey).setIpAddress(hwIp)
821 .setNodeId(nodeId).setTopologyId(input.getTopologyId()).build();
822 //TO DO: add retry if it fails
823 FluentFuture<Void> future = retryingTxRunner
824 .callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
825 tx -> tx.mergeParentStructurePut(path, deviceVtep));
827 future.addCallback(new FutureCallback<Void>() {
829 @Override public void onSuccess(Void voidInstance) {
830 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>success().build());
833 @Override public void onFailure(Throwable error) {
834 String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
835 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId, hwIp);
836 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
837 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
839 }, MoreExecutors.directExecutor());
843 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
844 .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
848 if (!foundVxlanTzone) {
849 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
850 .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
855 } catch (Exception e) {
856 RpcResultBuilder<AddL2GwDeviceOutput> resultBuilder = RpcResultBuilder.<AddL2GwDeviceOutput>failed()
857 .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
858 return Futures.immediateFuture(resultBuilder.build());
863 public ListenableFuture<RpcResult<GetWatchPortForTunnelOutput>> getWatchPortForTunnel(
864 GetWatchPortForTunnelInput input) {
865 throw new UnsupportedOperationException("TODO");
868 @SuppressWarnings("checkstyle:IllegalCatch")
870 public ListenableFuture<RpcResult<AddL2GwMlagDeviceOutput>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input) {
872 final SettableFuture<RpcResult<AddL2GwMlagDeviceOutput>> result = SettableFuture.create();
874 final IpAddress hwIp = input.getIpAddress();
875 final List<String> nodeId = input.getNodeId();
876 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
877 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
878 containerPath, dataBroker);
879 if (transportZonesOptional.isPresent()) {
880 TransportZones transportZones = transportZonesOptional.get();
881 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
882 LOG.error("No teps configured");
883 result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
884 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
887 String transportZone = transportZones.getTransportZone().get(0).getZoneName();
888 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
889 InstanceIdentifier<DeviceVteps> path =
890 InstanceIdentifier.builder(TransportZones.class)
891 .child(TransportZone.class, new TransportZoneKey(transportZone))
892 .child(DeviceVteps.class, deviceVtepKey).build();
893 DeviceVteps deviceVtep = new DeviceVtepsBuilder().withKey(deviceVtepKey).setIpAddress(hwIp)
894 .setNodeId(nodeId.get(0)).setTopologyId(input.getTopologyId()).build();
895 LOG.trace("writing hWvtep{}", deviceVtep);
896 FluentFuture<Void> future =
897 retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
899 tx.mergeParentStructurePut(path, deviceVtep);
900 if (nodeId.size() == 2) {
901 LOG.trace("second node-id {}", nodeId.get(1));
902 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
903 InstanceIdentifier<DeviceVteps> path2 = InstanceIdentifier
904 .builder(TransportZones.class)
905 .child(TransportZone.class, new TransportZoneKey(transportZone))
906 .child(DeviceVteps.class, deviceVtepKey2).build();
907 DeviceVteps deviceVtep2 = new DeviceVtepsBuilder().withKey(deviceVtepKey2)
908 .setIpAddress(hwIp).setNodeId(nodeId.get(1))
909 .setTopologyId(input.getTopologyId()).build();
910 LOG.trace("writing {}", deviceVtep2);
911 tx.mergeParentStructurePut(path2, deviceVtep2);
914 future.addCallback(new FutureCallback<Void>() {
916 public void onSuccess(Void voidInstance) {
917 result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>success().build());
921 public void onFailure(Throwable error) {
922 String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
923 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
924 result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
925 .withError(RpcError.ErrorType.APPLICATION, msg, error)
928 }, MoreExecutors.directExecutor());
931 } catch (RuntimeException e) {
932 RpcResultBuilder<AddL2GwMlagDeviceOutput> resultBuilder = RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
933 .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
934 return Futures.immediateFuture(resultBuilder.build());
938 @SuppressWarnings("checkstyle:IllegalCatch")
940 public ListenableFuture<RpcResult<DeleteL2GwMlagDeviceOutput>> deleteL2GwMlagDevice(
941 DeleteL2GwMlagDeviceInput input) {
942 final SettableFuture<RpcResult<DeleteL2GwMlagDeviceOutput>> result = SettableFuture.create();
944 final IpAddress hwIp = input.getIpAddress();
945 final List<String> nodeId = input.getNodeId();
946 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
947 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
948 containerPath, dataBroker);
949 if (transportZonesOptional.isPresent()) {
950 TransportZones tzones = transportZonesOptional.get();
951 if (tzones.getTransportZone() == null || tzones.getTransportZone().isEmpty()) {
952 LOG.error("No teps configured");
953 result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed()
954 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
957 String transportZone = tzones.getTransportZone().get(0).getZoneName();
958 FluentFuture<Void> future =
959 retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
961 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
962 InstanceIdentifier<DeviceVteps> path =
963 InstanceIdentifier.builder(TransportZones.class)
964 .child(TransportZone.class, new TransportZoneKey(transportZone))
965 .child(DeviceVteps.class,
966 deviceVtepKey).build();
968 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
969 InstanceIdentifier<DeviceVteps> path2 =
970 InstanceIdentifier.builder(TransportZones.class)
971 .child(TransportZone.class, new TransportZoneKey(transportZone))
972 .child(DeviceVteps.class,
973 deviceVtepKey2).build();
978 future.addCallback(new FutureCallback<Void>() {
981 public void onSuccess(Void voidInstance) {
982 result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>success().build());
986 public void onFailure(Throwable error) {
987 String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
988 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
989 result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed()
990 .withError(RpcError.ErrorType.APPLICATION, msg, error)
993 }, MoreExecutors.directExecutor());
996 } catch (Exception e) {
997 RpcResultBuilder<DeleteL2GwMlagDeviceOutput> resultBuilder =
998 RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed().withError(RpcError.ErrorType.APPLICATION,
999 "Deleting l2 Gateway to DS Failed", e);
1000 return Futures.immediateFuture(resultBuilder.build());
1005 public ListenableFuture<RpcResult<IsTunnelInternalOrExternalOutput>> isTunnelInternalOrExternal(
1006 IsTunnelInternalOrExternalInput input) {
1007 RpcResultBuilder<IsTunnelInternalOrExternalOutput> resultBld;
1008 String tunIfName = input.getTunnelInterfaceName();
1010 IsTunnelInternalOrExternalOutputBuilder output = new IsTunnelInternalOrExternalOutputBuilder()
1011 .setTunnelType(tunVal);
1013 if (ItmUtils.ITM_CACHE.getInternalTunnel(tunIfName) != null) {
1015 } else if (ItmUtils.ITM_CACHE.getExternalTunnel(tunIfName) != null) {
1018 output.setTunnelType(tunVal);
1019 resultBld = RpcResultBuilder.success();
1020 resultBld.withResult(output.build());
1021 return Futures.immediateFuture(resultBld.build());
1025 public ListenableFuture<RpcResult<IsDcgwPresentOutput>> isDcgwPresent(IsDcgwPresentInput input) {
1026 RpcResultBuilder<IsDcgwPresentOutput> resultBld = RpcResultBuilder.success();
1028 Map<DcGatewayIpKey, DcGatewayIp> dcGatewayIpList = new HashMap<>();
1029 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
1030 tx -> dcGatewayIpList.values().addAll(getDcGatewayIpList(tx).values())).isDone();
1032 String dcgwIpStr = input.getDcgwIp();
1033 IpAddress dcgwIpAddr = IpAddressBuilder.getDefaultInstance(dcgwIpStr);
1036 if (!dcGatewayIpList.isEmpty()
1037 && dcGatewayIpList.values().stream().anyMatch(gwIp -> Objects.equal(gwIp.getIpAddress(), dcgwIpAddr))) {
1040 IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
1041 resultBld.withResult(output.build());
1045 IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
1046 resultBld.withResult(output.build());
1048 return Futures.immediateFuture(resultBld.build());
1052 public ListenableFuture<RpcResult<GetDpnEndpointIpsOutput>> getDpnEndpointIps(GetDpnEndpointIpsInput input) {
1053 Uint64 srcDpn = input.getSourceDpid();
1054 RpcResultBuilder<GetDpnEndpointIpsOutput> resultBld = failed();
1055 InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
1056 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class,
1057 new DPNTEPsInfoKey(srcDpn)).build();
1058 Optional<DPNTEPsInfo> tunnelInfo = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tunnelInfoId, dataBroker);
1059 if (!tunnelInfo.isPresent()) {
1060 LOG.error("tunnelInfo is not present");
1061 return Futures.immediateFuture(resultBld.build());
1064 List<TunnelEndPoints> tunnelEndPointList = tunnelInfo.get().getTunnelEndPoints();
1065 if (tunnelEndPointList == null || tunnelEndPointList.isEmpty()) {
1066 LOG.error("tunnelEndPointList is null or empty");
1067 return Futures.immediateFuture(resultBld.build());
1070 List<IpAddress> nexthopIpList = new ArrayList<>();
1071 tunnelEndPointList.forEach(tunnelEndPoint -> nexthopIpList.add(tunnelEndPoint.getIpAddress()));
1073 GetDpnEndpointIpsOutputBuilder output = new GetDpnEndpointIpsOutputBuilder().setNexthopipList(nexthopIpList);
1074 resultBld = RpcResultBuilder.success();
1075 resultBld.withResult(output.build()) ;
1076 return Futures.immediateFuture(resultBld.build());
1080 public ListenableFuture<RpcResult<GetDpnInfoOutput>> getDpnInfo(GetDpnInfoInput input) {
1081 return FutureRpcResults.fromListenableFuture(LOG, "getDpnInfo", input,
1082 () -> Futures.immediateFuture(getDpnInfoInternal(input))).build();
1085 private GetDpnInfoOutput getDpnInfoInternal(GetDpnInfoInput input) throws ReadFailedException {
1086 Map<String, Uint64> computeNamesVsDpnIds
1087 = getDpnIdByComputeNodeNameFromOpInventoryNodes(input.getComputeNames());
1088 Map<Uint64, ComputesBuilder> dpnIdVsVtepsComputes
1089 = getTunnelEndPointByDpnIdFromTranPortZone(computeNamesVsDpnIds.values());
1090 List<Computes> computes = computeNamesVsDpnIds.entrySet().stream()
1091 .map(entry -> dpnIdVsVtepsComputes.get(entry.getValue()).setComputeName(entry.getKey()).build())
1092 .collect(Collectors.toList());
1093 return new GetDpnInfoOutputBuilder().setComputes(computes).build();
1096 private Map<Uint64, ComputesBuilder> getTunnelEndPointByDpnIdFromTranPortZone(Collection<Uint64> dpnIds)
1097 throws ReadFailedException {
1098 TransportZones transportZones = singleTransactionDataBroker.syncRead(
1099 LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(TransportZones.class).build());
1100 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
1101 throw new IllegalStateException("Failed to find transport zones in config datastore");
1103 Map<Uint64, ComputesBuilder> result = new HashMap<>();
1104 for (TransportZone transportZone : transportZones.getTransportZone()) {
1105 for (Vteps vtep : transportZone.getVteps().values()) {
1106 if (dpnIds.contains(vtep.getDpnId())) {
1107 result.putIfAbsent(vtep.getDpnId(),
1108 new ComputesBuilder()
1109 .setZoneName(transportZone.getZoneName())
1110 .setDpnId(vtep.getDpnId())
1111 .setNodeId(getNodeId(vtep.getDpnId()))
1112 .setTepIp(Collections.singletonList(vtep.getIpAddress())));
1116 for (Uint64 dpnId : dpnIds) {
1117 if (!result.containsKey(dpnId)) {
1118 throw new IllegalStateException("Failed to find dpn id " + dpnId + " in transport zone");
1124 private Map<String, Uint64> getDpnIdByComputeNodeNameFromOpInventoryNodes(List<String> nodeNames)
1125 throws ReadFailedException {
1126 Nodes operInventoryNodes = singleTransactionDataBroker.syncRead(
1127 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(Nodes.class).build());
1128 if (operInventoryNodes.getNode() == null || operInventoryNodes.getNode().isEmpty()) {
1129 throw new IllegalStateException("Failed to find operational inventory nodes datastore");
1131 Map<String, Uint64> result = new HashMap<>();
1132 for (Node node : operInventoryNodes.getNode().values()) {
1133 String name = node.augmentation(FlowCapableNode.class).getDescription();
1134 if (nodeNames.contains(name)) {
1135 String[] nodeId = node.getId().getValue().split(":");
1136 result.put(name, Uint64.valueOf(nodeId[1]));
1139 for (String nodeName : nodeNames) {
1140 if (!result.containsKey(nodeName)) {
1141 throw new IllegalStateException("Failed to find dpn id of compute node name from oper inventory "
1148 private String getNodeId(Uint64 dpnId) throws ReadFailedException {
1149 InstanceIdentifier<BridgeRefEntry> path = InstanceIdentifier
1150 .builder(BridgeRefInfo.class)
1151 .child(BridgeRefEntry.class, new BridgeRefEntryKey(dpnId)).build();
1152 BridgeRefEntry bridgeRefEntry =
1153 singleTransactionDataBroker.syncRead(LogicalDatastoreType.OPERATIONAL, path);
1154 return bridgeRefEntry.getBridgeReference().getValue()
1155 .firstKeyOf(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021
1156 .network.topology.topology.Node.class).getNodeId().getValue();
1159 private ListenableFuture<GetEgressActionsForTunnelOutput>
1160 getEgressActionsForInternalTunnels(String interfaceName, Long tunnelKey, Integer actionKey)
1161 throws ExecutionException, InterruptedException, OperationFailedException {
1163 DpnTepInterfaceInfo interfaceInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
1164 if (interfaceInfo == null) {
1165 throw new IllegalStateException("Interface information not present in config DS for" + interfaceName);
1168 String tunnelType = ItmUtils.convertTunnelTypetoString(interfaceInfo.getTunnelType());
1169 if (!tunnelType.equalsIgnoreCase(ITMConstants.TUNNEL_TYPE_VXLAN)) {
1170 throw new IllegalArgumentException(tunnelType + " tunnel not handled by ITM");
1173 Optional<DPNTEPsInfo> dpntePsInfoOptional = dpnTEPsInfoCache.get(InstanceIdentifier.builder(DpnEndpoints.class)
1174 .child(DPNTEPsInfo.class, new DPNTEPsInfoKey(
1175 // FIXME: the cache should be caching this value, not just as a String
1176 Uint64.valueOf(dpnTepStateCache.getTunnelEndPointInfoFromCache(interfaceInfo.getTunnelName())
1177 .getDstEndPointInfo())))
1180 if (dpntePsInfoOptional.isPresent()) {
1181 dstId = dpntePsInfoOptional.get().getDstId();
1183 dstId = directTunnelUtils.allocateId(ITMConstants.ITM_IDPOOL_NAME, interfaceInfo.getRemoteDPN().toString());
1186 List<ActionInfo> result = new ArrayList<>();
1187 long regValue = MetaDataUtil.getRemoteDpnMetadatForEgressTunnelTable(dstId);
1188 int actionKeyStart = actionKey == null ? 0 : actionKey;
1189 result.add(new ActionSetFieldTunnelId(actionKeyStart++,
1190 Uint64.valueOf(tunnelKey != null ? tunnelKey : 0L)));
1191 result.add(new ActionRegLoad(actionKeyStart++, NxmNxReg6.class, MetaDataUtil.REG6_START_INDEX,
1192 MetaDataUtil.REG6_END_INDEX, regValue));
1193 result.add(new ActionNxResubmit(actionKeyStart, NwConstants.EGRESS_TUNNEL_TABLE));
1195 return Futures.immediateFuture(new GetEgressActionsForTunnelOutputBuilder()
1196 .setAction(result.stream().map(ActionInfo::buildAction).collect(Collectors.toList())).build());
1199 public static Map<DcGatewayIpKey, DcGatewayIp>
1200 getDcGatewayIpList(TypedReadWriteTransaction<Datastore.Configuration> tx)
1201 throws ExecutionException, InterruptedException {
1202 Map<DcGatewayIpKey, DcGatewayIp> dcGatewayIpList = new HashMap<>();
1203 FluentFuture<Optional<DcGatewayIpList>> future =
1204 tx.read(InstanceIdentifier.builder(DcGatewayIpList.class).build());
1205 future.addCallback(new FutureCallback<Optional<DcGatewayIpList>>() {
1207 public void onSuccess(Optional<DcGatewayIpList> optional) {
1209 // FIXME: why not just use the provided optional?
1210 Optional<DcGatewayIpList> opt = future.get();
1211 if (opt.isPresent()) {
1212 DcGatewayIpList list = opt.get();
1214 dcGatewayIpList.values().addAll(list.getDcGatewayIp().values());
1217 } catch (ExecutionException | InterruptedException e) {
1218 LOG.error("DcGateway IpList read failed", e);
1223 public void onFailure(Throwable error) {
1224 LOG.error("DcGateway IpList read failed", error);
1226 }, MoreExecutors.directExecutor());
1227 return dcGatewayIpList;