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.mdsal.rpc.FutureRpcResults.LogLevel.ERROR;
12 import static org.opendaylight.serviceutils.tools.mdsal.rpc.FutureRpcResults.fromListenableFuture;
13 import static org.opendaylight.yangtools.yang.common.RpcResultBuilder.failed;
15 import com.google.common.base.Objects;
16 import com.google.common.base.Optional;
17 import com.google.common.util.concurrent.FutureCallback;
18 import com.google.common.util.concurrent.Futures;
19 import com.google.common.util.concurrent.ListenableFuture;
20 import com.google.common.util.concurrent.MoreExecutors;
21 import com.google.common.util.concurrent.SettableFuture;
22 import java.math.BigInteger;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.List;
29 import java.util.stream.Collectors;
30 import javax.annotation.Nonnull;
31 import javax.annotation.PostConstruct;
32 import javax.annotation.PreDestroy;
33 import javax.inject.Inject;
34 import javax.inject.Singleton;
35 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
36 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
37 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
38 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
39 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
40 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
41 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
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.NwConstants;
58 import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
59 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
60 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
61 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
62 import org.opendaylight.serviceutils.tools.mdsal.rpc.FutureRpcResults;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntry;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnTepsState;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTepsKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpns;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpnsBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpnsKey;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVteps;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVtepsBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVtepsKey;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointOutput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceOutput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwMlagDeviceInput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwMlagDeviceOutput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.BuildExternalTunnelFromDpnsInput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.BuildExternalTunnelFromDpnsOutput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsInput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsOutput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwDeviceInput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwDeviceOutput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwMlagDeviceInput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwMlagDeviceOutput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsInput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutputBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoInput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoOutput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoOutputBuilder;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutputBuilder;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutputBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameInput;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutput;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutputBuilder;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInput;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutputBuilder;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeInput;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeOutput;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeOutputBuilder;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetWatchPortForTunnelInput;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetWatchPortForTunnelOutput;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentInput;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutput;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutputBuilder;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalInput;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutput;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutputBuilder;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInput;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointOutput;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsInput;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsOutput;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInput;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsOutput;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdParamOnTunnelInput;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdParamOnTunnelOutput;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdParamOnTunnelOutputBuilder;
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.yangtools.yang.binding.InstanceIdentifier;
162 import org.opendaylight.yangtools.yang.common.RpcError;
163 import org.opendaylight.yangtools.yang.common.RpcResult;
164 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
165 import org.slf4j.Logger;
166 import org.slf4j.LoggerFactory;
169 public class ItmManagerRpcService implements ItmRpcService {
171 private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
173 private final DataBroker dataBroker;
174 private final IMdsalApiManager mdsalManager;
175 private final DPNTEPsInfoCache dpnTEPsInfoCache;
176 private final ItmExternalTunnelAddWorker externalTunnelAddWorker;
177 private final SingleTransactionDataBroker singleTransactionDataBroker;
178 private final IInterfaceManager interfaceManager;
179 private final InterfaceManagerService interfaceManagerService;
180 private final DpnTepStateCache dpnTepStateCache;
181 private final TunnelStateCache tunnelStateCache;
182 private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache;
183 private final DirectTunnelUtils directTunnelUtils;
184 private final ManagedNewTransactionRunner txRunner;
187 public ItmManagerRpcService(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
188 final ItmConfig itmConfig, final DPNTEPsInfoCache dpnTEPsInfoCache,
189 final IInterfaceManager interfaceManager, final DpnTepStateCache dpnTepStateCache,
190 final TunnelStateCache tunnelStateCache,
191 final InterfaceManagerService interfaceManagerService,
192 final OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
193 final DirectTunnelUtils directTunnelUtils) {
194 this.dataBroker = dataBroker;
195 this.mdsalManager = mdsalManager;
196 this.dpnTEPsInfoCache = dpnTEPsInfoCache;
197 this.externalTunnelAddWorker = new ItmExternalTunnelAddWorker(dataBroker, itmConfig, dpnTEPsInfoCache);
198 this.singleTransactionDataBroker = new SingleTransactionDataBroker(dataBroker);
199 this.interfaceManager = interfaceManager;
200 this.interfaceManagerService = interfaceManagerService;
201 this.dpnTepStateCache = dpnTepStateCache;
202 this.tunnelStateCache = tunnelStateCache;
203 this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache;
204 this.directTunnelUtils = directTunnelUtils;
205 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
209 public void start() {
210 LOG.info("ItmManagerRpcService Started");
214 public void close() {
215 LOG.info("ItmManagerRpcService Closed");
219 public ListenableFuture<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(
220 GetTunnelInterfaceNameInput input) {
221 RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
222 BigInteger sourceDpn = input.getSourceDpid();
223 BigInteger destinationDpn = input.getDestinationDpid();
224 Optional<InternalTunnel> optTunnel = Optional.absent();
226 if (interfaceManager.isItmDirectTunnelsEnabled()) {
227 DpnTepInterfaceInfo interfaceInfo = dpnTepStateCache.getDpnTepInterface(sourceDpn, destinationDpn);
228 if (interfaceInfo != null) {
229 resultBld = RpcResultBuilder.success();
230 resultBld.withResult(new GetTunnelInterfaceNameOutputBuilder()
231 .setInterfaceName(interfaceInfo.getTunnelName())).build();
232 return Futures.immediateFuture(resultBld.build());
235 if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
236 optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn,
237 TunnelTypeLogicalGroup.class, dataBroker);
238 LOG.debug("MULTIPLE_VxLAN_TUNNELS: getTunnelInterfaceName {}", optTunnel);
240 if (!optTunnel.isPresent()) {
241 optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn, input.getTunnelType(), dataBroker);
243 if (optTunnel.isPresent()) {
244 InternalTunnel tunnel = optTunnel.get();
245 GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
246 List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
247 if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
248 output.setInterfaceName(tunnelInterfaces.get(0));
249 resultBld = RpcResultBuilder.success();
250 resultBld.withResult(output.build());
252 resultBld = failed();
256 resultBld = failed();
258 return Futures.immediateFuture(resultBld.build());
262 public ListenableFuture<RpcResult<GetEgressActionsForTunnelOutput>>
263 getEgressActionsForTunnel(GetEgressActionsForTunnelInput input) {
264 String tunnelName = input.getIntfName();
265 if (tunnelName == null) {
266 return Futures.immediateFuture(RpcResultBuilder.<GetEgressActionsForTunnelOutput>failed()
267 .withError(RpcError.ErrorType.APPLICATION,
268 "tunnel name not set for GetEgressActionsForTunnel call").build());
270 if (!dpnTepStateCache.isInternal(tunnelName) || !interfaceManager.isItmDirectTunnelsEnabled()) {
271 // Re-direct the RPC to Interface Manager
272 // From the rpc input and get the output and copy to output
273 org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
274 .GetEgressActionsForInterfaceInputBuilder inputIfmBuilder =
275 new org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
276 .GetEgressActionsForInterfaceInputBuilder().setIntfName(input.getIntfName())
277 .setTunnelKey(input.getTunnelKey()).setActionKey(input.getActionKey());
278 SettableFuture<RpcResult<GetEgressActionsForTunnelOutput>> settableFuture = SettableFuture.create();
279 Futures.addCallback(interfaceManagerService.getEgressActionsForInterface(inputIfmBuilder.build()),
280 new FutureCallback<org.opendaylight.yang.gen.v1.urn.opendaylight.genius
281 .interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput>() {
283 public void onSuccess(@Nonnull org.opendaylight.yang.gen.v1.urn.opendaylight.genius
284 .interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput result) {
285 GetEgressActionsForTunnelOutputBuilder output =
286 new GetEgressActionsForTunnelOutputBuilder().setAction(result.getAction());
287 settableFuture.set(RpcResultBuilder.<GetEgressActionsForTunnelOutput>success()
288 .withResult(output.build()).build());
292 public void onFailure(Throwable throwable) {
293 LOG.debug("RPC Call to Get egress actions failed for interface {}", tunnelName);
294 String errMsg = String.format("RPC call to get egress actions failed for interface %s",
296 settableFuture.set(RpcResultBuilder.<GetEgressActionsForTunnelOutput>failed()
297 .withError(RpcError.ErrorType.APPLICATION, errMsg, throwable).build());
300 return settableFuture;
302 return fromListenableFuture(LOG, input, () -> getEgressActionsForInterface(input.getIntfName(),
303 input.getTunnelKey(), input.getActionKey())).onFailureLogLevel(ERROR).build();
308 public ListenableFuture<RpcResult<GetTunnelTypeOutput>> getTunnelType(GetTunnelTypeInput input) {
309 String tunnelName = input.getIntfName();
310 if (tunnelName == null) {
311 return Futures.immediateFuture(RpcResultBuilder.<GetTunnelTypeOutput>failed()
312 .withError(RpcError.ErrorType.APPLICATION,
313 "tunnel name not set for getTunnelType call").build());
316 if (!dpnTepStateCache.isInternal(tunnelName) || !interfaceManager.isItmDirectTunnelsEnabled()) {
317 org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
318 .GetTunnelTypeInputBuilder inputBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight
319 .genius.interfacemanager.rpcs.rev160406.GetTunnelTypeInputBuilder()
320 .setIntfName(input.getIntfName());
321 SettableFuture<RpcResult<GetTunnelTypeOutput>> settableFuture = SettableFuture.create();
322 Futures.addCallback(interfaceManagerService.getTunnelType(inputBuilder.build()),
323 new FutureCallback<org.opendaylight.yang.gen.v1.urn.opendaylight.genius
324 .interfacemanager.rpcs.rev160406.GetTunnelTypeOutput>() {
325 public void onSuccess(@Nonnull org.opendaylight.yang.gen.v1.urn.opendaylight.genius
326 .interfacemanager.rpcs.rev160406.GetTunnelTypeOutput result) {
327 GetTunnelTypeOutputBuilder output = new GetTunnelTypeOutputBuilder()
328 .setTunnelType(result.getTunnelType());
329 settableFuture.set(RpcResultBuilder.<GetTunnelTypeOutput>success()
330 .withResult(output.build()).build());
333 public void onFailure(Throwable throwable) {
334 LOG.debug("RPC Call to Get tunnel type failed for interface {}", tunnelName);
335 String errMsg = String.format("RPC to Get tunnel type failed for interface %s",
337 settableFuture.set(RpcResultBuilder.<GetTunnelTypeOutput>failed()
338 .withError(RpcError.ErrorType.APPLICATION, errMsg, throwable).build());
341 return settableFuture;
343 LOG.debug("get tunnel type from ITM for interface name {}", input.getIntfName());
344 return FutureRpcResults.fromBuilder(LOG, input, () -> {
345 DpnTepInterfaceInfo ifInfo = dpnTepStateCache.getTunnelFromCache(input.getIntfName());
346 return new GetTunnelTypeOutputBuilder().setTunnelType(ifInfo.getTunnelType());
352 public ListenableFuture<RpcResult<SetBfdParamOnTunnelOutput>> setBfdParamOnTunnel(
353 SetBfdParamOnTunnelInput input) {
354 BigInteger srcDpnId = new BigInteger(input.getSourceNode());
355 BigInteger destDpnId = new BigInteger(input.getDestinationNode());
356 DpnTepInterfaceInfo dpnTepInterfaceInfo = dpnTepStateCache.getDpnTepInterface(srcDpnId, destDpnId);
357 return fromListenableFuture(LOG, input,
358 () -> Futures.transform(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
359 java.util.Objects.requireNonNull(dpnTepInterfaceInfo, "dpnTepInterfaceInfo");
360 RemoteDpnsBuilder remoteDpnsBuilder = new RemoteDpnsBuilder();
361 remoteDpnsBuilder.withKey(new RemoteDpnsKey(destDpnId));
362 remoteDpnsBuilder.setDestinationDpnId(destDpnId);
363 remoteDpnsBuilder.setTunnelName(dpnTepInterfaceInfo.getTunnelName());
364 remoteDpnsBuilder.setInternal(dpnTepInterfaceInfo.isInternal());
365 if (input.isMonitoringEnabled() && input.getMonitoringInterval() != null) {
366 remoteDpnsBuilder.setMonitoringInterval(input.getMonitoringInterval());
368 remoteDpnsBuilder.setMonitoringEnabled(input.isMonitoringEnabled());
369 RemoteDpns remoteDpn = remoteDpnsBuilder.build();
370 Optional<OvsBridgeRefEntry> ovsBridgeRefEntry = ovsBridgeRefEntryCache.get(srcDpnId);
371 directTunnelUtils.updateBfdConfiguration(srcDpnId, remoteDpn, ovsBridgeRefEntry);
372 InstanceIdentifier<RemoteDpns> iid = InstanceIdentifier.builder(DpnTepsState.class)
373 .child(DpnsTeps.class, new DpnsTepsKey(srcDpnId))
374 .child(RemoteDpns.class,
375 new RemoteDpnsKey(destDpnId)).build();
376 tx.merge(LogicalDatastoreType.CONFIGURATION, iid, remoteDpn);
377 }), unused -> new SetBfdParamOnTunnelOutputBuilder().build(), MoreExecutors.directExecutor())).build();
381 public ListenableFuture<RpcResult<RemoveExternalTunnelEndpointOutput>> removeExternalTunnelEndpoint(
382 RemoveExternalTunnelEndpointInput input) {
383 //Ignore the Futures for now
384 final SettableFuture<RpcResult<RemoveExternalTunnelEndpointOutput>> result = SettableFuture.create();
385 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
386 ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, meshedDpnList,
387 input.getDestinationIp(), input.getTunnelType());
388 InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
389 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
390 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
391 transaction.delete(LogicalDatastoreType.CONFIGURATION, extPath);
392 ListenableFuture<Void> futureCheck = transaction.submit();
393 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
395 @Override public void onSuccess(Void voidInstance) {
396 result.set(RpcResultBuilder.<RemoveExternalTunnelEndpointOutput>success().build());
399 @Override public void onFailure(Throwable error) {
400 String msg = "Unable to delete DcGatewayIp " + input.getDestinationIp()
401 + " in datastore and tunnel type " + input.getTunnelType();
402 LOG.error("Unable to delete DcGatewayIp {} in datastore and tunnel type {}", input.getDestinationIp(),
403 input.getTunnelType());
404 result.set(RpcResultBuilder.<RemoveExternalTunnelEndpointOutput>failed()
405 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
412 public ListenableFuture<RpcResult<RemoveExternalTunnelFromDpnsOutput>> removeExternalTunnelFromDpns(
413 RemoveExternalTunnelFromDpnsInput input) {
414 //Ignore the Futures for now
415 final SettableFuture<RpcResult<RemoveExternalTunnelFromDpnsOutput>> result = SettableFuture.create();
416 List<DPNTEPsInfo> cfgDpnList = ItmUtils.getDpnTepListFromDpnId(dpnTEPsInfoCache, input.getDpnId()) ;
417 ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, cfgDpnList,
418 input.getDestinationIp(), input.getTunnelType());
419 result.set(RpcResultBuilder.<RemoveExternalTunnelFromDpnsOutput>success().build());
424 public ListenableFuture<RpcResult<BuildExternalTunnelFromDpnsOutput>> buildExternalTunnelFromDpns(
425 BuildExternalTunnelFromDpnsInput input) {
426 //Ignore the Futures for now
427 final SettableFuture<RpcResult<BuildExternalTunnelFromDpnsOutput>> result = SettableFuture.create();
428 List<ListenableFuture<Void>> extTunnelResultList = externalTunnelAddWorker
429 .buildTunnelsFromDpnToExternalEndPoint(input.getDpnId(), input.getDestinationIp(),input.getTunnelType());
430 for (ListenableFuture<Void> extTunnelResult : extTunnelResultList) {
431 Futures.addCallback(extTunnelResult, new FutureCallback<Void>() {
434 public void onSuccess(Void voidInstance) {
435 result.set(RpcResultBuilder.<BuildExternalTunnelFromDpnsOutput>success().build());
439 public void onFailure(Throwable error) {
440 String msg = "Unable to create ext tunnel";
441 LOG.error("create ext tunnel failed. {}.", msg, error);
442 result.set(RpcResultBuilder.<BuildExternalTunnelFromDpnsOutput>failed()
443 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
451 public ListenableFuture<RpcResult<AddExternalTunnelEndpointOutput>> addExternalTunnelEndpoint(
452 AddExternalTunnelEndpointInput input) {
453 // TODO Auto-generated method stub
455 //Ignore the Futures for now
456 final SettableFuture<RpcResult<AddExternalTunnelEndpointOutput>> result = SettableFuture.create();
457 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
458 externalTunnelAddWorker.buildTunnelsToExternalEndPoint(meshedDpnList,
459 input.getDestinationIp(), input.getTunnelType());
460 InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
461 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
462 DcGatewayIp dcGatewayIp =
463 new DcGatewayIpBuilder().setIpAddress(input.getDestinationIp())
464 .setTunnnelType(input.getTunnelType()).build();
465 WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
466 writeTransaction.put(LogicalDatastoreType.CONFIGURATION, extPath,dcGatewayIp, true);
467 ListenableFuture<Void> futureCheck = writeTransaction.submit();
468 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
470 @Override public void onSuccess(Void voidInstance) {
471 result.set(RpcResultBuilder.<AddExternalTunnelEndpointOutput>success().build());
474 @Override public void onFailure(Throwable error) {
476 "Unable to create DcGatewayIp {} in datastore for ip " + input.getDestinationIp() + "and "
477 + "tunnel type " + input.getTunnelType();
479 LOG.error("Unable to create DcGatewayIp in datastore for ip {} and tunnel type {}",
480 input.getDestinationIp() , input.getTunnelType());
481 result.set(RpcResultBuilder.<AddExternalTunnelEndpointOutput>failed()
482 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
489 public ListenableFuture<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
490 GetExternalTunnelInterfaceNameInput input) {
491 SettableFuture.create();
492 RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
493 String sourceNode = input.getSourceNode();
494 String dstNode = input.getDestinationNode();
495 ExternalTunnelKey externalTunnelKey = new ExternalTunnelKey(dstNode, sourceNode, input.getTunnelType());
496 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
497 ExternalTunnelList.class)
498 .child(ExternalTunnel.class, externalTunnelKey);
499 ExternalTunnel exTunnel =
500 ItmUtils.getExternalTunnelbyExternalTunnelKey(externalTunnelKey, path, this.dataBroker);
501 if (exTunnel != null) {
502 GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder();
503 output.setInterfaceName(exTunnel.getTunnelInterfaceName());
504 resultBld = RpcResultBuilder.success();
505 resultBld.withResult(output.build());
507 resultBld = failed();
510 return Futures.immediateFuture(resultBld.build());
514 public ListenableFuture<RpcResult<CreateTerminatingServiceActionsOutput>>
515 createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
516 LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}",
517 input.getDpnId() , input.getServiceId(), input.getInstruction());
518 final SettableFuture<RpcResult<CreateTerminatingServiceActionsOutput>> result = SettableFuture.create();
519 int serviceId = input.getServiceId() ;
520 final List<MatchInfo> mkMatches = getTunnelMatchesForServiceId(serviceId);
522 Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
523 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,serviceId), 5,
524 String.format("%s:%d","ITM Flow Entry ",serviceId), 0, 0,
525 ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(serviceId)),mkMatches, input.getInstruction());
527 ListenableFuture<Void> installFlowResult = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
528 tx -> mdsalManager.addFlow(tx, input.getDpnId(), terminatingServiceTableFlow));
529 Futures.addCallback(installFlowResult, new FutureCallback<Void>() {
532 public void onSuccess(Void voidInstance) {
533 result.set(RpcResultBuilder.<CreateTerminatingServiceActionsOutput>success().build());
537 public void onFailure(Throwable error) {
538 String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
539 LOG.error("create terminating service actions failed. {}", msg, error);
540 result.set(RpcResultBuilder.<CreateTerminatingServiceActionsOutput>failed()
541 .withError(RpcError.ErrorType.APPLICATION, msg, error)
544 }, MoreExecutors.directExecutor());
545 // result.set(RpcResultBuilder.<Void>success().build());
550 public ListenableFuture<RpcResult<RemoveTerminatingServiceActionsOutput>>
551 removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
552 LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}",
553 input.getDpnId(), input.getServiceId());
554 final SettableFuture<RpcResult<RemoveTerminatingServiceActionsOutput>> result = SettableFuture.create();
556 ListenableFuture<Void> removeFlowResult = txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
557 tx -> mdsalManager.removeFlow(tx, input.getDpnId(),
558 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, input.getServiceId()),
559 NwConstants.INTERNAL_TUNNEL_TABLE));
560 Futures.addCallback(removeFlowResult, new FutureCallback<Void>() {
563 public void onSuccess(Void voidInstance) {
564 result.set(RpcResultBuilder.<RemoveTerminatingServiceActionsOutput>success().build());
568 public void onFailure(Throwable error) {
569 String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
570 LOG.error("remove terminating service actions failed. {}", msg, error);
571 result.set(RpcResultBuilder.<RemoveTerminatingServiceActionsOutput>failed()
572 .withError(RpcError.ErrorType.APPLICATION, msg, error)
575 }, MoreExecutors.directExecutor());
576 //result.set(RpcResultBuilder.<Void>success().build());
582 public List<MatchInfo> getTunnelMatchesForServiceId(int serviceId) {
583 final List<MatchInfo> mkMatches = new ArrayList<>();
586 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(serviceId)));
591 private String getFlowRef(long termSvcTable, int svcId) {
592 return String.valueOf(termSvcTable) + svcId;
596 public ListenableFuture<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
597 GetInternalOrExternalInterfaceNameInput input) {
598 RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = failed();
599 BigInteger srcDpn = input.getSourceDpid() ;
600 IpAddress dstIp = input.getDestinationIp() ;
601 InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(ExternalTunnelList.class)
602 .child(ExternalTunnel.class,
603 new ExternalTunnelKey(dstIp.stringValue(), srcDpn.toString(), input.getTunnelType()));
605 Optional<ExternalTunnel> optExtTunnel = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
607 if (optExtTunnel != null && optExtTunnel.isPresent()) {
608 ExternalTunnel extTunnel = optExtTunnel.get();
609 GetInternalOrExternalInterfaceNameOutputBuilder output =
610 new GetInternalOrExternalInterfaceNameOutputBuilder()
611 .setInterfaceName(extTunnel.getTunnelInterfaceName());
612 resultBld = RpcResultBuilder.success();
613 resultBld.withResult(output.build()) ;
615 Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
617 // Look for external tunnels if not look for internal tunnel
618 for (DPNTEPsInfo teps : meshedDpnList) {
619 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
620 if (dstIp.equals(firstEndPt.getIpAddress())) {
621 Optional<InternalTunnel> optTunnel = Optional.absent();
622 if (interfaceManager.isItmDirectTunnelsEnabled()) {
623 DpnTepInterfaceInfo interfaceInfo =
624 dpnTepStateCache.getDpnTepInterface(srcDpn, teps.getDPNID());
625 if (interfaceInfo != null) {
626 resultBld = RpcResultBuilder.success();
627 resultBld.withResult(new GetInternalOrExternalInterfaceNameOutputBuilder()
628 .setInterfaceName(interfaceInfo.getTunnelName())).build();
629 return Futures.immediateFuture(resultBld.build());
633 if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
634 optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
635 TunnelTypeLogicalGroup.class, dataBroker);
636 LOG.debug("MULTIPLE_VxLAN_TUNNELS: getInternalOrExternalInterfaceName {}", optTunnel);
638 if (!optTunnel.isPresent()) {
639 optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
640 input.getTunnelType(), dataBroker);
642 if (optTunnel.isPresent()) {
643 InternalTunnel tunnel = optTunnel.get();
644 List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
645 if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
646 GetInternalOrExternalInterfaceNameOutputBuilder
648 new GetInternalOrExternalInterfaceNameOutputBuilder()
649 .setInterfaceName(tunnelInterfaces.get(0));
650 resultBld = RpcResultBuilder.success();
651 resultBld.withResult(output.build());
653 LOG.error("No tunnel interface found between source DPN {} ans destination IP {}", srcDpn,
658 LOG.error("Tunnel not found for source DPN {} ans destination IP {}", srcDpn, dstIp);
663 return Futures.immediateFuture(resultBld.build());
666 @SuppressWarnings("checkstyle:IllegalCatch")
668 public ListenableFuture<RpcResult<DeleteL2GwDeviceOutput>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
669 final SettableFuture<RpcResult<DeleteL2GwDeviceOutput>> result = SettableFuture.create();
670 boolean foundVxlanTzone = false;
672 final IpAddress hwIp = input.getIpAddress();
673 final String nodeId = input.getNodeId();
674 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
675 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
676 containerPath, dataBroker);
677 if (transportZonesOptional.isPresent()) {
678 TransportZones transportZones = transportZonesOptional.get();
679 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
680 LOG.error("No teps configured");
681 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
682 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
685 for (TransportZone tzone : transportZones.getTransportZone()) {
686 if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
689 foundVxlanTzone = true;
690 String transportZone = tzone.getZoneName();
691 if (tzone.getSubnets() == null || tzone.getSubnets().isEmpty()) {
692 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
693 .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
696 SubnetsKey subnetsKey = tzone.getSubnets().get(0).key();
697 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
698 InstanceIdentifier<DeviceVteps> path = InstanceIdentifier.builder(TransportZones.class)
699 .child(TransportZone.class, new TransportZoneKey(transportZone))
700 .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey)
702 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
703 //TO DO: add retry if it fails
705 transaction.delete(LogicalDatastoreType.CONFIGURATION, path);
707 ListenableFuture<Void> futureCheck = transaction.submit();
708 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
710 @Override public void onSuccess(Void voidInstance) {
711 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>success().build());
714 @Override public void onFailure(Throwable error) {
715 String msg = String.format("Unable to delete HwVtep %s from datastore", nodeId);
716 LOG.error("Unable to delete HwVtep {}, {} from datastore", nodeId, hwIp);
717 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
718 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
724 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
725 .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
729 if (!foundVxlanTzone) {
730 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
731 .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
736 } catch (Exception e) {
737 RpcResultBuilder<DeleteL2GwDeviceOutput> resultBuilder = RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
738 .withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
739 return Futures.immediateFuture(resultBuilder.build());
743 @SuppressWarnings("checkstyle:IllegalCatch")
745 public ListenableFuture<RpcResult<AddL2GwDeviceOutput>> addL2GwDevice(AddL2GwDeviceInput input) {
747 final SettableFuture<RpcResult<AddL2GwDeviceOutput>> result = SettableFuture.create();
748 boolean foundVxlanTzone = false;
750 final IpAddress hwIp = input.getIpAddress();
751 final String nodeId = input.getNodeId();
752 //iterate through all transport zones and put TORs under vxlan
753 //if no vxlan tzone is cnfigured, return an error.
754 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
755 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
756 containerPath, dataBroker);
757 if (transportZonesOptional.isPresent()) {
758 TransportZones transportZones = transportZonesOptional.get();
759 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
760 LOG.error("No transportZone configured");
761 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
762 .withError(RpcError.ErrorType.APPLICATION, "No transportZone Configured").build());
765 for (TransportZone tzone : transportZones.getTransportZone()) {
766 if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
769 String transportZone = tzone.getZoneName();
770 if (tzone.getSubnets() == null || tzone.getSubnets().isEmpty()) {
773 foundVxlanTzone = true;
774 SubnetsKey subnetsKey = tzone.getSubnets().get(0).key();
775 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
776 InstanceIdentifier<DeviceVteps> path = InstanceIdentifier.builder(TransportZones.class)
777 .child(TransportZone.class, new TransportZoneKey(transportZone))
778 .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey)
780 DeviceVteps deviceVtep = new DeviceVtepsBuilder().withKey(deviceVtepKey).setIpAddress(hwIp)
781 .setNodeId(nodeId).setTopologyId(input.getTopologyId()).build();
782 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
783 //TO DO: add retry if it fails
784 transaction.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
786 ListenableFuture<Void> futureCheck = transaction.submit();
787 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
789 @Override public void onSuccess(Void voidInstance) {
790 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>success().build());
793 @Override public void onFailure(Throwable error) {
794 String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
795 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId, hwIp);
796 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
797 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
803 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
804 .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
808 if (!foundVxlanTzone) {
809 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
810 .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
815 } catch (Exception e) {
816 RpcResultBuilder<AddL2GwDeviceOutput> resultBuilder = RpcResultBuilder.<AddL2GwDeviceOutput>failed()
817 .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
818 return Futures.immediateFuture(resultBuilder.build());
823 public ListenableFuture<RpcResult<GetWatchPortForTunnelOutput>> getWatchPortForTunnel(
824 GetWatchPortForTunnelInput input) {
825 throw new UnsupportedOperationException("TODO");
828 @SuppressWarnings("checkstyle:IllegalCatch")
830 public ListenableFuture<RpcResult<AddL2GwMlagDeviceOutput>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input) {
832 final SettableFuture<RpcResult<AddL2GwMlagDeviceOutput>> result = SettableFuture.create();
834 final IpAddress hwIp = input.getIpAddress();
835 final List<String> nodeId = input.getNodeId();
836 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
837 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
838 containerPath, dataBroker);
839 if (transportZonesOptional.isPresent()) {
840 TransportZones transportZones = transportZonesOptional.get();
841 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
842 LOG.error("No teps configured");
843 result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
844 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
847 String transportZone = transportZones.getTransportZone().get(0).getZoneName();
848 if (transportZones.getTransportZone().get(0).getSubnets() == null
849 || transportZones.getTransportZone().get(0).getSubnets().isEmpty()) {
850 result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
851 .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
854 SubnetsKey subnetsKey = transportZones.getTransportZone().get(0).getSubnets().get(0).key();
855 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
856 InstanceIdentifier<DeviceVteps> path =
857 InstanceIdentifier.builder(TransportZones.class)
858 .child(TransportZone.class, new TransportZoneKey(transportZone))
859 .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build();
860 DeviceVteps deviceVtep = new DeviceVtepsBuilder().withKey(deviceVtepKey).setIpAddress(hwIp)
861 .setNodeId(nodeId.get(0)).setTopologyId(input.getTopologyId()).build();
862 WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
863 //TO DO: add retry if it fails
864 LOG.trace("writing hWvtep{}",deviceVtep);
865 writeTransaction.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
867 if (nodeId.size() == 2) {
868 LOG.trace("second node-id {}",nodeId.get(1));
869 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
870 InstanceIdentifier<DeviceVteps> path2 = InstanceIdentifier.builder(TransportZones.class)
871 .child(TransportZone.class, new TransportZoneKey(transportZone))
872 .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey2).build();
873 DeviceVteps deviceVtep2 = new DeviceVtepsBuilder().withKey(deviceVtepKey2).setIpAddress(hwIp)
874 .setNodeId(nodeId.get(1))
875 .setTopologyId(input.getTopologyId()).build();
876 //TO DO: add retry if it fails
877 LOG.trace("writing {}",deviceVtep2);
878 writeTransaction.put(LogicalDatastoreType.CONFIGURATION, path2, deviceVtep2, true);
880 ListenableFuture<Void> futureCheck = writeTransaction.submit();
881 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
884 public void onSuccess(Void voidInstance) {
885 result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>success().build());
889 public void onFailure(Throwable error) {
890 String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
891 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
892 result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
893 .withError(RpcError.ErrorType.APPLICATION, msg, error)
896 }, MoreExecutors.directExecutor());
899 } catch (RuntimeException e) {
900 RpcResultBuilder<AddL2GwMlagDeviceOutput> resultBuilder = RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
901 .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
902 return Futures.immediateFuture(resultBuilder.build());
906 @SuppressWarnings("checkstyle:IllegalCatch")
908 public ListenableFuture<RpcResult<DeleteL2GwMlagDeviceOutput>> deleteL2GwMlagDevice(
909 DeleteL2GwMlagDeviceInput input) {
910 final SettableFuture<RpcResult<DeleteL2GwMlagDeviceOutput>> result = SettableFuture.create();
912 final IpAddress hwIp = input.getIpAddress();
913 final List<String> nodeId = input.getNodeId();
914 InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
915 Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
916 containerPath, dataBroker);
917 if (transportZonesOptional.isPresent()) {
918 TransportZones tzones = transportZonesOptional.get();
919 if (tzones.getTransportZone() == null || tzones.getTransportZone().isEmpty()) {
920 LOG.error("No teps configured");
921 result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed()
922 .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
925 String transportZone = tzones.getTransportZone().get(0).getZoneName();
926 if (tzones.getTransportZone().get(0).getSubnets() == null || tzones.getTransportZone()
927 .get(0).getSubnets().isEmpty()) {
928 result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed()
929 .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
932 SubnetsKey subnetsKey = tzones.getTransportZone().get(0).getSubnets().get(0).key();
933 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
934 InstanceIdentifier<DeviceVteps> path =
935 InstanceIdentifier.builder(TransportZones.class)
936 .child(TransportZone.class, new TransportZoneKey(transportZone))
937 .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
938 deviceVtepKey).build();
939 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
940 //TO DO: add retry if it fails
941 transaction.delete(LogicalDatastoreType.CONFIGURATION, path);
943 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
944 InstanceIdentifier<DeviceVteps> path2 =
945 InstanceIdentifier.builder(TransportZones.class)
946 .child(TransportZone.class, new TransportZoneKey(transportZone))
947 .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
948 deviceVtepKey2).build();
949 //TO DO: add retry if it fails
950 transaction.delete(LogicalDatastoreType.CONFIGURATION, path2);
952 ListenableFuture<Void> futureCheck = transaction.submit();
953 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
956 public void onSuccess(Void voidInstance) {
957 result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>success().build());
961 public void onFailure(Throwable error) {
962 String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
963 LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
964 result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed()
965 .withError(RpcError.ErrorType.APPLICATION, msg, error)
971 } catch (Exception e) {
972 RpcResultBuilder<DeleteL2GwMlagDeviceOutput> resultBuilder =
973 RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed().withError(RpcError.ErrorType.APPLICATION,
974 "Deleting l2 Gateway to DS Failed", e);
975 return Futures.immediateFuture(resultBuilder.build());
980 public ListenableFuture<RpcResult<IsTunnelInternalOrExternalOutput>> isTunnelInternalOrExternal(
981 IsTunnelInternalOrExternalInput input) {
982 RpcResultBuilder<IsTunnelInternalOrExternalOutput> resultBld;
983 String tunIfName = input.getTunnelInterfaceName();
985 IsTunnelInternalOrExternalOutputBuilder output = new IsTunnelInternalOrExternalOutputBuilder()
986 .setTunnelType(tunVal);
988 if (ItmUtils.ITM_CACHE.getInternalTunnel(tunIfName) != null) {
990 } else if (ItmUtils.ITM_CACHE.getExternalTunnel(tunIfName) != null) {
993 output.setTunnelType(tunVal);
994 resultBld = RpcResultBuilder.success();
995 resultBld.withResult(output.build());
996 return Futures.immediateFuture(resultBld.build());
1000 public ListenableFuture<RpcResult<IsDcgwPresentOutput>> isDcgwPresent(IsDcgwPresentInput input) {
1001 RpcResultBuilder<IsDcgwPresentOutput> resultBld = RpcResultBuilder.success();
1003 List<DcGatewayIp> dcGatewayIpList = ItmUtils.getDcGatewayIpList(dataBroker);
1004 String dcgwIpStr = input.getDcgwIp();
1005 IpAddress dcgwIpAddr = IpAddressBuilder.getDefaultInstance(dcgwIpStr);
1008 if (dcGatewayIpList != null && !dcGatewayIpList.isEmpty()
1009 && dcGatewayIpList.stream().anyMatch(gwIp -> Objects.equal(gwIp.getIpAddress(), dcgwIpAddr))) {
1012 IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
1013 resultBld.withResult(output.build());
1017 IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
1018 resultBld.withResult(output.build());
1020 return Futures.immediateFuture(resultBld.build());
1024 public ListenableFuture<RpcResult<GetDpnEndpointIpsOutput>> getDpnEndpointIps(GetDpnEndpointIpsInput input) {
1025 BigInteger srcDpn = input.getSourceDpid() ;
1026 RpcResultBuilder<GetDpnEndpointIpsOutput> resultBld = failed();
1027 InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
1028 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class,
1029 new DPNTEPsInfoKey(srcDpn)).build();
1030 Optional<DPNTEPsInfo> tunnelInfo = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tunnelInfoId, dataBroker);
1031 if (!tunnelInfo.isPresent()) {
1032 LOG.error("tunnelInfo is not present");
1033 return Futures.immediateFuture(resultBld.build());
1036 List<TunnelEndPoints> tunnelEndPointList = tunnelInfo.get().getTunnelEndPoints();
1037 if (tunnelEndPointList == null || tunnelEndPointList.isEmpty()) {
1038 LOG.error("tunnelEndPointList is null or empty");
1039 return Futures.immediateFuture(resultBld.build());
1042 List<IpAddress> nexthopIpList = new ArrayList<>();
1043 tunnelEndPointList.forEach(tunnelEndPoint -> nexthopIpList.add(tunnelEndPoint.getIpAddress()));
1045 GetDpnEndpointIpsOutputBuilder output = new GetDpnEndpointIpsOutputBuilder().setNexthopipList(nexthopIpList);
1046 resultBld = RpcResultBuilder.success();
1047 resultBld.withResult(output.build()) ;
1048 return Futures.immediateFuture(resultBld.build());
1052 public ListenableFuture<RpcResult<GetDpnInfoOutput>> getDpnInfo(GetDpnInfoInput input) {
1053 return FutureRpcResults.fromListenableFuture(LOG, "getDpnInfo", input,
1054 () -> Futures.immediateFuture(getDpnInfoInternal(input))).build();
1057 private GetDpnInfoOutput getDpnInfoInternal(GetDpnInfoInput input) throws ReadFailedException {
1058 Map<String, BigInteger> computeNamesVsDpnIds
1059 = getDpnIdByComputeNodeNameFromOpInventoryNodes(input.getComputeNames());
1060 Map<BigInteger, ComputesBuilder> dpnIdVsVtepsComputes
1061 = getTunnelEndPointByDpnIdFromTranPortZone(computeNamesVsDpnIds.values());
1062 List<Computes> computes = computeNamesVsDpnIds.entrySet().stream()
1063 .map(entry -> dpnIdVsVtepsComputes.get(entry.getValue()).setComputeName(entry.getKey()).build())
1064 .collect(Collectors.toList());
1065 return new GetDpnInfoOutputBuilder().setComputes(computes).build();
1068 private Map<BigInteger, ComputesBuilder> getTunnelEndPointByDpnIdFromTranPortZone(Collection<BigInteger> dpnIds)
1069 throws ReadFailedException {
1070 TransportZones transportZones = singleTransactionDataBroker.syncRead(
1071 LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(TransportZones.class).build());
1072 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
1073 throw new IllegalStateException("Failed to find transport zones in config datastore");
1075 Map<BigInteger, ComputesBuilder> result = new HashMap<>();
1076 for (TransportZone transportZone : transportZones.getTransportZone()) {
1077 if (transportZone.getSubnets() == null || transportZone.getSubnets().isEmpty()) {
1078 LOG.debug("Transport Zone {} has no subnets", transportZone.getZoneName());
1081 for (Subnets sub : transportZone.getSubnets()) {
1082 if (sub.getVteps() == null || sub.getVteps().isEmpty()) {
1083 LOG.debug("Transport Zone {} subnet {} has no vteps configured",
1084 transportZone.getZoneName(), sub.getPrefix());
1087 for (Vteps vtep : sub.getVteps()) {
1088 if (dpnIds.contains(vtep.getDpnId())) {
1089 result.putIfAbsent(vtep.getDpnId(),
1090 new ComputesBuilder()
1091 .setZoneName(transportZone.getZoneName())
1092 .setPrefix(sub.getPrefix())
1093 .setDpnId(vtep.getDpnId())
1094 .setPortName(vtep.getPortname())
1095 .setNodeId(getNodeId(vtep.getDpnId()))
1096 .setTepIp(Collections.singletonList(vtep.getIpAddress())));
1101 for (BigInteger dpnId : dpnIds) {
1102 if (!result.containsKey(dpnId)) {
1103 throw new IllegalStateException("Failed to find dpn id " + dpnId + " in transport zone");
1109 private Map<String, BigInteger> getDpnIdByComputeNodeNameFromOpInventoryNodes(List<String> nodeNames)
1110 throws ReadFailedException {
1111 Nodes operInventoryNodes = singleTransactionDataBroker.syncRead(
1112 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(Nodes.class).build());
1113 if (operInventoryNodes.getNode() == null || operInventoryNodes.getNode().isEmpty()) {
1114 throw new IllegalStateException("Failed to find operational inventory nodes datastore");
1116 Map<String, BigInteger> result = new HashMap<>();
1117 for (Node node : operInventoryNodes.getNode()) {
1118 String name = node.augmentation(FlowCapableNode.class).getDescription();
1119 if (nodeNames.contains(name)) {
1120 String[] nodeId = node.getId().getValue().split(":");
1121 result.put(name, new BigInteger(nodeId[1]));
1124 for (String nodeName : nodeNames) {
1125 if (!result.containsKey(nodeName)) {
1126 throw new IllegalStateException("Failed to find dpn id of compute node name from oper inventory "
1133 private String getNodeId(BigInteger dpnId) throws ReadFailedException {
1134 InstanceIdentifier<BridgeRefEntry> path = InstanceIdentifier
1135 .builder(BridgeRefInfo.class)
1136 .child(BridgeRefEntry.class, new BridgeRefEntryKey(dpnId)).build();
1137 BridgeRefEntry bridgeRefEntry =
1138 singleTransactionDataBroker.syncRead(LogicalDatastoreType.OPERATIONAL, path);
1139 return bridgeRefEntry.getBridgeReference().getValue()
1140 .firstKeyOf(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021
1141 .network.topology.topology.Node.class).getNodeId().getValue();
1144 private ListenableFuture<GetEgressActionsForTunnelOutput> getEgressActionsForInterface(String interfaceName,
1145 Long tunnelKey, Integer actionKey) throws ReadFailedException {
1146 int actionKeyStart = actionKey == null ? 0 : actionKey;
1147 DpnTepInterfaceInfo interfaceInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
1148 if (interfaceInfo == null) {
1149 throw new IllegalStateException("Interface information not present in config DS for" + interfaceName);
1151 Optional<StateTunnelList> ifState = tunnelStateCache
1152 .get(tunnelStateCache.getStateTunnelListIdentifier(interfaceName));
1153 if (ifState.isPresent()) {
1154 String tunnelType = ItmUtils.convertTunnelTypetoString(interfaceInfo.getTunnelType());
1155 List<Action> actions = getEgressActionInfosForInterface(tunnelType, ifState.get().getPortNumber(),
1156 tunnelKey, actionKeyStart).stream().map(ActionInfo::buildAction).collect(Collectors.toList());
1157 return Futures.immediateFuture(new GetEgressActionsForTunnelOutputBuilder().setAction(actions).build());
1159 throw new IllegalStateException("Interface information not present in oper DS for" + interfaceName);
1162 private static List<ActionInfo> getEgressActionInfosForInterface(String tunnelType, String portNo, Long tunnelKey,
1163 int actionKeyStart) {
1164 List<ActionInfo> result = new ArrayList<>();
1165 switch (tunnelType) {
1166 case ITMConstants.TUNNEL_TYPE_GRE:
1167 case ITMConstants.TUNNEL_TYPE_MPLSoGRE:
1168 // Invoke IFM RPC and pass it on to the caller.
1169 LOG.warn("Interface Type {} not handled by ITM", tunnelType);
1171 case ITMConstants.TUNNEL_TYPE_VXLAN:
1172 //TODO tunnel_id to encode GRE key, once it is supported
1173 // Until then, tunnel_id should be "cleaned", otherwise it stores the value coming from a VXLAN tunnel
1174 result.add(new ActionSetFieldTunnelId(actionKeyStart++,
1175 BigInteger.valueOf(tunnelKey != null ? tunnelKey : 0L)));
1176 result.add(new ActionOutput(actionKeyStart, new Uri(portNo)));
1180 LOG.warn("Interface Type {} not handled yet", tunnelType);