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 org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
14 import com.google.common.base.Optional;
15 import com.google.common.base.Strings;
16 import com.google.common.util.concurrent.ListenableFuture;
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.List;
23 import java.util.Objects;
25 import java.util.concurrent.Callable;
26 import java.util.concurrent.Future;
27 import java.util.concurrent.locks.ReentrantLock;
28 import javax.annotation.PostConstruct;
29 import javax.inject.Inject;
30 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.NwConstants;
40 import org.opendaylight.genius.utils.JvmGlobalLocks;
41 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
42 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
43 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
44 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
45 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
46 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
47 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpnInterfaceListInputBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpnInterfaceListOutput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.get.dpn._interface.list.output.Interfaces;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.extraroute.rds.map.extraroute.rds.DestPrefixes;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpData;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
76 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
77 import org.opendaylight.yangtools.yang.common.RpcResult;
78 import org.opendaylight.yangtools.yang.common.Uint32;
79 import org.opendaylight.yangtools.yang.common.Uint64;
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.MOD_FLOW, false);
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 boolean isTunnelUp = TunnelOperStatus.Up == update.getOperState();
177 if (isGreTunnel(update)) {
178 programDcGwLoadBalancingGroup(update, NwConstants.MOD_FLOW, isTunnelUp);
181 //Remove the corresponding nexthop from the routepath under extraroute in fibentries.
182 Uint64 srcDpnId = Uint64.valueOf(update.getSrcInfo().getTepDeviceId()).intern();
183 String srcTepIp = update.getSrcInfo().getTepIp().stringValue();
184 List<VpnInstanceOpDataEntry> vpnInstanceOpData = vpnUtil.getAllVpnInstanceOpData();
185 if (vpnInstanceOpData == null) {
186 LOG.trace("update: No vpnInstanceOpdata present");
189 vpnInstanceOpData.stream()
190 .filter(opData -> opData.getVpnToDpnList() != null
191 && opData.getVpnToDpnList().stream().anyMatch(
192 vpnToDpn -> Objects.equals(vpnToDpn.getDpnId(), srcDpnId)))
194 List<DestPrefixes> prefixes = VpnExtraRouteHelper.getExtraRouteDestPrefixes(dataBroker,
196 prefixes.forEach(destPrefix -> {
197 VrfEntry vrfEntry = vpnUtil.getVrfEntry(opData.getVrfId(),
198 destPrefix.getDestPrefix());
199 if (vrfEntry == null || vrfEntry.getRoutePaths() == null) {
202 List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
203 routePaths.forEach(routePath -> {
204 if (Objects.equals(routePath.getNexthopAddress(), srcTepIp)) {
205 String prefix = destPrefix.getDestPrefix();
206 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(opData.getVpnInstanceName(),
208 // FIXME: separate out to somehow?
209 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnPrefixKey);
212 fibManager.refreshVrfEntry(opData.getVrfId(), prefix);
223 protected void add(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList add) {
224 LOG.trace("add: Tunnel addition---- {}", add);
225 TunnelOperStatus tunOpStatus = add.getOperState();
226 if (tunOpStatus != TunnelOperStatus.Down && tunOpStatus != TunnelOperStatus.Up) {
227 LOG.info("add: Returning from unsupported tunnelOperStatus {} for tunnel interface {}", tunOpStatus,
228 add.getTunnelInterfaceName());
231 if (tunOpStatus != TunnelOperStatus.Up) {
232 LOG.error("add: Tunnel {} is not yet UP.", add.getTunnelInterfaceName());
234 boolean isTunnelUp = TunnelOperStatus.Up == add.getOperState();
235 if (isGreTunnel(add)) {
236 programDcGwLoadBalancingGroup(add, NwConstants.ADD_FLOW, isTunnelUp);
238 LOG.info("add: ITM Tunnel ,type {} ,added between src: {} and dest: {}",
239 fibManager.getTransportTypeStr(add.getTransportType().toString()),
240 add.getSrcInfo().getTepDeviceId(), add.getDstInfo().getTepDeviceId());
241 handleTunnelEventForDPN(add, TunnelAction.TUNNEL_EP_ADD);
244 public enum TunnelEventProcessingMethod {
245 POPULATESUBNETS(0), MANAGEREMOTEROUTES(1);
247 private final int method;
249 TunnelEventProcessingMethod(int id) {
253 public int getValue() {
258 // TODO Clean up the exception handling
259 @SuppressWarnings("checkstyle:IllegalCatch")
260 private void handleTunnelEventForDPN(StateTunnelList stateTunnelList, TunnelAction tunnelAction) {
261 final Uint64 srcDpnId = Uint64.valueOf(stateTunnelList.getSrcInfo().getTepDeviceId()).intern();
262 final String srcTepIp = stateTunnelList.getSrcInfo().getTepIp().stringValue();
263 String destTepIp = stateTunnelList.getDstInfo().getTepIp().stringValue();
265 Uint64 remoteDpnId = null;
266 boolean isTepDeletedOnDpn = false;
268 LOG.info("handleTunnelEventForDPN: Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ",
269 srcDpnId, srcTepIp, destTepIp);
270 int tunTypeVal = getTunnelType(stateTunnelList);
271 LOG.trace("handleTunnelEventForDPN: tunTypeVal is {}", tunTypeVal);
273 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
274 LOG.info("handleTunnelEventForDPN: Tunnel ADD event received for Dpn {} VTEP Ip {} destTepIp {}",
275 srcDpnId, srcTepIp, destTepIp);
276 if (isTunnelInLogicalGroup(stateTunnelList)) {
279 } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE) {
280 LOG.info("handleTunnelEventForDPN: Tunnel DELETE event received for Dpn {} VTEP Ip {} DestTepIp {}",
281 srcDpnId, srcTepIp, destTepIp);
282 // When tunnel EP is deleted on a DPN , VPN gets two deletion event.
283 // One for a DPN on which tunnel EP was deleted and another for other-end DPN.
284 // Update the adj for the vpninterfaces for a DPN on which TEP is deleted.
285 // Update the adj & VRF for the vpninterfaces for a DPN on which TEP is deleted.
286 // Dont update the adj & VRF for vpninterfaces for a DPN on which TEP is not deleted.
287 String endpointIpForDPN;
289 endpointIpForDPN = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
290 } catch (Exception e) {
291 LOG.error("handleTunnelEventForDPN: Unable to resolve endpoint IP for srcDpn {}", srcDpnId);
292 /* this dpn does not have the VTEP */
293 endpointIpForDPN = null;
296 if (endpointIpForDPN == null) {
297 LOG.info("handleTunnelEventForDPN: Tunnel TEP is deleted on Dpn {} VTEP Ip {} destTepIp {}",
298 srcDpnId, srcTepIp, destTepIp);
299 isTepDeletedOnDpn = true;
303 // Get the list of VpnInterfaces from Intf Mgr for a SrcDPN on which TEP is added/deleted
304 Future<RpcResult<GetDpnInterfaceListOutput>> result;
305 List<Interfaces> srcDpninterfacelist = new ArrayList<>();
306 List<Interfaces> destDpninterfacelist = new ArrayList<>();
308 result = intfRpcService.getDpnInterfaceList(
309 new GetDpnInterfaceListInputBuilder().setDpid(srcDpnId).build());
310 RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
311 if (!rpcResult.isSuccessful()) {
312 LOG.error("handleTunnelEventForDPN: RPC Call to GetDpnInterfaceList for srcDpnid {} srcTepIp {}"
313 + " destTepIP {} returned with Errors {}", srcDpnId, srcTepIp, destTepIp,
314 rpcResult.getErrors());
316 srcDpninterfacelist = rpcResult.getResult().nonnullInterfaces();
318 } catch (Exception e) {
319 LOG.error("handleTunnelEventForDPN: Exception when querying for GetDpnInterfaceList for srcDpnid {}"
320 + " srcTepIp {} destTepIp {}", srcDpnId, srcTepIp, destTepIp, e);
322 // Get the list of VpnInterfaces from Intf Mgr for a destDPN only for internal tunnel.
323 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
324 remoteDpnId = Uint64.valueOf(stateTunnelList.getDstInfo().getTepDeviceId()).intern();
326 result = intfRpcService.getDpnInterfaceList(
327 new GetDpnInterfaceListInputBuilder().setDpid(remoteDpnId).build());
328 RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
329 if (!rpcResult.isSuccessful()) {
330 LOG.error("handleTunnelEventForDPN: RPC Call to GetDpnInterfaceList for remoteDpnid {}"
331 + " srcTepIP {} destTepIp {} returned with Errors {}", remoteDpnId, srcTepIp,
332 destTepIp, rpcResult.getErrors());
334 destDpninterfacelist = rpcResult.getResult().nonnullInterfaces();
336 } catch (Exception e) {
337 LOG.error("handleTunnelEventForDPN: Exception when querying for GetDpnInterfaceList"
338 + " for remoteDpnid {} srcTepIp {} destTepIp {}", remoteDpnId,
339 srcTepIp, destTepIp, e);
344 * Iterate over the list of VpnInterface for a SrcDpn on which TEP is added or deleted and read the adj.
345 * Update the adjacencies with the updated nexthop.
347 List<Uuid> subnetList = new ArrayList<>();
348 Map<Uint32, String> vpnIdRdMap = new HashMap<>();
349 Set<String> listVpnName = new HashSet<>();
351 for (Interfaces interfaces : srcDpninterfacelist) {
352 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
353 LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
356 String intfName = interfaces.getInterfaceName();
357 VpnInterface vpnInterface =
358 vpnUtil.getConfiguredVpnInterface(intfName);
359 if (vpnInterface != null) {
360 listVpnName.addAll(VpnHelper
361 .getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
362 handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
363 tunnelAction, isTepDeletedOnDpn,
364 subnetList, TunnelEventProcessingMethod.POPULATESUBNETS,
369 * Iterate over the list of VpnInterface for destDPN and get the prefix .
370 * Create remote rule for each of those prefix on srcDPN.
372 for (Interfaces interfaces : destDpninterfacelist) {
373 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
374 LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
377 String intfName = interfaces.getInterfaceName();
378 VpnInterface vpnInterface =
379 vpnUtil.getConfiguredVpnInterface(intfName);
380 if (vpnInterface != null) {
381 handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
382 tunnelAction, isTepDeletedOnDpn,
383 subnetList, TunnelEventProcessingMethod.MANAGEREMOTEROUTES,
388 //Iterate over the VpnId-to-Rd map.
389 for (Map.Entry<Uint32, String> entry : vpnIdRdMap.entrySet()) {
390 Uint32 vpnId = entry.getKey();
391 rd = entry.getValue();
392 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
393 && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
394 fibManager.populateExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
395 } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
396 && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
397 fibManager.cleanUpExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
400 if (listVpnName.size() >= 1) {
401 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
402 for (Uuid subnetId : subnetList) {
403 // Populate the List of subnets
404 vpnSubnetRouteHandler.updateSubnetRouteOnTunnelUpEvent(subnetId, srcDpnId);
407 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
408 for (Uuid subnetId : subnetList) {
409 // Populate the List of subnets
410 vpnSubnetRouteHandler.updateSubnetRouteOnTunnelDownEvent(subnetId, srcDpnId);
414 } catch (RuntimeException e) {
415 LOG.error("handleTunnelEventForDpn: Unable to handle the tunnel event for srcDpnId {} srcTepIp {}"
416 + " remoteDpnId {} destTepIp {}", srcDpnId, srcTepIp, remoteDpnId, destTepIp, e);
420 // TODO Clean up the exception handling
421 @SuppressWarnings("checkstyle:IllegalCatch")
422 private void handleTunnelEventForDPNVpn(StateTunnelList stateTunnelList,
423 Map<Uint32, String> vpnIdRdMap, TunnelAction tunnelAction,
424 boolean isTepDeletedOnDpn, List<Uuid> subnetList,
425 TunnelEventProcessingMethod method,
426 VpnInterface cfgVpnInterface) {
428 String intfName = cfgVpnInterface.getName();
429 final Uint64 srcDpnId = Uint64.valueOf(stateTunnelList.getSrcInfo().getTepDeviceId()).intern();
430 String destTepIp = stateTunnelList.getDstInfo().getTepIp().stringValue();
431 String srcTepIp = stateTunnelList.getSrcInfo().getTepIp().stringValue();
432 int tunTypeVal = getTunnelType(stateTunnelList);
433 Uint64 remoteDpnId = null;
434 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
435 remoteDpnId = Uint64.valueOf(stateTunnelList.getDstInfo().getTepDeviceId()).intern();
437 if (cfgVpnInterface.getVpnInstanceNames() == null) {
438 LOG.warn("handleTunnelEventForDpn: no vpnName found for interface {}", intfName);
442 for (VpnInstanceNames vpnInstance : cfgVpnInterface.getVpnInstanceNames()) {
443 String vpnName = vpnInstance.getVpnName();
444 if (method == TunnelEventProcessingMethod.POPULATESUBNETS) {
445 Optional<VpnInterfaceOpDataEntry> opVpnInterface = vpnUtil
446 .getVpnInterfaceOpDataEntry(intfName, vpnName);
447 if (opVpnInterface.isPresent()) {
448 VpnInterfaceOpDataEntry vpnInterface = opVpnInterface.get();
449 jobCoordinator.enqueueJob("VPNINTERFACE-" + intfName,
450 new UpdateVpnInterfaceOnTunnelEvent(tunnelAction,
455 // Populate the List of subnets
456 InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
457 InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
458 new PortOpDataEntryKey(intfName)).build();
459 Optional<PortOpDataEntry> optionalPortOp =
460 SingleTransactionDataBroker.syncReadOptional(dataBroker,
461 LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
462 if (optionalPortOp.isPresent()) {
463 List<Uuid> subnetIdList = optionalPortOp.get().getSubnetIds();
464 if (subnetIdList != null) {
465 for (Uuid subnetId : subnetIdList) {
466 if (!subnetList.contains(subnetId)) {
467 subnetList.add(subnetId);
472 //Populate the map for VpnId-to-Rd
473 Uint32 vpnId = vpnUtil.getVpnId(vpnName);
474 rd = vpnUtil.getVpnRd(vpnName);
475 vpnIdRdMap.put(vpnId, rd);
477 } else if (method == TunnelEventProcessingMethod.MANAGEREMOTEROUTES) {
478 Optional<VpnInterfaceOpDataEntry> opVpnInterface = vpnUtil.getVpnInterfaceOpDataEntry(intfName,
480 if (opVpnInterface.isPresent()) {
481 VpnInterfaceOpDataEntry vpnInterface = opVpnInterface.get();
482 AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
483 List<Adjacency> adjList =
484 adjacencies != null && adjacencies.getAdjacency() != null ? adjacencies.getAdjacency()
486 String prefix = null;
487 Uint32 vpnId = vpnUtil.getVpnId(vpnInterface.getVpnInstanceName());
488 if (vpnIdRdMap.containsKey(vpnId)) {
489 rd = vpnIdRdMap.get(vpnId);
490 LOG.info("handleTunnelEventForDPN: Remote DpnId {} VpnId {} rd {} VpnInterface {}"
491 + " srcTepIp {} destTepIp {}", remoteDpnId, vpnId, rd , vpnInterface, srcTepIp,
493 for (Adjacency adj : adjList) {
494 prefix = adj.getIpAddress();
495 Uint32 label = adj.getLabel();
496 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
497 && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
498 fibManager.manageRemoteRouteOnDPN(true, srcDpnId, vpnId, rd, prefix, destTepIp,
501 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
502 && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
503 fibManager.manageRemoteRouteOnDPN(false, srcDpnId, vpnId, rd, prefix, destTepIp,
511 } catch (ReadFailedException e) {
512 LOG.error("handleTunnelEventForDPN: Failed to read data store for interface {} srcDpn {} srcTep {} "
513 + "dstTep {}", intfName, srcDpnId, srcTepIp, destTepIp);
517 private class UpdateVpnInterfaceOnTunnelEvent implements Callable {
518 private final VpnInterfaceOpDataEntry vpnInterface;
519 private final StateTunnelList stateTunnelList;
520 private final TunnelAction tunnelAction;
521 private final boolean isTepDeletedOnDpn;
523 UpdateVpnInterfaceOnTunnelEvent(TunnelAction tunnelAction,
524 VpnInterfaceOpDataEntry vpnInterface,
525 StateTunnelList stateTunnelList,
526 boolean isTepDeletedOnDpn) {
527 this.stateTunnelList = stateTunnelList;
528 this.vpnInterface = vpnInterface;
529 this.tunnelAction = tunnelAction;
530 this.isTepDeletedOnDpn = isTepDeletedOnDpn;
534 public List<ListenableFuture<Void>> call() {
535 List<ListenableFuture<Void>> futures = new ArrayList<>(2);
536 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx ->
537 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx -> {
538 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
539 vpnInterfaceManager.updateVpnInterfaceOnTepAdd(vpnInterface, stateTunnelList, confTx, operTx);
542 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
543 vpnInterfaceManager.updateVpnInterfaceOnTepDelete(vpnInterface, stateTunnelList, confTx,
551 private int getTunnelType(StateTunnelList stateTunnelList) {
553 if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
554 tunTypeVal = VpnConstants.ITMTunnelLocType.Internal.getValue();
555 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
556 tunTypeVal = VpnConstants.ITMTunnelLocType.External.getValue();
557 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class) {
558 tunTypeVal = VpnConstants.ITMTunnelLocType.Hwvtep.getValue();
560 tunTypeVal = VpnConstants.ITMTunnelLocType.Invalid.getValue();
565 private boolean isGreTunnel(StateTunnelList del) {
566 return del.getTransportType() == TunnelTypeMplsOverGre.class;
569 private void programDcGwLoadBalancingGroup(StateTunnelList tunnelState, int addOrRemove, boolean isTunnelUp) {
570 IpAddress dcGwIp = tunnelState.getDstInfo().getTepIp();
571 String dcGwIpAddress = String.valueOf(dcGwIp.stringValue());
572 Uint64 dpId = Uint64.valueOf(tunnelState.getSrcInfo().getTepDeviceId()).intern();
573 fibManager.programDcGwLoadBalancingGroup(dpId, dcGwIpAddress, addOrRemove, isTunnelUp,
574 tunnelState.getTransportType());
577 private boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
578 String ifaceName = stateTunnelList.getTunnelInterfaceName();
579 if (getTunnelType(stateTunnelList) == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
580 Interface configIface = InterfaceUtils.getInterface(dataBroker, stateTunnelList.getTunnelInterfaceName());
581 IfTunnel ifTunnel = configIface != null ? configIface.augmentation(IfTunnel.class) : null;
582 if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
583 ParentRefs refs = configIface.augmentation(ParentRefs.class);
584 if (refs != null && !Strings.isNullOrEmpty(refs.getParentInterface())) {
585 return true; //multiple VxLAN tunnels enabled, i.e. only logical tunnel should be treated
589 LOG.trace("isTunnelInLogicalGroup: MULTIPLE_VxLAN_TUNNELS: ignoring the tunnel event for {}", ifaceName);