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.stream.Collectors.toList;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Strings;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.Iterator;
21 import java.util.List;
24 import java.util.concurrent.Callable;
25 import java.util.concurrent.Future;
26 import javax.annotation.PostConstruct;
27 import javax.inject.Inject;
28 import javax.inject.Singleton;
29 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
30 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
32 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
33 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
34 import org.opendaylight.genius.mdsalutil.MDSALUtil;
35 import org.opendaylight.genius.mdsalutil.NwConstants;
36 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
37 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
38 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
39 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
40 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
41 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
42 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
43 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpnInterfaceListInputBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpnInterfaceListOutput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.get.dpn._interface.list.output.Interfaces;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.extraroute.rds.map.extraroute.rds.DestPrefixes;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpData;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
73 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
74 import org.opendaylight.yangtools.yang.common.RpcResult;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
79 public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBase<StateTunnelList,
80 TunnelInterfaceStateListener> {
82 private static final Logger LOG = LoggerFactory.getLogger(TunnelInterfaceStateListener.class);
84 private final DataBroker dataBroker;
85 private final ManagedNewTransactionRunner txRunner;
86 private final IFibManager fibManager;
87 private final OdlInterfaceRpcService intfRpcService;
88 private final VpnInterfaceManager vpnInterfaceManager;
89 private final VpnSubnetRouteHandler vpnSubnetRouteHandler;
90 private final JobCoordinator jobCoordinator;
92 protected enum UpdateRouteAction {
93 ADVERTISE_ROUTE, WITHDRAW_ROUTE
96 protected enum TunnelAction {
103 * Responsible for listening to tunnel interface state change.
106 public TunnelInterfaceStateListener(final DataBroker dataBroker,
107 final IFibManager fibManager,
108 final OdlInterfaceRpcService ifaceMgrRpcService,
109 final VpnInterfaceManager vpnInterfaceManager,
110 final VpnSubnetRouteHandler vpnSubnetRouteHandler,
111 final JobCoordinator jobCoordinator) {
112 super(StateTunnelList.class, TunnelInterfaceStateListener.class);
113 this.dataBroker = dataBroker;
114 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
115 this.fibManager = fibManager;
116 this.intfRpcService = ifaceMgrRpcService;
117 this.vpnInterfaceManager = vpnInterfaceManager;
118 this.vpnSubnetRouteHandler = vpnSubnetRouteHandler;
119 this.jobCoordinator = jobCoordinator;
123 public void start() {
124 LOG.info("{} start", getClass().getSimpleName());
125 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
129 protected InstanceIdentifier<StateTunnelList> getWildCardPath() {
130 return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
134 protected TunnelInterfaceStateListener getDataTreeChangeListener() {
135 return TunnelInterfaceStateListener.this;
139 protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
140 LOG.trace("remove: Tunnel deletion---- {}", del);
141 if (isGreTunnel(del)) {
142 programDcGwLoadBalancingGroup(del, NwConstants.DEL_FLOW);
144 handleTunnelEventForDPN(del, TunnelAction.TUNNEL_EP_DELETE);
148 protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original,
149 StateTunnelList update) {
150 LOG.trace("update: Tunnel updation---- {}", update);
151 LOG.info("update: ITM Tunnel {} of type {} state event changed from :{} to :{}",
152 update.getTunnelInterfaceName(),
153 fibManager.getTransportTypeStr(update.getTransportType().toString()),
154 original.getOperState(), update.getOperState());
155 TunnelOperStatus tunOpStatus = update.getOperState();
156 if (tunOpStatus != TunnelOperStatus.Down && tunOpStatus != TunnelOperStatus.Up) {
157 LOG.info("update: Returning from unsupported tunnelOperStatus {} for tunnel interface {}", tunOpStatus,
158 update.getTunnelInterfaceName());
161 if (isGreTunnel(update)) {
162 programDcGwLoadBalancingGroup(update, NwConstants.MOD_FLOW);
165 //Remove the corresponding nexthop from the routepath under extraroute in fibentries.
166 BigInteger srcDpnId = new BigInteger(update.getSrcInfo().getTepDeviceId());
167 String srcTepIp = String.valueOf(update.getSrcInfo().getTepIp().getValue());
168 List<VpnInstanceOpDataEntry> vpnInstanceOpData = VpnUtil.getAllVpnInstanceOpData(dataBroker);
169 if (vpnInstanceOpData == null) {
170 LOG.trace("update: No vpnInstanceOpdata present");
173 if (tunOpStatus == TunnelOperStatus.Up) {
174 handleTunnelEventForDPN(update, TunnelAction.TUNNEL_EP_ADD);
176 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx ->
177 vpnInstanceOpData.stream()
178 .filter(opData -> opData.getVpnToDpnList() != null
179 && opData.getVpnToDpnList().stream().anyMatch(
180 vpnToDpn -> vpnToDpn.getDpnId().equals(srcDpnId)))
182 List<DestPrefixes> prefixes = VpnExtraRouteHelper.getExtraRouteDestPrefixes(dataBroker,
184 prefixes.forEach(destPrefix -> {
185 VrfEntry vrfEntry = VpnUtil.getVrfEntry(dataBroker, opData.getVrfId(),
186 destPrefix.getDestPrefix());
187 if (vrfEntry == null || vrfEntry.getRoutePaths() == null) {
190 List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
191 routePaths.forEach(routePath -> {
192 if (routePath.getNexthopAddress().equals(srcTepIp)) {
193 fibManager.updateRoutePathForFibEntry(opData.getVrfId(),
194 destPrefix.getDestPrefix(), srcTepIp, routePath.getLabel(),
200 ), LOG, "Error updating route paths for FIB entries");
205 protected void add(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList add) {
206 LOG.trace("add: Tunnel addition---- {}", add);
207 TunnelOperStatus tunOpStatus = add.getOperState();
208 if (tunOpStatus != TunnelOperStatus.Down && tunOpStatus != TunnelOperStatus.Up) {
209 LOG.info("add: Returning from unsupported tunnelOperStatus {} for tunnel interface {}", tunOpStatus,
210 add.getTunnelInterfaceName());
213 if (tunOpStatus != TunnelOperStatus.Up) {
214 LOG.error("add: Tunnel {} is not yet UP.", add.getTunnelInterfaceName());
216 if (isGreTunnel(add)) {
217 programDcGwLoadBalancingGroup(add, NwConstants.ADD_FLOW);
219 LOG.info("add: ITM Tunnel ,type {} ,added between src: {} and dest: {}",
220 fibManager.getTransportTypeStr(add.getTransportType().toString()),
221 add.getSrcInfo().getTepDeviceId(), add.getDstInfo().getTepDeviceId());
222 handleTunnelEventForDPN(add, TunnelAction.TUNNEL_EP_ADD);
225 public enum TunnelEventProcessingMethod {
226 POPULATESUBNETS(0), MANAGEREMOTEROUTES(1);
228 private final int method;
230 TunnelEventProcessingMethod(int id) {
234 public int getValue() {
239 // TODO Clean up the exception handling
240 @SuppressWarnings("checkstyle:IllegalCatch")
241 private void handleTunnelEventForDPN(StateTunnelList stateTunnelList, TunnelAction tunnelAction) {
242 final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
243 final String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
244 String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
246 BigInteger remoteDpnId = null;
247 boolean isTepDeletedOnDpn = false;
249 LOG.info("handleTunnelEventForDPN: Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ",
250 srcDpnId, srcTepIp, destTepIp);
251 int tunTypeVal = getTunnelType(stateTunnelList);
252 LOG.trace("handleTunnelEventForDPN: tunTypeVal is {}", tunTypeVal);
254 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
255 LOG.info("handleTunnelEventForDPN: Tunnel ADD event received for Dpn {} VTEP Ip {} destTepIp {}",
256 srcDpnId, srcTepIp, destTepIp);
257 if (isTunnelInLogicalGroup(stateTunnelList)) {
260 } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE) {
261 LOG.info("handleTunnelEventForDPN: Tunnel DELETE event received for Dpn {} VTEP Ip {} DestTepIp {}",
262 srcDpnId, srcTepIp, destTepIp);
263 // When tunnel EP is deleted on a DPN , VPN gets two deletion event.
264 // One for a DPN on which tunnel EP was deleted and another for other-end DPN.
265 // Update the adj for the vpninterfaces for a DPN on which TEP is deleted.
266 // Update the adj & VRF for the vpninterfaces for a DPN on which TEP is deleted.
267 // Dont update the adj & VRF for vpninterfaces for a DPN on which TEP is not deleted.
268 String endpointIpForDPN = null;
270 endpointIpForDPN = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
271 } catch (Exception e) {
272 LOG.error("handleTunnelEventForDPN: Unable to resolve endpoint IP for srcDpn {}", srcDpnId);
273 /* this dpn does not have the VTEP */
274 endpointIpForDPN = null;
277 if (endpointIpForDPN == null) {
278 LOG.info("handleTunnelEventForDPN: Tunnel TEP is deleted on Dpn {} VTEP Ip {} destTepIp {}",
279 srcDpnId, srcTepIp, destTepIp);
280 isTepDeletedOnDpn = true;
284 // Get the list of VpnInterfaces from Intf Mgr for a SrcDPN on which TEP is added/deleted
285 Future<RpcResult<GetDpnInterfaceListOutput>> result;
286 List<Interfaces> srcDpninterfacelist = new ArrayList<>();
287 List<Interfaces> destDpninterfacelist = new ArrayList<>();
289 result = intfRpcService.getDpnInterfaceList(
290 new GetDpnInterfaceListInputBuilder().setDpid(srcDpnId).build());
291 RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
292 if (!rpcResult.isSuccessful()) {
293 LOG.error("handleTunnelEventForDPN: RPC Call to GetDpnInterfaceList for srcDpnid {} srcTepIp {}"
294 + " destTepIP {} returned with Errors {}", srcDpnId, srcTepIp, destTepIp,
295 rpcResult.getErrors());
297 srcDpninterfacelist = rpcResult.getResult().getInterfaces();
299 } catch (Exception e) {
300 LOG.error("handleTunnelEventForDPN: Exception when querying for GetDpnInterfaceList for srcDpnid {}"
301 + " srcTepIp {} destTepIp {}", srcDpnId, srcTepIp, destTepIp, e);
303 // Get the list of VpnInterfaces from Intf Mgr for a destDPN only for internal tunnel.
304 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
305 remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
307 result = intfRpcService.getDpnInterfaceList(
308 new GetDpnInterfaceListInputBuilder().setDpid(remoteDpnId).build());
309 RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
310 if (!rpcResult.isSuccessful()) {
311 LOG.error("handleTunnelEventForDPN: RPC Call to GetDpnInterfaceList for remoteDpnid {}"
312 + " srcTepIP {} destTepIp {} returned with Errors {}", remoteDpnId, srcTepIp,
313 destTepIp, rpcResult.getErrors());
315 destDpninterfacelist = rpcResult.getResult().getInterfaces();
317 } catch (Exception e) {
318 LOG.error("handleTunnelEventForDPN: Exception when querying for GetDpnInterfaceList"
319 + " for remoteDpnid {} srcTepIp {} destTepIp {}", remoteDpnId,
320 srcTepIp, destTepIp, e);
325 * Iterate over the list of VpnInterface for a SrcDpn on which TEP is added or deleted and read the adj.
326 * Update the adjacencies with the updated nexthop.
328 Iterator<Interfaces> interfacelistIter = srcDpninterfacelist.iterator();
329 Interfaces interfaces = null;
330 String intfName = null;
331 List<Uuid> subnetList = new ArrayList<>();
332 Map<Long, String> vpnIdRdMap = new HashMap<>();
333 Set<String> listVpnName = new HashSet<>();
335 while (interfacelistIter.hasNext()) {
336 interfaces = interfacelistIter.next();
337 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
338 LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
341 intfName = interfaces.getInterfaceName();
342 VpnInterface vpnInterface =
343 VpnUtil.getConfiguredVpnInterface(dataBroker, intfName);
344 if (vpnInterface != null && !Boolean.TRUE.equals(vpnInterface.isScheduledForRemove())) {
345 listVpnName.addAll(VpnHelper
346 .getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
347 handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
348 tunnelAction, isTepDeletedOnDpn,
349 subnetList, TunnelEventProcessingMethod.POPULATESUBNETS,
354 * Iterate over the list of VpnInterface for destDPN and get the prefix .
355 * Create remote rule for each of those prefix on srcDPN.
357 interfacelistIter = destDpninterfacelist.iterator();
358 while (interfacelistIter.hasNext()) {
359 interfaces = interfacelistIter.next();
360 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
361 LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
364 intfName = interfaces.getInterfaceName();
365 VpnInterface vpnInterface =
366 VpnUtil.getConfiguredVpnInterface(dataBroker, intfName);
367 if (vpnInterface != null) {
368 handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
369 tunnelAction, isTepDeletedOnDpn,
370 subnetList, TunnelEventProcessingMethod.MANAGEREMOTEROUTES,
375 //Iterate over the VpnId-to-Rd map.
376 for (Map.Entry<Long, String> entry : vpnIdRdMap.entrySet()) {
377 Long vpnId = entry.getKey();
378 rd = entry.getValue();
379 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
380 && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
381 fibManager.populateExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
382 } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
383 && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
384 fibManager.cleanUpExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
387 if (listVpnName.size() >= 1) {
388 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
389 for (Uuid subnetId : subnetList) {
390 // Populate the List of subnets
391 vpnSubnetRouteHandler.updateSubnetRouteOnTunnelUpEvent(subnetId, srcDpnId);
394 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
395 for (Uuid subnetId : subnetList) {
396 // Populate the List of subnets
397 vpnSubnetRouteHandler.updateSubnetRouteOnTunnelDownEvent(subnetId, srcDpnId);
401 } catch (RuntimeException e) {
402 LOG.error("handleTunnelEventForDpn: Unable to handle the tunnel event for srcDpnId {} srcTepIp {}"
403 + " remoteDpnId {} destTepIp {}", srcDpnId, srcTepIp, remoteDpnId, destTepIp, e);
407 // TODO Clean up the exception handling
408 @SuppressWarnings("checkstyle:IllegalCatch")
409 private void handleTunnelEventForDPNVpn(StateTunnelList stateTunnelList,
410 Map<Long, String> vpnIdRdMap, TunnelAction tunnelAction,
411 boolean isTepDeletedOnDpn, List<Uuid> subnetList,
412 TunnelEventProcessingMethod method,
413 VpnInterface cfgVpnInterface) {
415 String intfName = cfgVpnInterface.getName();
416 final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
417 String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
418 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
419 int tunTypeVal = getTunnelType(stateTunnelList);
420 BigInteger remoteDpnId = null;
421 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
422 remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
424 if (cfgVpnInterface.getVpnInstanceNames() == null) {
425 LOG.warn("handleTunnelEventForDpn: no vpnName found for interface {}", intfName);
428 for (VpnInstanceNames vpnInstance : cfgVpnInterface.getVpnInstanceNames()) {
429 String vpnName = vpnInstance.getVpnName();
430 if (method == TunnelEventProcessingMethod.POPULATESUBNETS) {
431 Optional<VpnInterfaceOpDataEntry> opVpnInterface = VpnUtil
432 .getVpnInterfaceOpDataEntry(dataBroker, intfName, vpnName);
433 if (opVpnInterface.isPresent() && !opVpnInterface.get().isScheduledForRemove()) {
434 VpnInterfaceOpDataEntry vpnInterface = opVpnInterface.get();
435 jobCoordinator.enqueueJob("VPNINTERFACE-" + intfName,
436 new UpdateVpnInterfaceOnTunnelEvent(tunnelAction,
441 // Populate the List of subnets
442 InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
443 InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
444 new PortOpDataEntryKey(intfName)).build();
445 Optional<PortOpDataEntry> optionalPortOp =
446 VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
447 if (optionalPortOp.isPresent()) {
448 List<Uuid> subnetIdList = optionalPortOp.get().getSubnetIds();
449 if (subnetIdList != null) {
450 for (Uuid subnetId : subnetIdList) {
451 if (!subnetList.contains(subnetId)) {
452 subnetList.add(subnetId);
457 //Populate the map for VpnId-to-Rd
458 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
459 rd = VpnUtil.getVpnRd(dataBroker, vpnName);
460 vpnIdRdMap.put(vpnId, rd);
462 } else if (method == TunnelEventProcessingMethod.MANAGEREMOTEROUTES) {
463 Optional<VpnInterfaceOpDataEntry> opVpnInterface = VpnUtil.getVpnInterfaceOpDataEntry(dataBroker,
465 if (opVpnInterface.isPresent()) {
466 VpnInterfaceOpDataEntry vpnInterface = opVpnInterface.get();
467 AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
468 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency()
469 : Collections.emptyList();
470 String prefix = null;
471 long vpnId = VpnUtil.getVpnId(dataBroker, vpnInterface.getVpnInstanceName());
472 if (vpnIdRdMap.containsKey(vpnId)) {
473 rd = vpnIdRdMap.get(vpnId);
474 LOG.info("handleTunnelEventForDPN: Remote DpnId {} VpnId {} rd {} VpnInterface {} srcTepIp "
475 + "{} destTepIp {}", remoteDpnId, vpnId, rd , vpnInterface, srcTepIp, destTepIp);
476 for (Adjacency adj : adjList) {
477 prefix = adj.getIpAddress();
478 long label = adj.getLabel();
479 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
480 && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
481 fibManager.manageRemoteRouteOnDPN(true, srcDpnId, vpnId, rd, prefix, destTepIp, label);
484 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
485 && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
486 fibManager.manageRemoteRouteOnDPN(false, srcDpnId, vpnId, rd, prefix, destTepIp, label);
495 private class UpdateVpnInterfaceOnTunnelEvent implements Callable {
496 private final VpnInterfaceOpDataEntry vpnInterface;
497 private final StateTunnelList stateTunnelList;
498 private final TunnelAction tunnelAction;
499 private final boolean isTepDeletedOnDpn;
501 UpdateVpnInterfaceOnTunnelEvent(TunnelAction tunnelAction,
502 VpnInterfaceOpDataEntry vpnInterface,
503 StateTunnelList stateTunnelList,
504 boolean isTepDeletedOnDpn) {
505 this.stateTunnelList = stateTunnelList;
506 this.vpnInterface = vpnInterface;
507 this.tunnelAction = tunnelAction;
508 this.isTepDeletedOnDpn = isTepDeletedOnDpn;
512 public List<ListenableFuture<Void>> call() {
513 List<ListenableFuture<Void>> futures = new ArrayList<>(2);
514 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx ->
515 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(operTx -> {
516 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
517 vpnInterfaceManager.updateVpnInterfaceOnTepAdd(vpnInterface, stateTunnelList, confTx,
521 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
522 vpnInterfaceManager.updateVpnInterfaceOnTepDelete(vpnInterface, stateTunnelList, confTx,
530 private int getTunnelType(StateTunnelList stateTunnelList) {
532 if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
533 tunTypeVal = VpnConstants.ITMTunnelLocType.Internal.getValue();
534 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
535 tunTypeVal = VpnConstants.ITMTunnelLocType.External.getValue();
536 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class) {
537 tunTypeVal = VpnConstants.ITMTunnelLocType.Hwvtep.getValue();
539 tunTypeVal = VpnConstants.ITMTunnelLocType.Invalid.getValue();
544 private boolean isGreTunnel(StateTunnelList del) {
545 return del.getTransportType() == TunnelTypeMplsOverGre.class;
548 private void programDcGwLoadBalancingGroup(StateTunnelList tunnelState, int addOrRemove) {
549 IpAddress dcGwIp = tunnelState.getDstInfo().getTepIp();
550 String dcGwIpAddress = String.valueOf(dcGwIp.getValue());
551 List<String> availableDcGws = getDcGwIps();
552 BigInteger dpId = new BigInteger(tunnelState.getSrcInfo().getTepDeviceId());
553 boolean isTunnelUp = TunnelOperStatus.Up == tunnelState.getOperState();
554 fibManager.programDcGwLoadBalancingGroup(availableDcGws, dpId, dcGwIpAddress, addOrRemove, isTunnelUp);
557 private List<String> getDcGwIps() {
558 InstanceIdentifier<DcGatewayIpList> dcGatewayIpListid =
559 InstanceIdentifier.builder(DcGatewayIpList.class).build();
560 DcGatewayIpList dcGatewayIpListConfig =
561 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, dcGatewayIpListid).orNull();
562 if (dcGatewayIpListConfig == null) {
563 return Collections.EMPTY_LIST;
565 return dcGatewayIpListConfig.getDcGatewayIp()
567 .filter(dcGwIp -> dcGwIp.getTunnnelType().equals(TunnelTypeMplsOverGre.class))
568 .map(dcGwIp -> String.valueOf(dcGwIp.getIpAddress().getValue())).sorted()
572 private boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
573 String ifaceName = stateTunnelList.getTunnelInterfaceName();
574 if (getTunnelType(stateTunnelList) == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
575 Interface configIface = InterfaceUtils.getInterface(dataBroker, stateTunnelList.getTunnelInterfaceName());
576 IfTunnel ifTunnel = configIface != null ? configIface.augmentation(IfTunnel.class) : null;
577 if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
578 ParentRefs refs = configIface.augmentation(ParentRefs.class);
579 if (refs != null && !Strings.isNullOrEmpty(refs.getParentInterface())) {
580 return true; //multiple VxLAN tunnels enabled, i.e. only logical tunnel should be treated
584 LOG.trace("isTunnelInLogicalGroup: MULTIPLE_VxLAN_TUNNELS: ignoring the tunnel event for {}", ifaceName);