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.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;
33 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
34 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
35 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
36 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
37 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
38 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
39 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
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.netvirt.fibmanager.rev150330.extraroute.rds.map.extraroute.rds.DestPrefixes;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpData;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
77 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
78 import org.opendaylight.yangtools.yang.common.RpcResult;
79 import org.slf4j.Logger;
80 import org.slf4j.LoggerFactory;
83 public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBase<StateTunnelList,
84 TunnelInterfaceStateListener> {
86 private static final Logger LOG = LoggerFactory.getLogger(TunnelInterfaceStateListener.class);
88 private final DataBroker dataBroker;
89 private final ManagedNewTransactionRunner txRunner;
90 private final IFibManager fibManager;
91 private final OdlInterfaceRpcService intfRpcService;
92 private final VpnInterfaceManager vpnInterfaceManager;
93 private final VpnSubnetRouteHandler vpnSubnetRouteHandler;
94 private final JobCoordinator jobCoordinator;
95 private final VpnUtil vpnUtil;
97 protected enum UpdateRouteAction {
98 ADVERTISE_ROUTE, WITHDRAW_ROUTE
101 protected enum TunnelAction {
108 * Responsible for listening to tunnel interface state change.
109 * @param dataBroker Data Broker
110 * @param fibManager FIB APIs
111 * @param ifaceMgrRpcService Interface Manager RPC
112 * @param vpnInterfaceManager Vpn Interface APIs
113 * @param vpnSubnetRouteHandler Subnet-Route APIs
114 * @param jobCoordinator Key based job serialization mechanism
115 * @param vpnUtil Vpn Utility
118 public TunnelInterfaceStateListener(final DataBroker dataBroker,
119 final IFibManager fibManager,
120 final OdlInterfaceRpcService ifaceMgrRpcService,
121 final VpnInterfaceManager vpnInterfaceManager,
122 final VpnSubnetRouteHandler vpnSubnetRouteHandler,
123 final JobCoordinator jobCoordinator,
125 super(StateTunnelList.class, TunnelInterfaceStateListener.class);
126 this.dataBroker = dataBroker;
127 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
128 this.fibManager = fibManager;
129 this.intfRpcService = ifaceMgrRpcService;
130 this.vpnInterfaceManager = vpnInterfaceManager;
131 this.vpnSubnetRouteHandler = vpnSubnetRouteHandler;
132 this.jobCoordinator = jobCoordinator;
133 this.vpnUtil = vpnUtil;
137 public void start() {
138 LOG.info("{} start", getClass().getSimpleName());
139 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
143 protected InstanceIdentifier<StateTunnelList> getWildCardPath() {
144 return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
148 protected TunnelInterfaceStateListener getDataTreeChangeListener() {
149 return TunnelInterfaceStateListener.this;
153 protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
154 LOG.trace("remove: Tunnel deletion---- {}", del);
155 if (isGreTunnel(del)) {
156 programDcGwLoadBalancingGroup(del, NwConstants.MOD_FLOW, false);
158 handleTunnelEventForDPN(del, TunnelAction.TUNNEL_EP_DELETE);
162 protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original,
163 StateTunnelList update) {
164 LOG.trace("update: Tunnel updation---- {}", update);
165 LOG.info("update: ITM Tunnel {} of type {} state event changed from :{} to :{}",
166 update.getTunnelInterfaceName(),
167 fibManager.getTransportTypeStr(update.getTransportType().toString()),
168 original.getOperState(), update.getOperState());
169 TunnelOperStatus tunOpStatus = update.getOperState();
170 if (tunOpStatus != TunnelOperStatus.Down && tunOpStatus != TunnelOperStatus.Up) {
171 LOG.info("update: Returning from unsupported tunnelOperStatus {} for tunnel interface {}", tunOpStatus,
172 update.getTunnelInterfaceName());
175 boolean isTunnelUp = TunnelOperStatus.Up == update.getOperState();
176 if (isGreTunnel(update)) {
177 programDcGwLoadBalancingGroup(update, NwConstants.MOD_FLOW, isTunnelUp);
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 boolean isTunnelUp = TunnelOperStatus.Up == add.getOperState();
234 if (isGreTunnel(add)) {
235 programDcGwLoadBalancingGroup(add, NwConstants.ADD_FLOW, isTunnelUp);
237 LOG.info("add: ITM Tunnel ,type {} ,added between src: {} and dest: {}",
238 fibManager.getTransportTypeStr(add.getTransportType().toString()),
239 add.getSrcInfo().getTepDeviceId(), add.getDstInfo().getTepDeviceId());
240 handleTunnelEventForDPN(add, TunnelAction.TUNNEL_EP_ADD);
243 public enum TunnelEventProcessingMethod {
244 POPULATESUBNETS(0), MANAGEREMOTEROUTES(1);
246 private final int method;
248 TunnelEventProcessingMethod(int id) {
252 public int getValue() {
257 // TODO Clean up the exception handling
258 @SuppressWarnings("checkstyle:IllegalCatch")
259 private void handleTunnelEventForDPN(StateTunnelList stateTunnelList, TunnelAction tunnelAction) {
260 final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
261 final String srcTepIp = stateTunnelList.getSrcInfo().getTepIp().stringValue();
262 String destTepIp = stateTunnelList.getDstInfo().getTepIp().stringValue();
264 BigInteger remoteDpnId = null;
265 boolean isTepDeletedOnDpn = false;
267 LOG.info("handleTunnelEventForDPN: Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ",
268 srcDpnId, srcTepIp, destTepIp);
269 int tunTypeVal = getTunnelType(stateTunnelList);
270 LOG.trace("handleTunnelEventForDPN: tunTypeVal is {}", tunTypeVal);
272 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
273 LOG.info("handleTunnelEventForDPN: Tunnel ADD event received for Dpn {} VTEP Ip {} destTepIp {}",
274 srcDpnId, srcTepIp, destTepIp);
275 if (isTunnelInLogicalGroup(stateTunnelList)) {
278 } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE) {
279 LOG.info("handleTunnelEventForDPN: Tunnel DELETE event received for Dpn {} VTEP Ip {} DestTepIp {}",
280 srcDpnId, srcTepIp, destTepIp);
281 // When tunnel EP is deleted on a DPN , VPN gets two deletion event.
282 // One for a DPN on which tunnel EP was deleted and another for other-end DPN.
283 // Update the adj for the vpninterfaces for a DPN on which TEP is deleted.
284 // Update the adj & VRF for the vpninterfaces for a DPN on which TEP is deleted.
285 // Dont update the adj & VRF for vpninterfaces for a DPN on which TEP is not deleted.
286 String endpointIpForDPN;
288 endpointIpForDPN = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
289 } catch (Exception e) {
290 LOG.error("handleTunnelEventForDPN: Unable to resolve endpoint IP for srcDpn {}", srcDpnId);
291 /* this dpn does not have the VTEP */
292 endpointIpForDPN = null;
295 if (endpointIpForDPN == null) {
296 LOG.info("handleTunnelEventForDPN: Tunnel TEP is deleted on Dpn {} VTEP Ip {} destTepIp {}",
297 srcDpnId, srcTepIp, destTepIp);
298 isTepDeletedOnDpn = true;
302 // Get the list of VpnInterfaces from Intf Mgr for a SrcDPN on which TEP is added/deleted
303 Future<RpcResult<GetDpnInterfaceListOutput>> result;
304 List<Interfaces> srcDpninterfacelist = new ArrayList<>();
305 List<Interfaces> destDpninterfacelist = new ArrayList<>();
307 result = intfRpcService.getDpnInterfaceList(
308 new GetDpnInterfaceListInputBuilder().setDpid(srcDpnId).build());
309 RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
310 if (!rpcResult.isSuccessful()) {
311 LOG.error("handleTunnelEventForDPN: RPC Call to GetDpnInterfaceList for srcDpnid {} srcTepIp {}"
312 + " destTepIP {} returned with Errors {}", srcDpnId, srcTepIp, destTepIp,
313 rpcResult.getErrors());
315 srcDpninterfacelist = rpcResult.getResult().nonnullInterfaces();
317 } catch (Exception e) {
318 LOG.error("handleTunnelEventForDPN: Exception when querying for GetDpnInterfaceList for srcDpnid {}"
319 + " srcTepIp {} destTepIp {}", srcDpnId, srcTepIp, destTepIp, e);
321 // Get the list of VpnInterfaces from Intf Mgr for a destDPN only for internal tunnel.
322 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
323 remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
325 result = intfRpcService.getDpnInterfaceList(
326 new GetDpnInterfaceListInputBuilder().setDpid(remoteDpnId).build());
327 RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
328 if (!rpcResult.isSuccessful()) {
329 LOG.error("handleTunnelEventForDPN: RPC Call to GetDpnInterfaceList for remoteDpnid {}"
330 + " srcTepIP {} destTepIp {} returned with Errors {}", remoteDpnId, srcTepIp,
331 destTepIp, rpcResult.getErrors());
333 destDpninterfacelist = rpcResult.getResult().nonnullInterfaces();
335 } catch (Exception e) {
336 LOG.error("handleTunnelEventForDPN: Exception when querying for GetDpnInterfaceList"
337 + " for remoteDpnid {} srcTepIp {} destTepIp {}", remoteDpnId,
338 srcTepIp, destTepIp, e);
343 * Iterate over the list of VpnInterface for a SrcDpn on which TEP is added or deleted and read the adj.
344 * Update the adjacencies with the updated nexthop.
346 List<Uuid> subnetList = new ArrayList<>();
347 Map<Long, String> vpnIdRdMap = new HashMap<>();
348 Set<String> listVpnName = new HashSet<>();
350 for (Interfaces interfaces : srcDpninterfacelist) {
351 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
352 LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
355 String intfName = interfaces.getInterfaceName();
356 VpnInterface vpnInterface =
357 vpnUtil.getConfiguredVpnInterface(intfName);
358 if (vpnInterface != null) {
359 listVpnName.addAll(VpnHelper
360 .getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
361 handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
362 tunnelAction, isTepDeletedOnDpn,
363 subnetList, TunnelEventProcessingMethod.POPULATESUBNETS,
368 * Iterate over the list of VpnInterface for destDPN and get the prefix .
369 * Create remote rule for each of those prefix on srcDPN.
371 for (Interfaces interfaces : destDpninterfacelist) {
372 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
373 LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
376 String intfName = interfaces.getInterfaceName();
377 VpnInterface vpnInterface =
378 vpnUtil.getConfiguredVpnInterface(intfName);
379 if (vpnInterface != null) {
380 handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
381 tunnelAction, isTepDeletedOnDpn,
382 subnetList, TunnelEventProcessingMethod.MANAGEREMOTEROUTES,
387 //Iterate over the VpnId-to-Rd map.
388 for (Map.Entry<Long, String> entry : vpnIdRdMap.entrySet()) {
389 Long vpnId = entry.getKey();
390 rd = entry.getValue();
391 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
392 && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
393 fibManager.populateExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
394 } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
395 && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
396 fibManager.cleanUpExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
399 if (listVpnName.size() >= 1) {
400 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
401 for (Uuid subnetId : subnetList) {
402 // Populate the List of subnets
403 vpnSubnetRouteHandler.updateSubnetRouteOnTunnelUpEvent(subnetId, srcDpnId);
406 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
407 for (Uuid subnetId : subnetList) {
408 // Populate the List of subnets
409 vpnSubnetRouteHandler.updateSubnetRouteOnTunnelDownEvent(subnetId, srcDpnId);
413 } catch (RuntimeException e) {
414 LOG.error("handleTunnelEventForDpn: Unable to handle the tunnel event for srcDpnId {} srcTepIp {}"
415 + " remoteDpnId {} destTepIp {}", srcDpnId, srcTepIp, remoteDpnId, destTepIp, e);
419 // TODO Clean up the exception handling
420 @SuppressWarnings("checkstyle:IllegalCatch")
421 private void handleTunnelEventForDPNVpn(StateTunnelList stateTunnelList,
422 Map<Long, String> vpnIdRdMap, TunnelAction tunnelAction,
423 boolean isTepDeletedOnDpn, List<Uuid> subnetList,
424 TunnelEventProcessingMethod method,
425 VpnInterface cfgVpnInterface) {
427 String intfName = cfgVpnInterface.getName();
428 final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
429 String destTepIp = stateTunnelList.getDstInfo().getTepIp().stringValue();
430 String srcTepIp = stateTunnelList.getSrcInfo().getTepIp().stringValue();
431 int tunTypeVal = getTunnelType(stateTunnelList);
432 BigInteger remoteDpnId = null;
433 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
434 remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
436 if (cfgVpnInterface.getVpnInstanceNames() == null) {
437 LOG.warn("handleTunnelEventForDpn: no vpnName found for interface {}", intfName);
441 for (VpnInstanceNames vpnInstance : cfgVpnInterface.getVpnInstanceNames()) {
442 String vpnName = vpnInstance.getVpnName();
443 if (method == TunnelEventProcessingMethod.POPULATESUBNETS) {
444 Optional<VpnInterfaceOpDataEntry> opVpnInterface = vpnUtil
445 .getVpnInterfaceOpDataEntry(intfName, vpnName);
446 if (opVpnInterface.isPresent()) {
447 VpnInterfaceOpDataEntry vpnInterface = opVpnInterface.get();
448 jobCoordinator.enqueueJob("VPNINTERFACE-" + intfName,
449 new UpdateVpnInterfaceOnTunnelEvent(tunnelAction,
454 // Populate the List of subnets
455 InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
456 InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
457 new PortOpDataEntryKey(intfName)).build();
458 Optional<PortOpDataEntry> optionalPortOp =
459 SingleTransactionDataBroker.syncReadOptional(dataBroker,
460 LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
461 if (optionalPortOp.isPresent()) {
462 List<Uuid> subnetIdList = optionalPortOp.get().getSubnetIds();
463 if (subnetIdList != null) {
464 for (Uuid subnetId : subnetIdList) {
465 if (!subnetList.contains(subnetId)) {
466 subnetList.add(subnetId);
471 //Populate the map for VpnId-to-Rd
472 long vpnId = vpnUtil.getVpnId(vpnName);
473 rd = vpnUtil.getVpnRd(vpnName);
474 vpnIdRdMap.put(vpnId, rd);
476 } else if (method == TunnelEventProcessingMethod.MANAGEREMOTEROUTES) {
477 Optional<VpnInterfaceOpDataEntry> opVpnInterface = vpnUtil.getVpnInterfaceOpDataEntry(intfName,
479 if (opVpnInterface.isPresent()) {
480 VpnInterfaceOpDataEntry vpnInterface = opVpnInterface.get();
481 AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
482 List<Adjacency> adjList =
483 adjacencies != null && adjacencies.getAdjacency() != null ? adjacencies.getAdjacency()
485 String prefix = null;
486 long vpnId = vpnUtil.getVpnId(vpnInterface.getVpnInstanceName());
487 if (vpnIdRdMap.containsKey(vpnId)) {
488 rd = vpnIdRdMap.get(vpnId);
489 LOG.info("handleTunnelEventForDPN: Remote DpnId {} VpnId {} rd {} VpnInterface {}"
490 + " srcTepIp {} destTepIp {}", remoteDpnId, vpnId, rd , vpnInterface, srcTepIp,
492 for (Adjacency adj : adjList) {
493 prefix = adj.getIpAddress();
494 long label = adj.getLabel();
495 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
496 && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
497 fibManager.manageRemoteRouteOnDPN(true, srcDpnId, vpnId, rd, prefix, destTepIp,
500 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
501 && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
502 fibManager.manageRemoteRouteOnDPN(false, srcDpnId, vpnId, rd, prefix, destTepIp,
510 } catch (ReadFailedException e) {
511 LOG.error("handleTunnelEventForDPN: Failed to read data store for interface {} srcDpn {} srcTep {} "
512 + "dstTep {}", intfName, srcDpnId, srcTepIp, destTepIp);
516 private class UpdateVpnInterfaceOnTunnelEvent implements Callable {
517 private final VpnInterfaceOpDataEntry vpnInterface;
518 private final StateTunnelList stateTunnelList;
519 private final TunnelAction tunnelAction;
520 private final boolean isTepDeletedOnDpn;
522 UpdateVpnInterfaceOnTunnelEvent(TunnelAction tunnelAction,
523 VpnInterfaceOpDataEntry vpnInterface,
524 StateTunnelList stateTunnelList,
525 boolean isTepDeletedOnDpn) {
526 this.stateTunnelList = stateTunnelList;
527 this.vpnInterface = vpnInterface;
528 this.tunnelAction = tunnelAction;
529 this.isTepDeletedOnDpn = isTepDeletedOnDpn;
533 public List<ListenableFuture<Void>> call() {
534 List<ListenableFuture<Void>> futures = new ArrayList<>(2);
535 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx ->
536 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx -> {
537 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
538 vpnInterfaceManager.updateVpnInterfaceOnTepAdd(vpnInterface, stateTunnelList, confTx, operTx);
541 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
542 vpnInterfaceManager.updateVpnInterfaceOnTepDelete(vpnInterface, stateTunnelList, confTx,
550 private int getTunnelType(StateTunnelList stateTunnelList) {
552 if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
553 tunTypeVal = VpnConstants.ITMTunnelLocType.Internal.getValue();
554 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
555 tunTypeVal = VpnConstants.ITMTunnelLocType.External.getValue();
556 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class) {
557 tunTypeVal = VpnConstants.ITMTunnelLocType.Hwvtep.getValue();
559 tunTypeVal = VpnConstants.ITMTunnelLocType.Invalid.getValue();
564 private boolean isGreTunnel(StateTunnelList del) {
565 return del.getTransportType() == TunnelTypeMplsOverGre.class;
568 private void programDcGwLoadBalancingGroup(StateTunnelList tunnelState, int addOrRemove, boolean isTunnelUp) {
569 IpAddress dcGwIp = tunnelState.getDstInfo().getTepIp();
570 String dcGwIpAddress = String.valueOf(dcGwIp.stringValue());
571 BigInteger dpId = new BigInteger(tunnelState.getSrcInfo().getTepDeviceId());
572 fibManager.programDcGwLoadBalancingGroup(dpId, dcGwIpAddress, addOrRemove, isTunnelUp,
573 tunnelState.getTransportType());
576 private boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
577 String ifaceName = stateTunnelList.getTunnelInterfaceName();
578 if (getTunnelType(stateTunnelList) == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
579 Interface configIface = InterfaceUtils.getInterface(dataBroker, stateTunnelList.getTunnelInterfaceName());
580 IfTunnel ifTunnel = configIface != null ? configIface.augmentation(IfTunnel.class) : null;
581 if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
582 ParentRefs refs = configIface.augmentation(ParentRefs.class);
583 if (refs != null && !Strings.isNullOrEmpty(refs.getParentInterface())) {
584 return true; //multiple VxLAN tunnels enabled, i.e. only logical tunnel should be treated
588 LOG.trace("isTunnelInLogicalGroup: MULTIPLE_VxLAN_TUNNELS: ignoring the tunnel event for {}", ifaceName);