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.binding.api.WriteTransaction;
31 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
32 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
33 import org.opendaylight.genius.mdsalutil.MDSALUtil;
34 import org.opendaylight.genius.mdsalutil.NwConstants;
35 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
36 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
37 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
38 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
39 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
40 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
41 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpnInterfaceListInputBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpnInterfaceListOutput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.get.dpn._interface.list.output.Interfaces;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.extraroute.rds.map.extraroute.rds.DestPrefixes;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpData;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
71 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
72 import org.opendaylight.yangtools.yang.common.RpcResult;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
77 public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBase<StateTunnelList,
78 TunnelInterfaceStateListener> {
80 private static final Logger LOG = LoggerFactory.getLogger(TunnelInterfaceStateListener.class);
82 private final DataBroker dataBroker;
83 private final IFibManager fibManager;
84 private final OdlInterfaceRpcService intfRpcService;
85 private final VpnInterfaceManager vpnInterfaceManager;
86 private final VpnSubnetRouteHandler vpnSubnetRouteHandler;
87 private final JobCoordinator jobCoordinator;
89 protected enum UpdateRouteAction {
90 ADVERTISE_ROUTE, WITHDRAW_ROUTE
93 protected enum TunnelAction {
100 * Responsible for listening to tunnel interface state change.
103 public TunnelInterfaceStateListener(final DataBroker dataBroker,
104 final IFibManager fibManager,
105 final OdlInterfaceRpcService ifaceMgrRpcService,
106 final VpnInterfaceManager vpnInterfaceManager,
107 final VpnSubnetRouteHandler vpnSubnetRouteHandler,
108 final JobCoordinator jobCoordinator) {
109 super(StateTunnelList.class, TunnelInterfaceStateListener.class);
110 this.dataBroker = dataBroker;
111 this.fibManager = fibManager;
112 this.intfRpcService = ifaceMgrRpcService;
113 this.vpnInterfaceManager = vpnInterfaceManager;
114 this.vpnSubnetRouteHandler = vpnSubnetRouteHandler;
115 this.jobCoordinator = jobCoordinator;
119 public void start() {
120 LOG.info("{} start", getClass().getSimpleName());
121 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
125 protected InstanceIdentifier<StateTunnelList> getWildCardPath() {
126 return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
130 protected TunnelInterfaceStateListener getDataTreeChangeListener() {
131 return TunnelInterfaceStateListener.this;
135 protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
136 LOG.trace("remove: Tunnel deletion---- {}", del);
137 if (isGreTunnel(del)) {
138 programDcGwLoadBalancingGroup(del, NwConstants.DEL_FLOW);
140 handleTunnelEventForDPN(del, TunnelAction.TUNNEL_EP_DELETE);
144 protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original,
145 StateTunnelList update) {
146 LOG.trace("update: Tunnel updation---- {}", update);
147 LOG.info("update: ITM Tunnel {} of type {} state event changed from :{} to :{}",
148 update.getTunnelInterfaceName(),
149 fibManager.getTransportTypeStr(update.getTransportType().toString()),
150 original.getOperState(), update.getOperState());
151 TunnelOperStatus tunOpStatus = update.getOperState();
152 if (tunOpStatus != TunnelOperStatus.Down && tunOpStatus != TunnelOperStatus.Up) {
153 LOG.info("update: Returning from unsupported tunnelOperStatus {} for tunnel interface {}", tunOpStatus,
154 update.getTunnelInterfaceName());
157 if (isGreTunnel(update)) {
158 programDcGwLoadBalancingGroup(update, NwConstants.MOD_FLOW);
161 //Remove the corresponding nexthop from the routepath under extraroute in fibentries.
162 BigInteger srcDpnId = new BigInteger(update.getSrcInfo().getTepDeviceId());
163 String srcTepIp = String.valueOf(update.getSrcInfo().getTepIp().getValue());
164 List<VpnInstanceOpDataEntry> vpnInstanceOpData = VpnUtil.getAllVpnInstanceOpData(dataBroker);
165 if (vpnInstanceOpData == null) {
166 LOG.trace("update: No vpnInstanceOpdata present");
169 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
170 if (tunOpStatus == TunnelOperStatus.Up) {
171 handleTunnelEventForDPN(update, TunnelAction.TUNNEL_EP_ADD);
173 vpnInstanceOpData.stream().filter(opData -> {
174 if (opData.getVpnToDpnList() == null) {
177 return opData.getVpnToDpnList().stream().anyMatch(vpnToDpn -> vpnToDpn.getDpnId().equals(srcDpnId));
178 }).forEach(opData -> {
179 List<DestPrefixes> prefixes = VpnExtraRouteHelper.getExtraRouteDestPrefixes(dataBroker,
181 prefixes.forEach(destPrefix -> {
182 VrfEntry vrfEntry = VpnUtil.getVrfEntry(dataBroker, opData.getVrfId(),
183 destPrefix.getDestPrefix());
184 if (vrfEntry == null || vrfEntry.getRoutePaths() == null) {
187 List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
188 routePaths.forEach(routePath -> {
189 if (routePath.getNexthopAddress().equals(srcTepIp)) {
190 fibManager.updateRoutePathForFibEntry(opData.getVrfId(),
191 destPrefix.getDestPrefix(), srcTepIp, routePath.getLabel(),
192 false, writeConfigTxn);
198 writeConfigTxn.submit();
202 protected void add(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList add) {
203 LOG.trace("add: Tunnel addition---- {}", add);
204 TunnelOperStatus tunOpStatus = add.getOperState();
205 if (tunOpStatus != TunnelOperStatus.Down && tunOpStatus != TunnelOperStatus.Up) {
206 LOG.info("add: Returning from unsupported tunnelOperStatus {} for tunnel interface {}", tunOpStatus,
207 add.getTunnelInterfaceName());
210 if (tunOpStatus != TunnelOperStatus.Up) {
211 LOG.error("add: Tunnel {} is not yet UP.", add.getTunnelInterfaceName());
213 if (isGreTunnel(add)) {
214 programDcGwLoadBalancingGroup(add, NwConstants.ADD_FLOW);
216 LOG.info("add: ITM Tunnel ,type {} ,added between src: {} and dest: {}",
217 fibManager.getTransportTypeStr(add.getTransportType().toString()),
218 add.getSrcInfo().getTepDeviceId(), add.getDstInfo().getTepDeviceId());
219 handleTunnelEventForDPN(add, TunnelAction.TUNNEL_EP_ADD);
222 public enum TunnelEventProcessingMethod {
223 POPULATESUBNETS(0), MANAGEREMOTEROUTES(1);
225 private final int method;
227 TunnelEventProcessingMethod(int id) {
231 public int getValue() {
236 // TODO Clean up the exception handling
237 @SuppressWarnings("checkstyle:IllegalCatch")
238 private void handleTunnelEventForDPN(StateTunnelList stateTunnelList, TunnelAction tunnelAction) {
239 final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
240 final String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
241 String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
243 BigInteger remoteDpnId = null;
244 boolean isTepDeletedOnDpn = false;
246 LOG.info("handleTunnelEventForDPN: Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ",
247 srcDpnId, srcTepIp, destTepIp);
248 int tunTypeVal = getTunnelType(stateTunnelList);
249 LOG.trace("handleTunnelEventForDPN: tunTypeVal is {}", tunTypeVal);
251 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
252 LOG.info("handleTunnelEventForDPN: Tunnel ADD event received for Dpn {} VTEP Ip {} destTepIp {}",
253 srcDpnId, srcTepIp, destTepIp);
254 if (isTunnelInLogicalGroup(stateTunnelList)) {
257 } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE) {
258 LOG.info("handleTunnelEventForDPN: Tunnel DELETE event received for Dpn {} VTEP Ip {} DestTepIp {}",
259 srcDpnId, srcTepIp, destTepIp);
260 // When tunnel EP is deleted on a DPN , VPN gets two deletion event.
261 // One for a DPN on which tunnel EP was deleted and another for other-end DPN.
262 // Update the adj for the vpninterfaces for a DPN on which TEP is deleted.
263 // Update the adj & VRF for the vpninterfaces for a DPN on which TEP is deleted.
264 // Dont update the adj & VRF for vpninterfaces for a DPN on which TEP is not deleted.
265 String endpointIpForDPN = null;
267 endpointIpForDPN = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
268 } catch (Exception e) {
269 LOG.error("handleTunnelEventForDPN: Unable to resolve endpoint IP for srcDpn {}", srcDpnId);
270 /* this dpn does not have the VTEP */
271 endpointIpForDPN = null;
274 if (endpointIpForDPN == null) {
275 LOG.info("handleTunnelEventForDPN: Tunnel TEP is deleted on Dpn {} VTEP Ip {} destTepIp {}",
276 srcDpnId, srcTepIp, destTepIp);
277 isTepDeletedOnDpn = true;
281 // Get the list of VpnInterfaces from Intf Mgr for a SrcDPN on which TEP is added/deleted
282 Future<RpcResult<GetDpnInterfaceListOutput>> result;
283 List<Interfaces> srcDpninterfacelist = new ArrayList<>();
284 List<Interfaces> destDpninterfacelist = new ArrayList<>();
286 result = intfRpcService.getDpnInterfaceList(
287 new GetDpnInterfaceListInputBuilder().setDpid(srcDpnId).build());
288 RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
289 if (!rpcResult.isSuccessful()) {
290 LOG.error("handleTunnelEventForDPN: RPC Call to GetDpnInterfaceList for srcDpnid {} srcTepIp {}"
291 + " destTepIP {} returned with Errors {}", srcDpnId, srcTepIp, destTepIp,
292 rpcResult.getErrors());
294 srcDpninterfacelist = rpcResult.getResult().getInterfaces();
296 } catch (Exception e) {
297 LOG.error("handleTunnelEventForDPN: Exception when querying for GetDpnInterfaceList for srcDpnid {}"
298 + " srcTepIp {} destTepIp {}", srcDpnId, srcTepIp, destTepIp, e);
300 // Get the list of VpnInterfaces from Intf Mgr for a destDPN only for internal tunnel.
301 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
302 remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
304 result = intfRpcService.getDpnInterfaceList(
305 new GetDpnInterfaceListInputBuilder().setDpid(remoteDpnId).build());
306 RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
307 if (!rpcResult.isSuccessful()) {
308 LOG.error("handleTunnelEventForDPN: RPC Call to GetDpnInterfaceList for remoteDpnid {}"
309 + " srcTepIP {} destTepIp {} returned with Errors {}", remoteDpnId, srcTepIp,
310 destTepIp, rpcResult.getErrors());
312 destDpninterfacelist = rpcResult.getResult().getInterfaces();
314 } catch (Exception e) {
315 LOG.error("handleTunnelEventForDPN: Exception when querying for GetDpnInterfaceList"
316 + " for remoteDpnid {} srcTepIp {} destTepIp {}", remoteDpnId,
317 srcTepIp, destTepIp, e);
322 * Iterate over the list of VpnInterface for a SrcDpn on which TEP is added or deleted and read the adj.
323 * Update the adjacencies with the updated nexthop.
325 Iterator<Interfaces> interfacelistIter = srcDpninterfacelist.iterator();
326 Interfaces interfaces = null;
327 String intfName = null;
328 List<Uuid> subnetList = new ArrayList<>();
329 Map<Long, String> vpnIdRdMap = new HashMap<>();
330 Set<String> listVpnName = new HashSet<>();
332 while (interfacelistIter.hasNext()) {
333 interfaces = interfacelistIter.next();
334 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
335 LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
338 intfName = interfaces.getInterfaceName();
339 VpnInterface vpnInterface =
340 VpnUtil.getConfiguredVpnInterface(dataBroker, intfName);
341 if (vpnInterface != null && !Boolean.TRUE.equals(vpnInterface.isScheduledForRemove())) {
342 listVpnName.addAll(VpnHelper
343 .getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
344 handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
345 tunnelAction, isTepDeletedOnDpn,
346 subnetList, TunnelEventProcessingMethod.POPULATESUBNETS,
351 * Iterate over the list of VpnInterface for destDPN and get the prefix .
352 * Create remote rule for each of those prefix on srcDPN.
354 interfacelistIter = destDpninterfacelist.iterator();
355 while (interfacelistIter.hasNext()) {
356 interfaces = interfacelistIter.next();
357 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
358 LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
361 intfName = interfaces.getInterfaceName();
362 VpnInterface vpnInterface =
363 VpnUtil.getConfiguredVpnInterface(dataBroker, intfName);
364 if (vpnInterface != null) {
365 handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
366 tunnelAction, isTepDeletedOnDpn,
367 subnetList, TunnelEventProcessingMethod.MANAGEREMOTEROUTES,
372 //Iterate over the VpnId-to-Rd map.
373 for (Map.Entry<Long, String> entry : vpnIdRdMap.entrySet()) {
374 Long vpnId = entry.getKey();
375 rd = entry.getValue();
376 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
377 && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
378 fibManager.populateExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
379 } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
380 && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
381 fibManager.cleanUpExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
384 if (listVpnName.size() >= 1) {
385 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
386 for (Uuid subnetId : subnetList) {
387 // Populate the List of subnets
388 vpnSubnetRouteHandler.updateSubnetRouteOnTunnelUpEvent(subnetId, srcDpnId);
391 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
392 for (Uuid subnetId : subnetList) {
393 // Populate the List of subnets
394 vpnSubnetRouteHandler.updateSubnetRouteOnTunnelDownEvent(subnetId, srcDpnId);
398 } catch (RuntimeException e) {
399 LOG.error("handleTunnelEventForDpn: Unable to handle the tunnel event for srcDpnId {} srcTepIp {}"
400 + " remoteDpnId {} destTepIp {}", srcDpnId, srcTepIp, remoteDpnId, destTepIp, e);
404 // TODO Clean up the exception handling
405 @SuppressWarnings("checkstyle:IllegalCatch")
406 private void handleTunnelEventForDPNVpn(StateTunnelList stateTunnelList,
407 Map<Long, String> vpnIdRdMap, TunnelAction tunnelAction,
408 boolean isTepDeletedOnDpn, List<Uuid> subnetList,
409 TunnelEventProcessingMethod method,
410 VpnInterface cfgVpnInterface) {
412 String intfName = cfgVpnInterface.getName();
413 final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
414 String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
415 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
416 int tunTypeVal = getTunnelType(stateTunnelList);
417 BigInteger remoteDpnId = null;
418 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
419 remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
421 if (cfgVpnInterface.getVpnInstanceNames() == null) {
422 LOG.warn("handleTunnelEventForDpn: no vpnName found for interface {}", intfName);
425 for (VpnInstanceNames vpnInstance : cfgVpnInterface.getVpnInstanceNames()) {
426 String vpnName = vpnInstance.getVpnName();
427 if (method == TunnelEventProcessingMethod.POPULATESUBNETS) {
428 Optional<VpnInterfaceOpDataEntry> opVpnInterface = VpnUtil
429 .getVpnInterfaceOpDataEntry(dataBroker, intfName, vpnName);
430 if (opVpnInterface.isPresent() && !opVpnInterface.get().isScheduledForRemove()) {
431 VpnInterfaceOpDataEntry vpnInterface = opVpnInterface.get();
432 jobCoordinator.enqueueJob("VPNINTERFACE-" + intfName,
433 new UpdateVpnInterfaceOnTunnelEvent(tunnelAction,
438 // Populate the List of subnets
439 InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
440 InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
441 new PortOpDataEntryKey(intfName)).build();
442 Optional<PortOpDataEntry> optionalPortOp =
443 VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
444 if (optionalPortOp.isPresent()) {
445 List<Uuid> subnetIdList = optionalPortOp.get().getSubnetIds();
446 if (subnetIdList != null) {
447 for (Uuid subnetId : subnetIdList) {
448 if (!subnetList.contains(subnetId)) {
449 subnetList.add(subnetId);
454 //Populate the map for VpnId-to-Rd
455 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
456 rd = VpnUtil.getVpnRd(dataBroker, vpnName);
457 vpnIdRdMap.put(vpnId, rd);
459 } else if (method == TunnelEventProcessingMethod.MANAGEREMOTEROUTES) {
460 Optional<VpnInterfaceOpDataEntry> opVpnInterface = VpnUtil.getVpnInterfaceOpDataEntry(dataBroker,
462 if (opVpnInterface.isPresent()) {
463 VpnInterfaceOpDataEntry vpnInterface = opVpnInterface.get();
464 AdjacenciesOp adjacencies = vpnInterface.getAugmentation(AdjacenciesOp.class);
465 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency()
466 : Collections.emptyList();
467 String prefix = null;
468 long vpnId = VpnUtil.getVpnId(dataBroker, vpnInterface.getVpnInstanceName());
469 if (vpnIdRdMap.containsKey(vpnId)) {
470 rd = vpnIdRdMap.get(vpnId);
471 LOG.info("handleTunnelEventForDPN: Remote DpnId {} VpnId {} rd {} VpnInterface {} srcTepIp "
472 + "{} destTepIp {}", remoteDpnId, vpnId, rd , vpnInterface, srcTepIp, destTepIp);
473 for (Adjacency adj : adjList) {
474 prefix = adj.getIpAddress();
475 long label = adj.getLabel();
476 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
477 && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
478 fibManager.manageRemoteRouteOnDPN(true, srcDpnId, vpnId, rd, prefix, destTepIp, label);
481 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
482 && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
483 fibManager.manageRemoteRouteOnDPN(false, srcDpnId, vpnId, rd, prefix, destTepIp, label);
492 private class UpdateVpnInterfaceOnTunnelEvent implements Callable {
493 private final VpnInterfaceOpDataEntry vpnInterface;
494 private final StateTunnelList stateTunnelList;
495 private final TunnelAction tunnelAction;
496 private final boolean isTepDeletedOnDpn;
498 UpdateVpnInterfaceOnTunnelEvent(TunnelAction tunnelAction,
499 VpnInterfaceOpDataEntry vpnInterface,
500 StateTunnelList stateTunnelList,
501 boolean isTepDeletedOnDpn) {
502 this.stateTunnelList = stateTunnelList;
503 this.vpnInterface = vpnInterface;
504 this.tunnelAction = tunnelAction;
505 this.isTepDeletedOnDpn = isTepDeletedOnDpn;
509 public List<ListenableFuture<Void>> call() {
510 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
511 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
512 List<ListenableFuture<Void>> futures = new ArrayList<>();
514 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
515 vpnInterfaceManager.updateVpnInterfaceOnTepAdd(vpnInterface,
521 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
522 vpnInterfaceManager.updateVpnInterfaceOnTepDelete(vpnInterface,
528 futures.add(writeOperTxn.submit());
529 futures.add(writeConfigTxn.submit());
534 private int getTunnelType(StateTunnelList stateTunnelList) {
536 if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
537 tunTypeVal = VpnConstants.ITMTunnelLocType.Internal.getValue();
538 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
539 tunTypeVal = VpnConstants.ITMTunnelLocType.External.getValue();
540 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class) {
541 tunTypeVal = VpnConstants.ITMTunnelLocType.Hwvtep.getValue();
543 tunTypeVal = VpnConstants.ITMTunnelLocType.Invalid.getValue();
548 private boolean isGreTunnel(StateTunnelList del) {
549 return del.getTransportType() == TunnelTypeMplsOverGre.class;
552 private void programDcGwLoadBalancingGroup(StateTunnelList tunnelState, int addOrRemove) {
553 IpAddress dcGwIp = tunnelState.getDstInfo().getTepIp();
554 String dcGwIpAddress = String.valueOf(dcGwIp.getValue());
555 List<String> availableDcGws = getDcGwIps();
556 BigInteger dpId = new BigInteger(tunnelState.getSrcInfo().getTepDeviceId());
557 boolean isTunnelUp = TunnelOperStatus.Up == tunnelState.getOperState();
558 fibManager.programDcGwLoadBalancingGroup(availableDcGws, dpId, dcGwIpAddress, addOrRemove, isTunnelUp);
561 private List<String> getDcGwIps() {
562 InstanceIdentifier<DcGatewayIpList> dcGatewayIpListid =
563 InstanceIdentifier.builder(DcGatewayIpList.class).build();
564 DcGatewayIpList dcGatewayIpListConfig =
565 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, dcGatewayIpListid).orNull();
566 if (dcGatewayIpListConfig == null) {
567 return Collections.EMPTY_LIST;
569 return dcGatewayIpListConfig.getDcGatewayIp()
571 .filter(dcGwIp -> dcGwIp.getTunnnelType().equals(TunnelTypeMplsOverGre.class))
572 .map(dcGwIp -> String.valueOf(dcGwIp.getIpAddress().getValue())).sorted()
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.getAugmentation(IfTunnel.class) : null;
581 if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
582 ParentRefs refs = configIface.getAugmentation(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);