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.GetTepIpInput;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTepIpOutput;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInput;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutputBuilder;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeInput;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeOutput;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeOutputBuilder;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetWatchPortForTunnelInput;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetWatchPortForTunnelOutput;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentInput;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutput;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutputBuilder;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalInput;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutput;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutputBuilder;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInput;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointOutput;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsInput;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsOutput;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInput;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsOutput;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdParamOnTunnelInput;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdParamOnTunnelOutput;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.get.dpn.info.output.Computes;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.get.dpn.info.output.ComputesBuilder;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
164 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
165 import org.opendaylight.yangtools.yang.common.OperationFailedException;
166 import org.opendaylight.yangtools.yang.common.RpcError;
167 import org.opendaylight.yangtools.yang.common.RpcResult;
168 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
169 import org.opendaylight.yangtools.yang.common.Uint16;
170 import org.opendaylight.yangtools.yang.common.Uint64;
171 import org.slf4j.Logger;
172 import org.slf4j.LoggerFactory;
175 public class ItmManagerRpcService implements ItmRpcService {
177 private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
179 private final DataBroker dataBroker;
180 private final IMdsalApiManager mdsalManager;
181 private final DPNTEPsInfoCache dpnTEPsInfoCache;
182 private final ItmExternalTunnelAddWorker externalTunnelAddWorker;
183 private final SingleTransactionDataBroker singleTransactionDataBroker;
184 private final IInterfaceManager interfaceManager;
185 private final InterfaceManagerService interfaceManagerService;
186 private final DpnTepStateCache dpnTepStateCache;
187 private final TunnelStateCache tunnelStateCache;
188 private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache;
189 private final DirectTunnelUtils directTunnelUtils;
190 private final ManagedNewTransactionRunner txRunner;
191 private final RetryingManagedNewTransactionRunner retryingTxRunner;
192 private final ItmConfig itmConfig;
195 public ItmManagerRpcService(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
196 final ItmConfig itmConfig, final DPNTEPsInfoCache dpnTEPsInfoCache,
197 final IInterfaceManager interfaceManager, final DpnTepStateCache dpnTepStateCache,
198 final TunnelStateCache tunnelStateCache,
199 final InterfaceManagerService interfaceManagerService,
200 final OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
201 final DirectTunnelUtils directTunnelUtils) {
202 this.dataBroker = dataBroker;
203 this.mdsalManager = mdsalManager;
204 this.dpnTEPsInfoCache = dpnTEPsInfoCache;
205 this.externalTunnelAddWorker = new ItmExternalTunnelAddWorker(itmConfig, dpnTEPsInfoCache);
206 this.singleTransactionDataBroker = new SingleTransactionDataBroker(dataBroker);
207 this.interfaceManager = interfaceManager;
208 this.interfaceManagerService = interfaceManagerService;
209 this.dpnTepStateCache = dpnTepStateCache;
210 this.tunnelStateCache = tunnelStateCache;
211 this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache;
212 this.directTunnelUtils = directTunnelUtils;
213 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
214 this.retryingTxRunner = new RetryingManagedNewTransactionRunner(dataBroker);
215 this.itmConfig = itmConfig;
219 public void start() {
220 LOG.info("ItmManagerRpcService Started");
224 public void close() {
225 LOG.info("ItmManagerRpcService Closed");
229 public ListenableFuture<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(
230 GetTunnelInterfaceNameInput input) {
231 RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
232 Uint64 sourceDpn = input.getSourceDpid();
233 Uint64 destinationDpn = input.getDestinationDpid();
234 Optional<InternalTunnel> optTunnel = Optional.empty();
236 if (interfaceManager.isItmDirectTunnelsEnabled()) {
237 DpnTepInterfaceInfo interfaceInfo = dpnTepStateCache.getDpnTepInterface(sourceDpn, destinationDpn);
238 if (interfaceInfo != null) {
239 resultBld = RpcResultBuilder.success();
240 resultBld.withResult(new GetTunnelInterfaceNameOutputBuilder()
241 .setInterfaceName(interfaceInfo.getTunnelName())).build();
242 return Futures.immediateFuture(resultBld.build());
245 if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
246 optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn,
247 TunnelTypeLogicalGroup.class, dataBroker);
248 LOG.debug("MULTIPLE_VxLAN_TUNNELS: getTunnelInterfaceName {}", optTunnel);
250 if (!optTunnel.isPresent()) {
251 optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn, input.getTunnelType(), dataBroker);
253 if (optTunnel.isPresent()) {
254 InternalTunnel tunnel = optTunnel.get();
255 GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
256 List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
257 if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
258 output.setInterfaceName(tunnelInterfaces.get(0));
259 resultBld = RpcResultBuilder.success();
260 resultBld.withResult(output.build());
262 resultBld = failed();
266 resultBld = failed();
268 return Futures.immediateFuture(resultBld.build());
272 public ListenableFuture<RpcResult<GetEgressActionsForTunnelOutput>>
273 getEgressActionsForTunnel(GetEgressActionsForTunnelInput input) {
274 String tunnelName = input.getIntfName();
275 if (tunnelName == null) {
276 return Futures.immediateFuture(RpcResultBuilder.<GetEgressActionsForTunnelOutput>failed()
277 .withError(RpcError.ErrorType.APPLICATION,
278 "tunnel name not set for GetEgressActionsForTunnel call").build());
280 if (!dpnTepStateCache.isInternal(tunnelName) || !interfaceManager.isItmDirectTunnelsEnabled()) {
281 // Re-direct the RPC to Interface Manager
282 // From the rpc input and get the output and copy to output
283 org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
284 .GetEgressActionsForInterfaceInputBuilder inputIfmBuilder =
285 new org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
286 .GetEgressActionsForInterfaceInputBuilder().setIntfName(input.getIntfName())
287 .setTunnelKey(input.getTunnelKey()).setActionKey(input.getActionKey());
288 SettableFuture<RpcResult<GetEgressActionsForTunnelOutput>> settableFuture = SettableFuture.create();
289 Futures.addCallback(interfaceManagerService.getEgressActionsForInterface(inputIfmBuilder.build()),
290 new FutureCallback<org.opendaylight.yang.gen.v1.urn.opendaylight.genius
291 .interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput>() {
293 public void onSuccess(org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs
294 .rev160406.@NonNull GetEgressActionsForInterfaceOutput result) {
295 GetEgressActionsForTunnelOutputBuilder output =
296 new GetEgressActionsForTunnelOutputBuilder().setAction(result.getAction());
297 settableFuture.set(RpcResultBuilder.<GetEgressActionsForTunnelOutput>success()
298 .withResult(output.build()).build());
302 public void onFailure(Throwable throwable) {
303 LOG.debug("RPC Call to Get egress actions failed for interface {}", tunnelName);
304 String errMsg = String.format("RPC call to get egress actions failed for interface %s",
306 settableFuture.set(RpcResultBuilder.<GetEgressActionsForTunnelOutput>failed()
307 .withError(RpcError.ErrorType.APPLICATION, errMsg, throwable).build());
309 } ,MoreExecutors.directExecutor());
310 return settableFuture;
312 return fromListenableFuture(LOG, input, () -> getEgressActionsForInternalTunnels(input.getIntfName(),
313 input.getTunnelKey() != null ? input.getTunnelKey().toJava() : null,
314 input.getActionKey())).onFailureLogLevel(LogLevel.ERROR).build();
319 public ListenableFuture<RpcResult<GetTunnelTypeOutput>> getTunnelType(GetTunnelTypeInput input) {
320 String tunnelName = input.getIntfName();
321 if (tunnelName == null) {
322 return Futures.immediateFuture(RpcResultBuilder.<GetTunnelTypeOutput>failed()
323 .withError(RpcError.ErrorType.APPLICATION,
324 "tunnel name not set for getTunnelType call").build());
327 if (!dpnTepStateCache.isInternal(tunnelName) || !interfaceManager.isItmDirectTunnelsEnabled()) {
328 org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
329 .GetTunnelTypeInputBuilder inputBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight
330 .genius.interfacemanager.rpcs.rev160406.GetTunnelTypeInputBuilder()
331 .setIntfName(input.getIntfName());
332 SettableFuture<RpcResult<GetTunnelTypeOutput>> settableFuture = SettableFuture.create();
333 Futures.addCallback(interfaceManagerService.getTunnelType(inputBuilder.build()),
334 new FutureCallback<org.opendaylight.yang.gen.v1.urn.opendaylight.genius
335 .interfacemanager.rpcs.rev160406.GetTunnelTypeOutput>() {
337 public void onSuccess(org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs
338 .rev160406.@NonNull GetTunnelTypeOutput result) {
339 GetTunnelTypeOutputBuilder output = new GetTunnelTypeOutputBuilder()
340 .setTunnelType(result.getTunnelType());
341 settableFuture.set(RpcResultBuilder.<GetTunnelTypeOutput>success()
342 .withResult(output.build()).build());
346 public void onFailure(Throwable throwable) {
347 LOG.debug("RPC Call to Get tunnel type failed for interface {}", tunnelName);
348 String errMsg = String.format("RPC to Get tunnel type failed for interface %s",
350 settableFuture.set(RpcResultBuilder.<GetTunnelTypeOutput>failed()
351 .withError(RpcError.ErrorType.APPLICATION, errMsg, throwable).build());
353 },MoreExecutors.directExecutor());
354 return settableFuture;
356 LOG.debug("get tunnel type from ITM for interface name {}", input.getIntfName());
357 return FutureRpcResults.fromBuilder(LOG, input, () -> {
358 DpnTepInterfaceInfo ifInfo = dpnTepStateCache.getTunnelFromCache(input.getIntfName());
359 return new GetTunnelTypeOutputBuilder().setTunnelType(ifInfo.getTunnelType());
365 public ListenableFuture<RpcResult<SetBfdParamOnTunnelOutput>> setBfdParamOnTunnel(
366 SetBfdParamOnTunnelInput input) {
367 final Uint64 srcDpnId = Uint64.valueOf(input.getSourceNode());
368 final Uint64 destDpnId = Uint64.valueOf(input.getDestinationNode());
369 LOG.debug("setBfdParamOnTunnel srcDpnId: {}, destDpnId: {}", srcDpnId, destDpnId);
370 final SettableFuture<RpcResult<SetBfdParamOnTunnelOutput>> result = SettableFuture.create();
371 FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
372 enableBFD(tx, srcDpnId, destDpnId, input.isMonitoringEnabled(), input.getMonitoringInterval().toJava());
373 enableBFD(tx, destDpnId, srcDpnId, input.isMonitoringEnabled(), input.getMonitoringInterval().toJava());
376 future.addCallback(new FutureCallback<Object>() {
378 public void onSuccess(Object voidInstance) {
379 result.set(RpcResultBuilder.<SetBfdParamOnTunnelOutput>success().build());
383 public void onFailure(Throwable error) {
384 String msg = "Unable to remove external tunnel from DPN";
385 LOG.error("remove ext tunnel failed. {}.", msg, error);
386 result.set(RpcResultBuilder.<SetBfdParamOnTunnelOutput>failed()
387 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
389 }, MoreExecutors.directExecutor());
393 private void enableBFD(TypedWriteTransaction<Datastore.Configuration> tx, Uint64 srcDpnId, Uint64 destDpnId,
394 final Boolean enabled, final Integer interval) throws ReadFailedException {
395 DpnTepInterfaceInfo dpnTepInterfaceInfo = dpnTepStateCache.getDpnTepInterface(srcDpnId, destDpnId);
396 RemoteDpnsBuilder remoteDpnsBuilder = new RemoteDpnsBuilder();
397 remoteDpnsBuilder.withKey(new RemoteDpnsKey(destDpnId)).setDestinationDpnId(destDpnId)
398 .setTunnelName(dpnTepInterfaceInfo.getTunnelName()).setInternal(dpnTepInterfaceInfo.isInternal())
399 .setMonitoringEnabled(enabled);
400 if (enabled && interval != null) {
401 remoteDpnsBuilder.setMonitoringInterval(interval);
403 RemoteDpns remoteDpn = remoteDpnsBuilder.build();
404 Optional<OvsBridgeRefEntry> ovsBridgeRefEntry = ovsBridgeRefEntryCache.get(srcDpnId);
405 LOG.debug("setBfdParamOnTunnel TunnelName: {}, ovsBridgeRefEntry: {}", dpnTepInterfaceInfo.getTunnelName(),
407 directTunnelUtils.updateBfdConfiguration(srcDpnId, remoteDpn, ovsBridgeRefEntry);
408 InstanceIdentifier<RemoteDpns> iid = InstanceIdentifier.builder(DpnTepsState.class)
409 .child(DpnsTeps.class, new DpnsTepsKey(srcDpnId))
410 .child(RemoteDpns.class,
411 new RemoteDpnsKey(destDpnId)).build();
412 tx.mergeParentStructureMerge(iid, remoteDpn);
416 public ListenableFuture<RpcResult<RemoveExternalTunnelEndpointOutput>> removeExternalTunnelEndpoint(
417 RemoveExternalTunnelEndpointInput input) {
418 //Ignore the Futures for now
419 final SettableFuture<RpcResult<RemoveExternalTunnelEndpointOutput>> result = SettableFuture.create();
420 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
421 FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
423 ItmExternalTunnelDeleteWorker.deleteTunnels(meshedDpnList, input.getDestinationIp(),
424 input.getTunnelType(), tx);
425 InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
426 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
430 future.addCallback(new FutureCallback<Object>() {
431 @Override public void onSuccess(Object voidInstance) {
432 result.set(RpcResultBuilder.<RemoveExternalTunnelEndpointOutput>success().build());
435 @Override public void onFailure(Throwable error) {
436 String msg = "Unable to delete DcGatewayIp " + input.getDestinationIp()
437 + " in datastore and tunnel type " + input.getTunnelType();
438 LOG.error("Unable to delete DcGatewayIp {} in datastore and tunnel type {}", input.getDestinationIp(),
439 input.getTunnelType());
440 result.set(RpcResultBuilder.<RemoveExternalTunnelEndpointOutput>failed()
441 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
443 }, MoreExecutors.directExecutor());
448 public ListenableFuture<RpcResult<RemoveExternalTunnelFromDpnsOutput>> removeExternalTunnelFromDpns(
449 RemoveExternalTunnelFromDpnsInput input) {
450 //Ignore the Futures for now
451 final SettableFuture<RpcResult<RemoveExternalTunnelFromDpnsOutput>> result = SettableFuture.create();
452 List<DPNTEPsInfo> cfgDpnList = ItmUtils.getDpnTepListFromDpnId(dpnTEPsInfoCache, input.getDpnId());
453 FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
454 tx -> ItmExternalTunnelDeleteWorker.deleteTunnels(cfgDpnList, input.getDestinationIp(),
455 input.getTunnelType(), tx));
457 future.addCallback(new FutureCallback<Object>() {
459 public void onSuccess(Object voidInstance) {
460 result.set(RpcResultBuilder.<RemoveExternalTunnelFromDpnsOutput>success().build());
464 public void onFailure(Throwable error) {
465 String msg = "Unable to remove external tunnel from DPN";
466 LOG.error("remove ext tunnel failed. {}.", msg, error);
467 result.set(RpcResultBuilder.<RemoveExternalTunnelFromDpnsOutput>failed()
468 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
470 }, MoreExecutors.directExecutor());
475 public ListenableFuture<RpcResult<BuildExternalTunnelFromDpnsOutput>> buildExternalTunnelFromDpns(
476 BuildExternalTunnelFromDpnsInput input) {
477 //Ignore the Futures for now
478 final SettableFuture<RpcResult<BuildExternalTunnelFromDpnsOutput>> result = SettableFuture.create();
479 FluentFuture<?> extTunnelResultList =
480 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
481 tx -> externalTunnelAddWorker.buildTunnelsFromDpnToExternalEndPoint(input.getDpnId(),
482 input.getDestinationIp(),input.getTunnelType(), tx));
484 extTunnelResultList.addCallback(new FutureCallback<Object>() {
486 public void onSuccess(Object voidInstance) {
487 result.set(RpcResultBuilder.<BuildExternalTunnelFromDpnsOutput>success().build());
491 public void onFailure(Throwable error) {
492 String msg = "Unable to create ext tunnel";
493 LOG.error("create ext tunnel failed. {}.", msg, error);
494 result.set(RpcResultBuilder.<BuildExternalTunnelFromDpnsOutput>failed()
495 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
497 }, MoreExecutors.directExecutor());
502 public ListenableFuture<RpcResult<AddExternalTunnelEndpointOutput>> addExternalTunnelEndpoint(
503 AddExternalTunnelEndpointInput input) {
504 // TODO Auto-generated method stub
506 //Ignore the Futures for now
507 final SettableFuture<RpcResult<AddExternalTunnelEndpointOutput>> result = SettableFuture.create();
508 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
509 InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
510 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
511 DcGatewayIp dcGatewayIp =
512 new DcGatewayIpBuilder().setIpAddress(input.getDestinationIp())
513 .setTunnnelType(input.getTunnelType()).build();
515 FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
517 externalTunnelAddWorker.buildTunnelsToExternalEndPoint(meshedDpnList, input.getDestinationIp(),
518 input.getTunnelType(), tx);
519 tx.mergeParentStructurePut(extPath, dcGatewayIp);
522 future.addCallback(new FutureCallback<Object>() {
523 @Override public void onSuccess(Object voidInstance) {
524 result.set(RpcResultBuilder.<AddExternalTunnelEndpointOutput>success().build());
527 @Override public void onFailure(Throwable error) {
529 "Unable to create DcGatewayIp {} in datastore for ip " + input.getDestinationIp() + "and "
530 + "tunnel type " + input.getTunnelType();
532 LOG.error("Unable to create DcGatewayIp in datastore for ip {} and tunnel type {}",
533 input.getDestinationIp() , input.getTunnelType());
534 result.set(RpcResultBuilder.<AddExternalTunnelEndpointOutput>failed()
535 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
537 }, MoreExecutors.directExecutor());
542 public ListenableFuture<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
543 GetExternalTunnelInterfaceNameInput input) {
544 SettableFuture.create();
545 RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
546 String sourceNode = input.getSourceNode();
547 String dstNode = input.getDestinationNode();
548 ExternalTunnelKey externalTunnelKey = new ExternalTunnelKey(dstNode, sourceNode, input.getTunnelType());
549 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
550 ExternalTunnelList.class)
551 .child(ExternalTunnel.class, externalTunnelKey);
552 ExternalTunnel exTunnel =
553 ItmUtils.getExternalTunnelbyExternalTunnelKey(externalTunnelKey, path, this.dataBroker);
554 if (exTunnel != null) {
555 GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder();
556 output.setInterfaceName(exTunnel.getTunnelInterfaceName());
557 resultBld = RpcResultBuilder.success();
558 resultBld.withResult(output.build());
560 resultBld = failed();
563 return Futures.immediateFuture(resultBld.build());
567 public ListenableFuture<RpcResult<CreateTerminatingServiceActionsOutput>>
568 createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
569 LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}",
570 input.getDpnId() , input.getServiceId(), input.getInstruction());
571 final SettableFuture<RpcResult<CreateTerminatingServiceActionsOutput>> result = SettableFuture.create();
572 Uint16 serviceId = input.getServiceId();
573 final List<MatchInfo> mkMatches = getTunnelMatchesForServiceId(serviceId);
575 Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
576 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, serviceId), 5,
577 "ITM Flow Entry :" + serviceId, 0, 0,
578 Uint64.fromLongBits(ITMConstants.COOKIE_ITM.longValue() + serviceId.toJava()), mkMatches,
579 input.getInstruction());
581 ListenableFuture<?> installFlowResult = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
582 tx -> mdsalManager.addFlow(tx, input.getDpnId(), terminatingServiceTableFlow));
583 Futures.addCallback(installFlowResult, new FutureCallback<Object>() {
586 public void onSuccess(Object voidInstance) {
587 result.set(RpcResultBuilder.<CreateTerminatingServiceActionsOutput>success().build());
591 public void onFailure(Throwable error) {
592 String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
593 LOG.error("create terminating service actions failed. {}", msg, error);
594 result.set(RpcResultBuilder.<CreateTerminatingServiceActionsOutput>failed()
595 .withError(RpcError.ErrorType.APPLICATION, msg, error)
598 }, MoreExecutors.directExecutor());
599 // result.set(RpcResultBuilder.<Void>success().build());
604 public ListenableFuture<RpcResult<RemoveTerminatingServiceActionsOutput>>
605 removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
606 LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}",
607 input.getDpnId(), input.getServiceId());
608 final SettableFuture<RpcResult<RemoveTerminatingServiceActionsOutput>> result = SettableFuture.create();
610 ListenableFuture<?> removeFlowResult = txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
611 tx -> mdsalManager.removeFlow(tx, input.getDpnId(),
612 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, input.getServiceId()),
613 NwConstants.INTERNAL_TUNNEL_TABLE));
614 Futures.addCallback(removeFlowResult, new FutureCallback<Object>() {
617 public void onSuccess(Object voidInstance) {
618 result.set(RpcResultBuilder.<RemoveTerminatingServiceActionsOutput>success().build());
622 public void onFailure(Throwable error) {
623 String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
624 LOG.error("remove terminating service actions failed. {}", msg, error);
625 result.set(RpcResultBuilder.<RemoveTerminatingServiceActionsOutput>failed()
626 .withError(RpcError.ErrorType.APPLICATION, msg, error)
629 }, MoreExecutors.directExecutor());
630 //result.set(RpcResultBuilder.<Void>success().build());
635 public List<MatchInfo> getTunnelMatchesForServiceId(Uint16 serviceId) {
636 final List<MatchInfo> mkMatches = new ArrayList<>();
639 mkMatches.add(new MatchTunnelId(Uint64.valueOf(serviceId)));
644 private String getFlowRef(long termSvcTable, Uint16 svcId) {
645 return String.valueOf(termSvcTable) + svcId;
649 public ListenableFuture<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
650 GetInternalOrExternalInterfaceNameInput input) {
651 RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = failed();
652 Uint64 srcDpn = input.getSourceDpid();
653 IpAddress dstIp = input.getDestinationIp() ;
654 InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(ExternalTunnelList.class)
655 .child(ExternalTunnel.class,
656 new ExternalTunnelKey(dstIp.stringValue(), srcDpn.toString(), input.getTunnelType()));
658 Optional<ExternalTunnel> optExtTunnel = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
660 if (optExtTunnel != null && optExtTunnel.isPresent()) {
661 ExternalTunnel extTunnel = optExtTunnel.get();
662 GetInternalOrExternalInterfaceNameOutputBuilder output =
663 new GetInternalOrExternalInterfaceNameOutputBuilder()
664 .setInterfaceName(extTunnel.getTunnelInterfaceName());
665 resultBld = RpcResultBuilder.success();
666 resultBld.withResult(output.build()) ;
668 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
670 // Look for external tunnels if not look for internal tunnel
671 for (DPNTEPsInfo teps : meshedDpnList) {
672 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
673 if (dstIp.equals(firstEndPt.getIpAddress())) {
674 Optional<InternalTunnel> optTunnel = Optional.empty();
675 if (interfaceManager.isItmDirectTunnelsEnabled()) {
676 DpnTepInterfaceInfo interfaceInfo =
677 dpnTepStateCache.getDpnTepInterface(srcDpn, teps.getDPNID());
678 if (interfaceInfo != null) {
679 resultBld = RpcResultBuilder.success();
680 resultBld.withResult(new GetInternalOrExternalInterfaceNameOutputBuilder()
681 .setInterfaceName(interfaceInfo.getTunnelName())).build();
682 return Futures.immediateFuture(resultBld.build());
686 if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
687 optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
688 TunnelTypeLogicalGroup.class, dataBroker);
689 LOG.debug("MULTIPLE_VxLAN_TUNNELS: getInternalOrExternalInterfaceName {}", optTunnel);
691 if (!optTunnel.isPresent()) {
692 optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
693 input.getTunnelType(), dataBroker);
695 if (optTunnel.isPresent()) {
696 InternalTunnel tunnel = optTunnel.get();
697 List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
698 if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
699 GetInternalOrExternalInterfaceNameOutputBuilder
701 new GetInternalOrExternalInterfaceNameOutputBuilder()
702 .setInterfaceName(tunnelInterfaces.get(0));
703 resultBld = RpcResultBuilder.success();
704 resultBld.withResult(output.build());
706 LOG.error("No tunnel interface found between source DPN {} ans destination IP {}", srcDpn,
711 LOG.error("Tunnel not found for source DPN {} ans destination IP {}", srcDpn, dstIp);
716 return Futures.immediateFuture(resultBld.build());
719 @SuppressWarnings("checkstyle:IllegalCatch")
721 public ListenableFuture<RpcResult<DeleteL2GwDeviceOutput>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
722 final SettableFuture<RpcResult<DeleteL2GwDeviceOutput>> result = SettableFuture.create();
723 boolean foundVxlanTzone = false;
725 final IpAddress hwIp = input.getIpAddress();
726 final String nodeId = input.getNodeId();
727 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
728 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
729 containerPath, dataBroker);
730 if (transportZonesOptional.isPresent()) {
731 TransportZones transportZones = transportZonesOptional.get();
732 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
733 LOG.error("No teps configured");
734 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
735 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
738 for (TransportZone tzone : transportZones.getTransportZone()) {
739 if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
742 foundVxlanTzone = true;
743 String transportZone = tzone.getZoneName();
744 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
745 InstanceIdentifier<DeviceVteps> path = InstanceIdentifier
746 .builder(TransportZones.class)
747 .child(TransportZone.class,
748 new TransportZoneKey(transportZone))
749 .child(DeviceVteps.class, deviceVtepKey)
751 FluentFuture<?> future =
752 retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> tx.delete(path));
753 future.addCallback(new FutureCallback<Object>() {
754 @Override public void onSuccess(Object voidInstance) {
755 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>success().build());
758 @Override public void onFailure(Throwable error) {
759 String msg = String.format("Unable to delete HwVtep %s from datastore", nodeId);
760 LOG.error("Unable to delete HwVtep {}, {} from datastore", nodeId, hwIp);
761 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
762 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
764 }, MoreExecutors.directExecutor());
767 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
768 .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
772 if (!foundVxlanTzone) {
773 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
774 .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
779 } catch (Exception e) {
780 RpcResultBuilder<DeleteL2GwDeviceOutput> resultBuilder = RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
781 .withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
782 return Futures.immediateFuture(resultBuilder.build());
786 @SuppressWarnings("checkstyle:IllegalCatch")
788 public ListenableFuture<RpcResult<AddL2GwDeviceOutput>> addL2GwDevice(AddL2GwDeviceInput input) {
790 final SettableFuture<RpcResult<AddL2GwDeviceOutput>> result = SettableFuture.create();
791 boolean foundVxlanTzone = false;
793 final IpAddress hwIp = input.getIpAddress();
794 final String nodeId = input.getNodeId();
795 //iterate through all transport zones and put TORs under vxlan
796 //if no vxlan tzone is cnfigured, return an error.
797 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
798 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
799 containerPath, dataBroker);
800 if (transportZonesOptional.isPresent()) {
801 TransportZones transportZones = transportZonesOptional.get();
802 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
803 LOG.error("No transportZone configured");
804 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
805 .withError(RpcError.ErrorType.APPLICATION, "No transportZone Configured").build());
808 for (TransportZone tzone : transportZones.getTransportZone()) {
809 if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
812 String transportZone = tzone.getZoneName();
813 foundVxlanTzone = true;
814 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
815 InstanceIdentifier<DeviceVteps> path = InstanceIdentifier
816 .builder(TransportZones.class)
817 .child(TransportZone.class,
818 new TransportZoneKey(transportZone))
819 .child(DeviceVteps.class, deviceVtepKey)
821 DeviceVteps deviceVtep = new DeviceVtepsBuilder().withKey(deviceVtepKey).setIpAddress(hwIp)
822 .setNodeId(nodeId).setTopologyId(input.getTopologyId()).build();
823 //TO DO: add retry if it fails
824 FluentFuture<?> future = retryingTxRunner
825 .callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
826 tx -> tx.mergeParentStructurePut(path, deviceVtep));
828 future.addCallback(new FutureCallback<Object>() {
830 @Override public void onSuccess(Object voidInstance) {
831 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>success().build());
834 @Override public void onFailure(Throwable error) {
835 String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
836 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId, hwIp);
837 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
838 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
840 }, MoreExecutors.directExecutor());
844 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
845 .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
849 if (!foundVxlanTzone) {
850 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
851 .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
856 } catch (Exception e) {
857 RpcResultBuilder<AddL2GwDeviceOutput> resultBuilder = RpcResultBuilder.<AddL2GwDeviceOutput>failed()
858 .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
859 return Futures.immediateFuture(resultBuilder.build());
864 public ListenableFuture<RpcResult<GetWatchPortForTunnelOutput>> getWatchPortForTunnel(
865 GetWatchPortForTunnelInput input) {
866 throw new UnsupportedOperationException("TODO");
869 public ListenableFuture<RpcResult<GetTepIpOutput>> getTepIp(GetTepIpInput input) {
873 @SuppressWarnings("checkstyle:IllegalCatch")
875 public ListenableFuture<RpcResult<AddL2GwMlagDeviceOutput>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input) {
877 final SettableFuture<RpcResult<AddL2GwMlagDeviceOutput>> result = SettableFuture.create();
879 final IpAddress hwIp = input.getIpAddress();
880 final List<String> nodeId = input.getNodeId();
881 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
882 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
883 containerPath, dataBroker);
884 if (transportZonesOptional.isPresent()) {
885 TransportZones transportZones = transportZonesOptional.get();
886 if (transportZones.getTransportZone() == null || transportZones.getTransportZone()
888 LOG.error("No teps configured");
889 result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
890 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
893 for (TransportZone tzone : transportZones.getTransportZone()) {
894 if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
897 String transportZone = tzone.getZoneName();
898 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
899 InstanceIdentifier<DeviceVteps> path =
900 InstanceIdentifier.builder(TransportZones.class)
901 .child(TransportZone.class, new TransportZoneKey(transportZone))
902 .child(DeviceVteps.class, deviceVtepKey).build();
903 DeviceVteps deviceVtep = new DeviceVtepsBuilder().withKey(deviceVtepKey)
905 .setNodeId(nodeId.get(0)).setTopologyId(input.getTopologyId()).build();
906 LOG.trace("writing hWvtep{}", deviceVtep);
907 FluentFuture<?> future =
908 retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
910 tx.mergeParentStructurePut(path, deviceVtep);
911 if (nodeId.size() == 2) {
912 LOG.trace("second node-id {}", nodeId.get(1));
913 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp,
915 InstanceIdentifier<DeviceVteps> path2 = InstanceIdentifier
916 .builder(TransportZones.class)
917 .child(TransportZone.class, new TransportZoneKey(transportZone))
918 .child(DeviceVteps.class, deviceVtepKey2).build();
919 DeviceVteps deviceVtep2 = new DeviceVtepsBuilder()
920 .withKey(deviceVtepKey2)
921 .setIpAddress(hwIp).setNodeId(nodeId.get(1))
922 .setTopologyId(input.getTopologyId()).build();
923 LOG.trace("writing {}", deviceVtep2);
924 tx.mergeParentStructurePut(path2, deviceVtep2);
927 future.addCallback(new FutureCallback<Object>() {
929 public void onSuccess(Object voidInstance) {
930 result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>success().build());
934 public void onFailure(Throwable error) {
936 .format("Unable to write HwVtep %s to datastore", nodeId);
937 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId, hwIp);
938 result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
939 .withError(RpcError.ErrorType.APPLICATION, msg, error)
942 }, MoreExecutors.directExecutor());
946 } catch (RuntimeException e) {
947 RpcResultBuilder<AddL2GwMlagDeviceOutput> resultBuilder = RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
948 .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
949 return Futures.immediateFuture(resultBuilder.build());
953 @SuppressWarnings("checkstyle:IllegalCatch")
955 public ListenableFuture<RpcResult<DeleteL2GwMlagDeviceOutput>> deleteL2GwMlagDevice(
956 DeleteL2GwMlagDeviceInput input) {
957 final SettableFuture<RpcResult<DeleteL2GwMlagDeviceOutput>> result = SettableFuture.create();
959 final IpAddress hwIp = input.getIpAddress();
960 final List<String> nodeId = input.getNodeId();
961 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
962 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
963 containerPath, dataBroker);
964 if (transportZonesOptional.isPresent()) {
965 TransportZones tzones = transportZonesOptional.get();
966 if (tzones.getTransportZone() == null || tzones.getTransportZone().isEmpty()) {
967 LOG.error("No teps configured");
968 result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed()
969 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
972 String transportZone = tzones.getTransportZone().get(0).getZoneName();
973 FluentFuture<?> future =
974 retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
976 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
977 InstanceIdentifier<DeviceVteps> path =
978 InstanceIdentifier.builder(TransportZones.class)
979 .child(TransportZone.class, new TransportZoneKey(transportZone))
980 .child(DeviceVteps.class,
981 deviceVtepKey).build();
983 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
984 InstanceIdentifier<DeviceVteps> path2 =
985 InstanceIdentifier.builder(TransportZones.class)
986 .child(TransportZone.class, new TransportZoneKey(transportZone))
987 .child(DeviceVteps.class,
988 deviceVtepKey2).build();
993 future.addCallback(new FutureCallback<Object>() {
996 public void onSuccess(Object voidInstance) {
997 result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>success().build());
1001 public void onFailure(Throwable error) {
1002 String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
1003 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
1004 result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed()
1005 .withError(RpcError.ErrorType.APPLICATION, msg, error)
1008 }, MoreExecutors.directExecutor());
1011 } catch (Exception e) {
1012 RpcResultBuilder<DeleteL2GwMlagDeviceOutput> resultBuilder =
1013 RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed().withError(RpcError.ErrorType.APPLICATION,
1014 "Deleting l2 Gateway to DS Failed", e);
1015 return Futures.immediateFuture(resultBuilder.build());
1020 public ListenableFuture<RpcResult<IsTunnelInternalOrExternalOutput>> isTunnelInternalOrExternal(
1021 IsTunnelInternalOrExternalInput input) {
1022 RpcResultBuilder<IsTunnelInternalOrExternalOutput> resultBld;
1023 String tunIfName = input.getTunnelInterfaceName();
1025 IsTunnelInternalOrExternalOutputBuilder output = new IsTunnelInternalOrExternalOutputBuilder()
1026 .setTunnelType(tunVal);
1028 if (ItmUtils.ITM_CACHE.getInternalTunnel(tunIfName) != null) {
1030 } else if (ItmUtils.ITM_CACHE.getExternalTunnel(tunIfName) != null) {
1033 output.setTunnelType(tunVal);
1034 resultBld = RpcResultBuilder.success();
1035 resultBld.withResult(output.build());
1036 return Futures.immediateFuture(resultBld.build());
1040 public ListenableFuture<RpcResult<IsDcgwPresentOutput>> isDcgwPresent(IsDcgwPresentInput input) {
1041 RpcResultBuilder<IsDcgwPresentOutput> resultBld = RpcResultBuilder.success();
1043 Map<DcGatewayIpKey, DcGatewayIp> dcGatewayIpList = new HashMap<>();
1044 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
1045 tx -> dcGatewayIpList.putAll(getDcGatewayIpList(tx))).isDone();
1046 String dcgwIpStr = input.getDcgwIp();
1047 IpAddress dcgwIpAddr = IpAddressBuilder.getDefaultInstance(dcgwIpStr);
1050 if (!dcGatewayIpList.isEmpty()
1051 && dcGatewayIpList.values().stream().anyMatch(gwIp -> Objects.equal(gwIp.getIpAddress(), dcgwIpAddr))) {
1054 IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
1055 resultBld.withResult(output.build());
1059 IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
1060 resultBld.withResult(output.build());
1062 return Futures.immediateFuture(resultBld.build());
1066 public ListenableFuture<RpcResult<GetDpnEndpointIpsOutput>> getDpnEndpointIps(GetDpnEndpointIpsInput input) {
1067 Uint64 srcDpn = input.getSourceDpid();
1068 RpcResultBuilder<GetDpnEndpointIpsOutput> resultBld = failed();
1069 InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
1070 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class,
1071 new DPNTEPsInfoKey(srcDpn)).build();
1072 Optional<DPNTEPsInfo> tunnelInfo = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tunnelInfoId, dataBroker);
1073 if (!tunnelInfo.isPresent()) {
1074 LOG.error("tunnelInfo is not present");
1075 return Futures.immediateFuture(resultBld.build());
1078 List<TunnelEndPoints> tunnelEndPointList = tunnelInfo.get().getTunnelEndPoints();
1079 if (tunnelEndPointList == null || tunnelEndPointList.isEmpty()) {
1080 LOG.error("tunnelEndPointList is null or empty");
1081 return Futures.immediateFuture(resultBld.build());
1084 List<IpAddress> nexthopIpList = new ArrayList<>();
1085 tunnelEndPointList.forEach(tunnelEndPoint -> nexthopIpList.add(tunnelEndPoint.getIpAddress()));
1087 GetDpnEndpointIpsOutputBuilder output = new GetDpnEndpointIpsOutputBuilder().setNexthopipList(nexthopIpList);
1088 resultBld = RpcResultBuilder.success();
1089 resultBld.withResult(output.build()) ;
1090 return Futures.immediateFuture(resultBld.build());
1094 public ListenableFuture<RpcResult<GetDpnInfoOutput>> getDpnInfo(GetDpnInfoInput input) {
1095 return FutureRpcResults.fromListenableFuture(LOG, "getDpnInfo", input,
1096 () -> Futures.immediateFuture(getDpnInfoInternal(input))).build();
1099 private GetDpnInfoOutput getDpnInfoInternal(GetDpnInfoInput input) throws ReadFailedException {
1100 Map<String, Uint64> computeNamesVsDpnIds
1101 = getDpnIdByComputeNodeNameFromOpInventoryNodes(input.getComputeNames());
1102 Map<Uint64, ComputesBuilder> dpnIdVsVtepsComputes
1103 = getTunnelEndPointByDpnIdFromTranPortZone(computeNamesVsDpnIds.values());
1104 List<Computes> computes = computeNamesVsDpnIds.entrySet().stream()
1105 .map(entry -> dpnIdVsVtepsComputes.get(entry.getValue()).setComputeName(entry.getKey()).build())
1106 .collect(Collectors.toList());
1107 return new GetDpnInfoOutputBuilder().setComputes(computes).build();
1110 private Map<Uint64, ComputesBuilder> getTunnelEndPointByDpnIdFromTranPortZone(Collection<Uint64> dpnIds)
1111 throws ReadFailedException {
1112 TransportZones transportZones = singleTransactionDataBroker.syncRead(
1113 LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(TransportZones.class).build());
1114 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
1115 throw new IllegalStateException("Failed to find transport zones in config datastore");
1117 Map<Uint64, ComputesBuilder> result = new HashMap<>();
1118 for (TransportZone transportZone : transportZones.getTransportZone()) {
1119 for (Vteps vtep : transportZone.getVteps().values()) {
1120 if (dpnIds.contains(vtep.getDpnId())) {
1121 result.putIfAbsent(vtep.getDpnId(),
1122 new ComputesBuilder()
1123 .setZoneName(transportZone.getZoneName())
1124 .setDpnId(vtep.getDpnId())
1125 .setNodeId(getNodeId(vtep.getDpnId()))
1126 .setTepIp(Collections.singletonList(vtep.getIpAddress())));
1130 for (Uint64 dpnId : dpnIds) {
1131 if (!result.containsKey(dpnId)) {
1132 throw new IllegalStateException("Failed to find dpn id " + dpnId + " in transport zone");
1138 private Map<String, Uint64> getDpnIdByComputeNodeNameFromOpInventoryNodes(List<String> nodeNames)
1139 throws ReadFailedException {
1140 Nodes operInventoryNodes = singleTransactionDataBroker.syncRead(
1141 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(Nodes.class).build());
1142 if (operInventoryNodes.getNode() == null || operInventoryNodes.getNode().isEmpty()) {
1143 throw new IllegalStateException("Failed to find operational inventory nodes datastore");
1145 Map<String, Uint64> result = new HashMap<>();
1146 for (Node node : operInventoryNodes.getNode().values()) {
1147 String name = node.augmentation(FlowCapableNode.class).getDescription();
1148 if (nodeNames.contains(name)) {
1149 String[] nodeId = node.getId().getValue().split(":");
1150 result.put(name, Uint64.valueOf(nodeId[1]));
1153 for (String nodeName : nodeNames) {
1154 if (!result.containsKey(nodeName)) {
1155 throw new IllegalStateException("Failed to find dpn id of compute node name from oper inventory "
1162 private String getNodeId(Uint64 dpnId) throws ReadFailedException {
1163 InstanceIdentifier<BridgeRefEntry> path = InstanceIdentifier
1164 .builder(BridgeRefInfo.class)
1165 .child(BridgeRefEntry.class, new BridgeRefEntryKey(dpnId)).build();
1166 BridgeRefEntry bridgeRefEntry =
1167 singleTransactionDataBroker.syncRead(LogicalDatastoreType.OPERATIONAL, path);
1168 return bridgeRefEntry.getBridgeReference().getValue()
1169 .firstKeyOf(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021
1170 .network.topology.topology.Node.class).getNodeId().getValue();
1173 private ListenableFuture<GetEgressActionsForTunnelOutput>
1174 getEgressActionsForInternalTunnels(String interfaceName, Long tunnelKey, Integer actionKey)
1175 throws ExecutionException, InterruptedException, OperationFailedException {
1177 DpnTepInterfaceInfo interfaceInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
1178 if (interfaceInfo == null) {
1179 throw new IllegalStateException("Interface information not present in config DS for" + interfaceName);
1182 String tunnelType = ItmUtils.convertTunnelTypetoString(interfaceInfo.getTunnelType());
1183 if (!tunnelType.equalsIgnoreCase(ITMConstants.TUNNEL_TYPE_VXLAN)) {
1184 throw new IllegalArgumentException(tunnelType + " tunnel not handled by ITM");
1187 Optional<DPNTEPsInfo> dpntePsInfoOptional = dpnTEPsInfoCache.get(InstanceIdentifier.builder(DpnEndpoints.class)
1188 .child(DPNTEPsInfo.class, new DPNTEPsInfoKey(
1189 // FIXME: the cache should be caching this value, not just as a String
1190 Uint64.valueOf(dpnTepStateCache.getTunnelEndPointInfoFromCache(interfaceInfo.getTunnelName())
1191 .getDstEndPointInfo())))
1194 if (dpntePsInfoOptional.isPresent()) {
1195 dstId = dpntePsInfoOptional.get().getDstId();
1197 dstId = directTunnelUtils.allocateId(ITMConstants.ITM_IDPOOL_NAME, interfaceInfo.getRemoteDPN().toString());
1200 List<ActionInfo> result = new ArrayList<>();
1201 long regValue = MetaDataUtil.getRemoteDpnMetadatForEgressTunnelTable(dstId);
1202 int actionKeyStart = actionKey == null ? 0 : actionKey;
1203 result.add(new ActionSetFieldTunnelId(actionKeyStart++,
1204 Uint64.valueOf(tunnelKey != null ? tunnelKey : 0L)));
1205 result.add(new ActionRegLoad(actionKeyStart++, NxmNxReg6.class, MetaDataUtil.REG6_START_INDEX,
1206 MetaDataUtil.REG6_END_INDEX, regValue));
1207 result.add(new ActionNxResubmit(actionKeyStart, NwConstants.EGRESS_TUNNEL_TABLE));
1209 return Futures.immediateFuture(new GetEgressActionsForTunnelOutputBuilder()
1210 .setAction(result.stream().map(ActionInfo::buildAction).collect(Collectors.toList())).build());
1213 public static Map<DcGatewayIpKey, DcGatewayIp>
1214 getDcGatewayIpList(TypedReadWriteTransaction<Datastore.Configuration> tx)
1215 throws ExecutionException, InterruptedException {
1216 Map<DcGatewayIpKey, DcGatewayIp> dcGatewayIpMap = new HashMap<>();
1217 FluentFuture<Optional<DcGatewayIpList>> future =
1218 tx.read(InstanceIdentifier.builder(DcGatewayIpList.class).build());
1219 future.addCallback(new FutureCallback<Optional<DcGatewayIpList>>() {
1221 public void onSuccess(Optional<DcGatewayIpList> optional) {
1223 // FIXME: why not just use the provided optional?
1224 Optional<DcGatewayIpList> opt = future.get();
1225 if (opt.isPresent()) {
1226 DcGatewayIpList list = opt.get();
1228 dcGatewayIpMap.putAll(list.getDcGatewayIp());
1231 } catch (ExecutionException | InterruptedException e) {
1232 LOG.error("DcGateway IpList read failed", e);
1237 public void onFailure(Throwable error) {
1238 LOG.error("DcGateway IpList read failed", error);
1240 }, MoreExecutors.directExecutor());
1241 return dcGatewayIpMap;