2 * Copyright © 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.netvirt.vpnmanager;
10 import static java.util.Collections.emptyList;
11 import static java.util.stream.Collectors.toList;
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
13 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
15 import com.google.common.base.Optional;
16 import com.google.common.base.Strings;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import java.math.BigInteger;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
24 import java.util.Objects;
26 import java.util.concurrent.Callable;
27 import java.util.concurrent.Future;
28 import java.util.concurrent.locks.ReentrantLock;
29 import javax.annotation.PostConstruct;
30 import javax.inject.Inject;
31 import javax.inject.Singleton;
32 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
33 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
34 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
35 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
36 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
37 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
38 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
39 import org.opendaylight.genius.mdsalutil.MDSALUtil;
40 import org.opendaylight.genius.mdsalutil.NwConstants;
41 import org.opendaylight.genius.utils.JvmGlobalLocks;
42 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
43 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
44 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
45 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
46 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
47 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
48 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpnInterfaceListInputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpnInterfaceListOutput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.get.dpn._interface.list.output.Interfaces;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.extraroute.rds.map.extraroute.rds.DestPrefixes;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpData;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
78 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
79 import org.opendaylight.yangtools.yang.common.RpcResult;
80 import org.slf4j.Logger;
81 import org.slf4j.LoggerFactory;
84 public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBase<StateTunnelList,
85 TunnelInterfaceStateListener> {
87 private static final Logger LOG = LoggerFactory.getLogger(TunnelInterfaceStateListener.class);
89 private final DataBroker dataBroker;
90 private final ManagedNewTransactionRunner txRunner;
91 private final IFibManager fibManager;
92 private final OdlInterfaceRpcService intfRpcService;
93 private final VpnInterfaceManager vpnInterfaceManager;
94 private final VpnSubnetRouteHandler vpnSubnetRouteHandler;
95 private final JobCoordinator jobCoordinator;
96 private final VpnUtil vpnUtil;
98 protected enum UpdateRouteAction {
99 ADVERTISE_ROUTE, WITHDRAW_ROUTE
102 protected enum TunnelAction {
109 * Responsible for listening to tunnel interface state change.
110 * @param dataBroker Data Broker
111 * @param fibManager FIB APIs
112 * @param ifaceMgrRpcService Interface Manager RPC
113 * @param vpnInterfaceManager Vpn Interface APIs
114 * @param vpnSubnetRouteHandler Subnet-Route APIs
115 * @param jobCoordinator Key based job serialization mechanism
116 * @param vpnUtil Vpn Utility
119 public TunnelInterfaceStateListener(final DataBroker dataBroker,
120 final IFibManager fibManager,
121 final OdlInterfaceRpcService ifaceMgrRpcService,
122 final VpnInterfaceManager vpnInterfaceManager,
123 final VpnSubnetRouteHandler vpnSubnetRouteHandler,
124 final JobCoordinator jobCoordinator,
126 super(StateTunnelList.class, TunnelInterfaceStateListener.class);
127 this.dataBroker = dataBroker;
128 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
129 this.fibManager = fibManager;
130 this.intfRpcService = ifaceMgrRpcService;
131 this.vpnInterfaceManager = vpnInterfaceManager;
132 this.vpnSubnetRouteHandler = vpnSubnetRouteHandler;
133 this.jobCoordinator = jobCoordinator;
134 this.vpnUtil = vpnUtil;
138 public void start() {
139 LOG.info("{} start", getClass().getSimpleName());
140 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
144 protected InstanceIdentifier<StateTunnelList> getWildCardPath() {
145 return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
149 protected TunnelInterfaceStateListener getDataTreeChangeListener() {
150 return TunnelInterfaceStateListener.this;
154 protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
155 LOG.trace("remove: Tunnel deletion---- {}", del);
156 if (isGreTunnel(del)) {
157 programDcGwLoadBalancingGroup(del, NwConstants.DEL_FLOW);
159 handleTunnelEventForDPN(del, TunnelAction.TUNNEL_EP_DELETE);
163 protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original,
164 StateTunnelList update) {
165 LOG.trace("update: Tunnel updation---- {}", update);
166 LOG.info("update: ITM Tunnel {} of type {} state event changed from :{} to :{}",
167 update.getTunnelInterfaceName(),
168 fibManager.getTransportTypeStr(update.getTransportType().toString()),
169 original.getOperState(), update.getOperState());
170 TunnelOperStatus tunOpStatus = update.getOperState();
171 if (tunOpStatus != TunnelOperStatus.Down && tunOpStatus != TunnelOperStatus.Up) {
172 LOG.info("update: Returning from unsupported tunnelOperStatus {} for tunnel interface {}", tunOpStatus,
173 update.getTunnelInterfaceName());
176 if (isGreTunnel(update)) {
177 programDcGwLoadBalancingGroup(update, NwConstants.MOD_FLOW);
180 //Remove the corresponding nexthop from the routepath under extraroute in fibentries.
181 BigInteger srcDpnId = new BigInteger(update.getSrcInfo().getTepDeviceId());
182 String srcTepIp = update.getSrcInfo().getTepIp().stringValue();
183 List<VpnInstanceOpDataEntry> vpnInstanceOpData = vpnUtil.getAllVpnInstanceOpData();
184 if (vpnInstanceOpData == null) {
185 LOG.trace("update: No vpnInstanceOpdata present");
188 vpnInstanceOpData.stream()
189 .filter(opData -> opData.getVpnToDpnList() != null
190 && opData.getVpnToDpnList().stream().anyMatch(
191 vpnToDpn -> Objects.equals(vpnToDpn.getDpnId(), srcDpnId)))
193 List<DestPrefixes> prefixes = VpnExtraRouteHelper.getExtraRouteDestPrefixes(dataBroker,
195 prefixes.forEach(destPrefix -> {
196 VrfEntry vrfEntry = vpnUtil.getVrfEntry(opData.getVrfId(),
197 destPrefix.getDestPrefix());
198 if (vrfEntry == null || vrfEntry.getRoutePaths() == null) {
201 List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
202 routePaths.forEach(routePath -> {
203 if (Objects.equals(routePath.getNexthopAddress(), srcTepIp)) {
204 String prefix = destPrefix.getDestPrefix();
205 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(opData.getVpnInstanceName(),
207 // FIXME: separate out to somehow?
208 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnPrefixKey);
211 fibManager.refreshVrfEntry(opData.getVrfId(), prefix);
222 protected void add(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList add) {
223 LOG.trace("add: Tunnel addition---- {}", add);
224 TunnelOperStatus tunOpStatus = add.getOperState();
225 if (tunOpStatus != TunnelOperStatus.Down && tunOpStatus != TunnelOperStatus.Up) {
226 LOG.info("add: Returning from unsupported tunnelOperStatus {} for tunnel interface {}", tunOpStatus,
227 add.getTunnelInterfaceName());
230 if (tunOpStatus != TunnelOperStatus.Up) {
231 LOG.error("add: Tunnel {} is not yet UP.", add.getTunnelInterfaceName());
233 if (isGreTunnel(add)) {
234 programDcGwLoadBalancingGroup(add, NwConstants.ADD_FLOW);
236 LOG.info("add: ITM Tunnel ,type {} ,added between src: {} and dest: {}",
237 fibManager.getTransportTypeStr(add.getTransportType().toString()),
238 add.getSrcInfo().getTepDeviceId(), add.getDstInfo().getTepDeviceId());
239 handleTunnelEventForDPN(add, TunnelAction.TUNNEL_EP_ADD);
242 public enum TunnelEventProcessingMethod {
243 POPULATESUBNETS(0), MANAGEREMOTEROUTES(1);
245 private final int method;
247 TunnelEventProcessingMethod(int id) {
251 public int getValue() {
256 // TODO Clean up the exception handling
257 @SuppressWarnings("checkstyle:IllegalCatch")
258 private void handleTunnelEventForDPN(StateTunnelList stateTunnelList, TunnelAction tunnelAction) {
259 final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
260 final String srcTepIp = stateTunnelList.getSrcInfo().getTepIp().stringValue();
261 String destTepIp = stateTunnelList.getDstInfo().getTepIp().stringValue();
263 BigInteger remoteDpnId = null;
264 boolean isTepDeletedOnDpn = false;
266 LOG.info("handleTunnelEventForDPN: Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ",
267 srcDpnId, srcTepIp, destTepIp);
268 int tunTypeVal = getTunnelType(stateTunnelList);
269 LOG.trace("handleTunnelEventForDPN: tunTypeVal is {}", tunTypeVal);
271 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
272 LOG.info("handleTunnelEventForDPN: Tunnel ADD event received for Dpn {} VTEP Ip {} destTepIp {}",
273 srcDpnId, srcTepIp, destTepIp);
274 if (isTunnelInLogicalGroup(stateTunnelList)) {
277 } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE) {
278 LOG.info("handleTunnelEventForDPN: Tunnel DELETE event received for Dpn {} VTEP Ip {} DestTepIp {}",
279 srcDpnId, srcTepIp, destTepIp);
280 // When tunnel EP is deleted on a DPN , VPN gets two deletion event.
281 // One for a DPN on which tunnel EP was deleted and another for other-end DPN.
282 // Update the adj for the vpninterfaces for a DPN on which TEP is deleted.
283 // Update the adj & VRF for the vpninterfaces for a DPN on which TEP is deleted.
284 // Dont update the adj & VRF for vpninterfaces for a DPN on which TEP is not deleted.
285 String endpointIpForDPN;
287 endpointIpForDPN = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
288 } catch (Exception e) {
289 LOG.error("handleTunnelEventForDPN: Unable to resolve endpoint IP for srcDpn {}", srcDpnId);
290 /* this dpn does not have the VTEP */
291 endpointIpForDPN = null;
294 if (endpointIpForDPN == null) {
295 LOG.info("handleTunnelEventForDPN: Tunnel TEP is deleted on Dpn {} VTEP Ip {} destTepIp {}",
296 srcDpnId, srcTepIp, destTepIp);
297 isTepDeletedOnDpn = true;
301 // Get the list of VpnInterfaces from Intf Mgr for a SrcDPN on which TEP is added/deleted
302 Future<RpcResult<GetDpnInterfaceListOutput>> result;
303 List<Interfaces> srcDpninterfacelist = new ArrayList<>();
304 List<Interfaces> destDpninterfacelist = new ArrayList<>();
306 result = intfRpcService.getDpnInterfaceList(
307 new GetDpnInterfaceListInputBuilder().setDpid(srcDpnId).build());
308 RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
309 if (!rpcResult.isSuccessful()) {
310 LOG.error("handleTunnelEventForDPN: RPC Call to GetDpnInterfaceList for srcDpnid {} srcTepIp {}"
311 + " destTepIP {} returned with Errors {}", srcDpnId, srcTepIp, destTepIp,
312 rpcResult.getErrors());
314 srcDpninterfacelist = rpcResult.getResult().nonnullInterfaces();
316 } catch (Exception e) {
317 LOG.error("handleTunnelEventForDPN: Exception when querying for GetDpnInterfaceList for srcDpnid {}"
318 + " srcTepIp {} destTepIp {}", srcDpnId, srcTepIp, destTepIp, e);
320 // Get the list of VpnInterfaces from Intf Mgr for a destDPN only for internal tunnel.
321 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
322 remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
324 result = intfRpcService.getDpnInterfaceList(
325 new GetDpnInterfaceListInputBuilder().setDpid(remoteDpnId).build());
326 RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
327 if (!rpcResult.isSuccessful()) {
328 LOG.error("handleTunnelEventForDPN: RPC Call to GetDpnInterfaceList for remoteDpnid {}"
329 + " srcTepIP {} destTepIp {} returned with Errors {}", remoteDpnId, srcTepIp,
330 destTepIp, rpcResult.getErrors());
332 destDpninterfacelist = rpcResult.getResult().nonnullInterfaces();
334 } catch (Exception e) {
335 LOG.error("handleTunnelEventForDPN: Exception when querying for GetDpnInterfaceList"
336 + " for remoteDpnid {} srcTepIp {} destTepIp {}", remoteDpnId,
337 srcTepIp, destTepIp, e);
342 * Iterate over the list of VpnInterface for a SrcDpn on which TEP is added or deleted and read the adj.
343 * Update the adjacencies with the updated nexthop.
345 List<Uuid> subnetList = new ArrayList<>();
346 Map<Long, String> vpnIdRdMap = new HashMap<>();
347 Set<String> listVpnName = new HashSet<>();
349 for (Interfaces interfaces : srcDpninterfacelist) {
350 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
351 LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
354 String intfName = interfaces.getInterfaceName();
355 VpnInterface vpnInterface =
356 vpnUtil.getConfiguredVpnInterface(intfName);
357 if (vpnInterface != null) {
358 listVpnName.addAll(VpnHelper
359 .getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
360 handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
361 tunnelAction, isTepDeletedOnDpn,
362 subnetList, TunnelEventProcessingMethod.POPULATESUBNETS,
367 * Iterate over the list of VpnInterface for destDPN and get the prefix .
368 * Create remote rule for each of those prefix on srcDPN.
370 for (Interfaces interfaces : destDpninterfacelist) {
371 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
372 LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
375 String intfName = interfaces.getInterfaceName();
376 VpnInterface vpnInterface =
377 vpnUtil.getConfiguredVpnInterface(intfName);
378 if (vpnInterface != null) {
379 handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
380 tunnelAction, isTepDeletedOnDpn,
381 subnetList, TunnelEventProcessingMethod.MANAGEREMOTEROUTES,
386 //Iterate over the VpnId-to-Rd map.
387 for (Map.Entry<Long, String> entry : vpnIdRdMap.entrySet()) {
388 Long vpnId = entry.getKey();
389 rd = entry.getValue();
390 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
391 && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
392 fibManager.populateExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
393 } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
394 && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
395 fibManager.cleanUpExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
398 if (listVpnName.size() >= 1) {
399 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
400 for (Uuid subnetId : subnetList) {
401 // Populate the List of subnets
402 vpnSubnetRouteHandler.updateSubnetRouteOnTunnelUpEvent(subnetId, srcDpnId);
405 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
406 for (Uuid subnetId : subnetList) {
407 // Populate the List of subnets
408 vpnSubnetRouteHandler.updateSubnetRouteOnTunnelDownEvent(subnetId, srcDpnId);
412 } catch (RuntimeException e) {
413 LOG.error("handleTunnelEventForDpn: Unable to handle the tunnel event for srcDpnId {} srcTepIp {}"
414 + " remoteDpnId {} destTepIp {}", srcDpnId, srcTepIp, remoteDpnId, destTepIp, e);
418 // TODO Clean up the exception handling
419 @SuppressWarnings("checkstyle:IllegalCatch")
420 private void handleTunnelEventForDPNVpn(StateTunnelList stateTunnelList,
421 Map<Long, String> vpnIdRdMap, TunnelAction tunnelAction,
422 boolean isTepDeletedOnDpn, List<Uuid> subnetList,
423 TunnelEventProcessingMethod method,
424 VpnInterface cfgVpnInterface) {
426 String intfName = cfgVpnInterface.getName();
427 final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
428 String destTepIp = stateTunnelList.getDstInfo().getTepIp().stringValue();
429 String srcTepIp = stateTunnelList.getSrcInfo().getTepIp().stringValue();
430 int tunTypeVal = getTunnelType(stateTunnelList);
431 BigInteger remoteDpnId = null;
432 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
433 remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
435 if (cfgVpnInterface.getVpnInstanceNames() == null) {
436 LOG.warn("handleTunnelEventForDpn: no vpnName found for interface {}", intfName);
440 for (VpnInstanceNames vpnInstance : cfgVpnInterface.getVpnInstanceNames()) {
441 String vpnName = vpnInstance.getVpnName();
442 if (method == TunnelEventProcessingMethod.POPULATESUBNETS) {
443 Optional<VpnInterfaceOpDataEntry> opVpnInterface = vpnUtil
444 .getVpnInterfaceOpDataEntry(intfName, vpnName);
445 if (opVpnInterface.isPresent()) {
446 VpnInterfaceOpDataEntry vpnInterface = opVpnInterface.get();
447 jobCoordinator.enqueueJob("VPNINTERFACE-" + intfName,
448 new UpdateVpnInterfaceOnTunnelEvent(tunnelAction,
453 // Populate the List of subnets
454 InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
455 InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
456 new PortOpDataEntryKey(intfName)).build();
457 Optional<PortOpDataEntry> optionalPortOp =
458 SingleTransactionDataBroker.syncReadOptional(dataBroker,
459 LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
460 if (optionalPortOp.isPresent()) {
461 List<Uuid> subnetIdList = optionalPortOp.get().getSubnetIds();
462 if (subnetIdList != null) {
463 for (Uuid subnetId : subnetIdList) {
464 if (!subnetList.contains(subnetId)) {
465 subnetList.add(subnetId);
470 //Populate the map for VpnId-to-Rd
471 long vpnId = vpnUtil.getVpnId(vpnName);
472 rd = vpnUtil.getVpnRd(vpnName);
473 vpnIdRdMap.put(vpnId, rd);
475 } else if (method == TunnelEventProcessingMethod.MANAGEREMOTEROUTES) {
476 Optional<VpnInterfaceOpDataEntry> opVpnInterface = vpnUtil.getVpnInterfaceOpDataEntry(intfName,
478 if (opVpnInterface.isPresent()) {
479 VpnInterfaceOpDataEntry vpnInterface = opVpnInterface.get();
480 AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
481 List<Adjacency> adjList =
482 adjacencies != null && adjacencies.getAdjacency() != null ? adjacencies.getAdjacency()
484 String prefix = null;
485 long vpnId = vpnUtil.getVpnId(vpnInterface.getVpnInstanceName());
486 if (vpnIdRdMap.containsKey(vpnId)) {
487 rd = vpnIdRdMap.get(vpnId);
488 LOG.info("handleTunnelEventForDPN: Remote DpnId {} VpnId {} rd {} VpnInterface {}"
489 + " srcTepIp {} destTepIp {}", remoteDpnId, vpnId, rd , vpnInterface, srcTepIp,
491 for (Adjacency adj : adjList) {
492 prefix = adj.getIpAddress();
493 long label = adj.getLabel();
494 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
495 && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
496 fibManager.manageRemoteRouteOnDPN(true, srcDpnId, vpnId, rd, prefix, destTepIp,
499 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
500 && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
501 fibManager.manageRemoteRouteOnDPN(false, srcDpnId, vpnId, rd, prefix, destTepIp,
509 } catch (ReadFailedException e) {
510 LOG.error("handleTunnelEventForDPN: Failed to read data store for interface {} srcDpn {} srcTep {} "
511 + "dstTep {}", intfName, srcDpnId, srcTepIp, destTepIp);
515 private class UpdateVpnInterfaceOnTunnelEvent implements Callable {
516 private final VpnInterfaceOpDataEntry vpnInterface;
517 private final StateTunnelList stateTunnelList;
518 private final TunnelAction tunnelAction;
519 private final boolean isTepDeletedOnDpn;
521 UpdateVpnInterfaceOnTunnelEvent(TunnelAction tunnelAction,
522 VpnInterfaceOpDataEntry vpnInterface,
523 StateTunnelList stateTunnelList,
524 boolean isTepDeletedOnDpn) {
525 this.stateTunnelList = stateTunnelList;
526 this.vpnInterface = vpnInterface;
527 this.tunnelAction = tunnelAction;
528 this.isTepDeletedOnDpn = isTepDeletedOnDpn;
532 public List<ListenableFuture<Void>> call() {
533 List<ListenableFuture<Void>> futures = new ArrayList<>(2);
534 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx ->
535 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx -> {
536 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
537 vpnInterfaceManager.updateVpnInterfaceOnTepAdd(vpnInterface, stateTunnelList, confTx, operTx);
540 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
541 vpnInterfaceManager.updateVpnInterfaceOnTepDelete(vpnInterface, stateTunnelList, confTx,
549 private int getTunnelType(StateTunnelList stateTunnelList) {
551 if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
552 tunTypeVal = VpnConstants.ITMTunnelLocType.Internal.getValue();
553 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
554 tunTypeVal = VpnConstants.ITMTunnelLocType.External.getValue();
555 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class) {
556 tunTypeVal = VpnConstants.ITMTunnelLocType.Hwvtep.getValue();
558 tunTypeVal = VpnConstants.ITMTunnelLocType.Invalid.getValue();
563 private boolean isGreTunnel(StateTunnelList del) {
564 return del.getTransportType() == TunnelTypeMplsOverGre.class;
567 private void programDcGwLoadBalancingGroup(StateTunnelList tunnelState, int addOrRemove) {
568 IpAddress dcGwIp = tunnelState.getDstInfo().getTepIp();
569 String dcGwIpAddress = dcGwIp.stringValue();
570 List<String> availableDcGws = getDcGwIps();
571 BigInteger dpId = new BigInteger(tunnelState.getSrcInfo().getTepDeviceId());
572 boolean isTunnelUp = TunnelOperStatus.Up == tunnelState.getOperState();
573 fibManager.programDcGwLoadBalancingGroup(availableDcGws, dpId, dcGwIpAddress, addOrRemove, isTunnelUp,
574 tunnelState.getTransportType());
577 private List<String> getDcGwIps() {
578 InstanceIdentifier<DcGatewayIpList> dcGatewayIpListid =
579 InstanceIdentifier.builder(DcGatewayIpList.class).build();
580 DcGatewayIpList dcGatewayIpListConfig =
581 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, dcGatewayIpListid).orNull();
582 if (dcGatewayIpListConfig == null) {
585 return dcGatewayIpListConfig.getDcGatewayIp()
587 .filter(dcGwIp -> dcGwIp.getTunnnelType().equals(TunnelTypeMplsOverGre.class))
588 .map(dcGwIp -> dcGwIp.getIpAddress().stringValue()).sorted()
592 private boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
593 String ifaceName = stateTunnelList.getTunnelInterfaceName();
594 if (getTunnelType(stateTunnelList) == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
595 Interface configIface = InterfaceUtils.getInterface(dataBroker, stateTunnelList.getTunnelInterfaceName());
596 IfTunnel ifTunnel = configIface != null ? configIface.augmentation(IfTunnel.class) : null;
597 if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
598 ParentRefs refs = configIface.augmentation(ParentRefs.class);
599 if (refs != null && !Strings.isNullOrEmpty(refs.getParentInterface())) {
600 return true; //multiple VxLAN tunnels enabled, i.e. only logical tunnel should be treated
604 LOG.trace("isTunnelInLogicalGroup: MULTIPLE_VxLAN_TUNNELS: ignoring the tunnel event for {}", ifaceName);