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> {
79 private static final Logger LOG = LoggerFactory.getLogger(TunnelInterfaceStateListener.class);
80 private final DataBroker dataBroker;
81 private final IFibManager fibManager;
82 private final OdlInterfaceRpcService intfRpcService;
83 private final VpnInterfaceManager vpnInterfaceManager;
84 private final VpnSubnetRouteHandler vpnSubnetRouteHandler;
85 private final JobCoordinator jobCoordinator;
87 protected enum UpdateRouteAction {
88 ADVERTISE_ROUTE, WITHDRAW_ROUTE
91 protected enum TunnelAction {
98 * Responsible for listening to tunnel interface state change.
101 public TunnelInterfaceStateListener(final DataBroker dataBroker,
102 final IFibManager fibManager,
103 final OdlInterfaceRpcService ifaceMgrRpcService,
104 final VpnInterfaceManager vpnInterfaceManager,
105 final VpnSubnetRouteHandler vpnSubnetRouteHandler,
106 final JobCoordinator jobCoordinator) {
107 super(StateTunnelList.class, TunnelInterfaceStateListener.class);
108 this.dataBroker = dataBroker;
109 this.fibManager = fibManager;
110 this.intfRpcService = ifaceMgrRpcService;
111 this.vpnInterfaceManager = vpnInterfaceManager;
112 this.vpnSubnetRouteHandler = vpnSubnetRouteHandler;
113 this.jobCoordinator = jobCoordinator;
117 public void start() {
118 LOG.info("{} start", getClass().getSimpleName());
119 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
123 protected InstanceIdentifier<StateTunnelList> getWildCardPath() {
124 return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
128 protected TunnelInterfaceStateListener getDataTreeChangeListener() {
129 return TunnelInterfaceStateListener.this;
133 protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
134 LOG.trace("remove: Tunnel deletion---- {}", del);
135 if (isGreTunnel(del)) {
136 programDcGwLoadBalancingGroup(del, NwConstants.DEL_FLOW);
138 handleTunnelEventForDPN(del, TunnelAction.TUNNEL_EP_DELETE);
142 protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original,
143 StateTunnelList update) {
144 LOG.trace("update: Tunnel updation---- {}", update);
145 LOG.info("update: ITM Tunnel {} of type {} state event changed from :{} to :{}",
146 update.getTunnelInterfaceName(),
147 fibManager.getTransportTypeStr(update.getTransportType().toString()),
148 original.getOperState(), update.getOperState());
149 TunnelOperStatus tunOpStatus = update.getOperState();
150 if (tunOpStatus != TunnelOperStatus.Down && tunOpStatus != TunnelOperStatus.Up) {
151 LOG.info("update: Returning from unsupported tunnelOperStatus {} for tunnel interface {}", tunOpStatus,
152 update.getTunnelInterfaceName());
155 if (isGreTunnel(update)) {
156 programDcGwLoadBalancingGroup(update, NwConstants.MOD_FLOW);
159 //Remove the corresponding nexthop from the routepath under extraroute in fibentries.
160 BigInteger srcDpnId = new BigInteger(update.getSrcInfo().getTepDeviceId());
161 String srcTepIp = String.valueOf(update.getSrcInfo().getTepIp().getValue());
162 List<VpnInstanceOpDataEntry> vpnInstanceOpData = VpnUtil.getAllVpnInstanceOpData(dataBroker);
163 if (vpnInstanceOpData == null) {
164 LOG.trace("update: No vpnInstanceOpdata present");
167 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
168 if (tunOpStatus == TunnelOperStatus.Up) {
169 handleTunnelEventForDPN(update, TunnelAction.TUNNEL_EP_ADD);
171 vpnInstanceOpData.stream().filter(opData -> {
172 if (opData.getVpnToDpnList() == null) {
175 return opData.getVpnToDpnList().stream().anyMatch(vpnToDpn -> vpnToDpn.getDpnId().equals(srcDpnId));
176 }).forEach(opData -> {
177 List<DestPrefixes> prefixes = VpnExtraRouteHelper.getExtraRouteDestPrefixes(dataBroker,
179 prefixes.forEach(destPrefix -> {
180 VrfEntry vrfEntry = VpnUtil.getVrfEntry(dataBroker, opData.getVrfId(),
181 destPrefix.getDestPrefix());
182 if (vrfEntry == null || vrfEntry.getRoutePaths() == null) {
185 List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
186 routePaths.forEach(routePath -> {
187 if (routePath.getNexthopAddress().equals(srcTepIp)) {
188 fibManager.updateRoutePathForFibEntry(opData.getVrfId(),
189 destPrefix.getDestPrefix(), srcTepIp, routePath.getLabel(),
190 false, writeConfigTxn);
196 writeConfigTxn.submit();
200 protected void add(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList add) {
201 LOG.trace("add: Tunnel addition---- {}", add);
202 TunnelOperStatus tunOpStatus = add.getOperState();
203 if (tunOpStatus != TunnelOperStatus.Down && tunOpStatus != TunnelOperStatus.Up) {
204 LOG.info("add: Returning from unsupported tunnelOperStatus {} for tunnel interface {}", tunOpStatus,
205 add.getTunnelInterfaceName());
208 if (tunOpStatus != TunnelOperStatus.Up) {
209 LOG.error("add: Tunnel {} is not yet UP.", add.getTunnelInterfaceName());
211 if (isGreTunnel(add)) {
212 programDcGwLoadBalancingGroup(add, NwConstants.ADD_FLOW);
214 LOG.info("add: ITM Tunnel ,type {} ,added between src: {} and dest: {}",
215 fibManager.getTransportTypeStr(add.getTransportType().toString()),
216 add.getSrcInfo().getTepDeviceId(), add.getDstInfo().getTepDeviceId());
217 handleTunnelEventForDPN(add, TunnelAction.TUNNEL_EP_ADD);
220 public enum TunnelEventProcessingMethod {
221 POPULATESUBNETS(0), MANAGEREMOTEROUTES(1);
223 private final int method;
225 TunnelEventProcessingMethod(int id) {
229 public int getValue() {
234 // TODO Clean up the exception handling
235 @SuppressWarnings("checkstyle:IllegalCatch")
236 private void handleTunnelEventForDPN(StateTunnelList stateTunnelList,
237 TunnelAction tunnelAction) {
238 final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
239 final String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
240 String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
242 BigInteger remoteDpnId = null;
243 boolean isTepDeletedOnDpn = false;
245 LOG.info("handleTunnelEventForDPN: Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ",
246 srcDpnId, srcTepIp, destTepIp);
247 int tunTypeVal = getTunnelType(stateTunnelList);
248 LOG.trace("handleTunnelEventForDPN: tunTypeVal is {}", tunTypeVal);
250 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
251 LOG.info("handleTunnelEventForDPN: Tunnel ADD event received for Dpn {} VTEP Ip {} destTepIp",
252 srcDpnId, srcTepIp, destTepIp);
253 if (isTunnelInLogicalGroup(stateTunnelList)) {
256 } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE) {
257 LOG.info("handleTunnelEventForDPN: Tunnel DELETE event received for Dpn {} VTEP Ip {} DestTepIp",
258 srcDpnId, srcTepIp, destTepIp);
259 // When tunnel EP is deleted on a DPN , VPN gets two deletion event.
260 // One for a DPN on which tunnel EP was deleted and another for other-end DPN.
261 // Update the adj for the vpninterfaces for a DPN on which TEP is deleted.
262 // Update the adj & VRF for the vpninterfaces for a DPN on which TEP is deleted.
263 // Dont update the adj & VRF for vpninterfaces for a DPN on which TEP is not deleted.
264 String endpointIpForDPN = null;
266 endpointIpForDPN = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
267 } catch (Exception e) {
268 LOG.error("handleTunnelEventForDPN: Unable to resolve endpoint IP for srcDpn {}", srcDpnId);
269 /* this dpn does not have the VTEP */
270 endpointIpForDPN = null;
273 if (endpointIpForDPN == null) {
274 LOG.info("handleTunnelEventForDPN: Tunnel TEP is deleted on Dpn {} VTEP Ip {} destTepIp", srcDpnId,
275 srcTepIp, destTepIp);
276 isTepDeletedOnDpn = true;
280 // Get the list of VpnInterfaces from Intf Mgr for a SrcDPN on which TEP is added/deleted
281 Future<RpcResult<GetDpnInterfaceListOutput>> result;
282 List<Interfaces> srcDpninterfacelist = new ArrayList<>();
283 List<Interfaces> destDpninterfacelist = new ArrayList<>();
285 result = intfRpcService.getDpnInterfaceList(
286 new GetDpnInterfaceListInputBuilder().setDpid(srcDpnId).build());
287 RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
288 if (!rpcResult.isSuccessful()) {
289 LOG.error("handleTunnelEventForDPN: RPC Call to GetDpnInterfaceList for srcDpnid {} srcTepIp {}"
290 + " destTepIP {} returned with Errors {}", srcDpnId, srcTepIp, destTepIp,
291 rpcResult.getErrors());
293 srcDpninterfacelist = rpcResult.getResult().getInterfaces();
295 } catch (Exception e) {
296 LOG.error("handleTunnelEventForDPN: Exception {} when querying for GetDpnInterfaceList for srcDpnid {}"
297 + " srcTepIp {} destTepIp {}, trace {}", e, srcDpnId, srcTepIp, destTepIp, e.getStackTrace());
299 // Get the list of VpnInterfaces from Intf Mgr for a destDPN only for internal tunnel.
300 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
301 remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
303 result = intfRpcService.getDpnInterfaceList(
304 new GetDpnInterfaceListInputBuilder().setDpid(remoteDpnId).build());
305 RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
306 if (!rpcResult.isSuccessful()) {
307 LOG.error("handleTunnelEventForDPN: RPC Call to GetDpnInterfaceList for remoteDpnid {}"
308 + " srcTepIP {} destTepIp {} returned with Errors {}", remoteDpnId, srcTepIp,
309 destTepIp, rpcResult.getErrors());
311 destDpninterfacelist = rpcResult.getResult().getInterfaces();
313 } catch (Exception e) {
314 LOG.error("handleTunnelEventForDPN: Exception {} when querying for GetDpnInterfaceList"
315 + " for remoteDpnid {} srcTepIp {} destTepIp {}, trace {}", e, remoteDpnId,
316 srcTepIp, destTepIp, e.getStackTrace());
321 * Iterate over the list of VpnInterface for a SrcDpn on which TEP is added or deleted and read the adj.
322 * Update the adjacencies with the updated nexthop.
324 Iterator<Interfaces> interfacelistIter = srcDpninterfacelist.iterator();
325 Interfaces interfaces = null;
326 String intfName = null;
327 List<Uuid> subnetList = new ArrayList<>();
328 Map<Long, String> vpnIdRdMap = new HashMap<>();
329 Set<String> listVpnName = new HashSet<String>();
331 while (interfacelistIter.hasNext()) {
332 interfaces = interfacelistIter.next();
333 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
334 LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
337 intfName = interfaces.getInterfaceName();
338 VpnInterface vpnInterface =
339 VpnUtil.getConfiguredVpnInterface(dataBroker, intfName);
340 if (vpnInterface != null && !vpnInterface.isScheduledForRemove()) {
341 listVpnName.addAll(VpnHelper
342 .getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
343 handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
344 tunnelAction, isTepDeletedOnDpn,
345 subnetList, TunnelEventProcessingMethod.POPULATESUBNETS,
350 * Iterate over the list of VpnInterface for destDPN and get the prefix .
351 * Create remote rule for each of those prefix on srcDPN.
353 interfacelistIter = destDpninterfacelist.iterator();
354 while (interfacelistIter.hasNext()) {
355 interfaces = interfacelistIter.next();
356 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
357 LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
360 intfName = interfaces.getInterfaceName();
361 VpnInterface vpnInterface =
362 VpnUtil.getConfiguredVpnInterface(dataBroker, intfName);
363 if (vpnInterface != null) {
364 handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
365 tunnelAction, isTepDeletedOnDpn,
366 subnetList, TunnelEventProcessingMethod.MANAGEREMOTEROUTES,
371 //Iterate over the VpnId-to-Rd map.
372 for (Map.Entry<Long, String> entry : vpnIdRdMap.entrySet()) {
373 Long vpnId = entry.getKey();
374 rd = entry.getValue();
375 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
376 && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
377 fibManager.populateExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
378 } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
379 && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
380 fibManager.cleanUpExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
383 if (listVpnName.size() >= 1) {
384 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
385 for (Uuid subnetId : subnetList) {
386 // Populate the List of subnets
387 vpnSubnetRouteHandler.updateSubnetRouteOnTunnelUpEvent(subnetId, srcDpnId);
390 if ((tunnelAction == TunnelAction.TUNNEL_EP_DELETE) && isTepDeletedOnDpn) {
391 for (Uuid subnetId : subnetList) {
392 // Populate the List of subnets
393 vpnSubnetRouteHandler.updateSubnetRouteOnTunnelDownEvent(subnetId, srcDpnId);
397 } catch (RuntimeException e) {
398 LOG.error("handleTunnelEventForDpn: Unable to handle the tunnel event for srcDpnId {} srcTepIp {}"
399 + " remoteDpnId {} destTepIp {}", srcDpnId, srcTepIp, remoteDpnId, destTepIp, e);
403 // TODO Clean up the exception handling
404 @SuppressWarnings("checkstyle:IllegalCatch")
405 private void handleTunnelEventForDPNVpn(StateTunnelList stateTunnelList,
406 Map<Long, String> vpnIdRdMap, TunnelAction tunnelAction,
407 boolean isTepDeletedOnDpn, List<Uuid> subnetList,
408 TunnelEventProcessingMethod method,
409 VpnInterface cfgVpnInterface) {
411 String intfName = cfgVpnInterface.getName();
412 final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
413 String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
414 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
415 int tunTypeVal = getTunnelType(stateTunnelList);
416 BigInteger remoteDpnId = null;
417 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
418 remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
420 if (cfgVpnInterface.getVpnInstanceNames() == null) {
421 LOG.warn("handleTunnelEventForDpn: no vpnName found for interface {}", intfName);
424 for (VpnInstanceNames vpnInstance : cfgVpnInterface.getVpnInstanceNames()) {
425 String vpnName = vpnInstance.getVpnName();
426 if (method == TunnelEventProcessingMethod.POPULATESUBNETS) {
427 Optional<VpnInterfaceOpDataEntry> opVpnInterface = VpnUtil
428 .getVpnInterfaceOpDataEntry(dataBroker, intfName, vpnName);
429 if (opVpnInterface.isPresent() && !opVpnInterface.get().isScheduledForRemove()) {
430 VpnInterfaceOpDataEntry vpnInterface = opVpnInterface.get();
431 jobCoordinator.enqueueJob("VPNINTERFACE-" + intfName,
432 new UpdateVpnInterfaceOnTunnelEvent(tunnelAction,
437 // Populate the List of subnets
438 InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
439 InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
440 new PortOpDataEntryKey(intfName)).build();
441 Optional<PortOpDataEntry> optionalPortOp =
442 VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
443 if (optionalPortOp.isPresent()) {
444 List<Uuid> subnetIdList = optionalPortOp.get().getSubnetIds();
445 if (subnetIdList != null) {
446 for (Uuid subnetId : subnetIdList) {
447 if (!subnetList.contains(subnetId)) {
448 subnetList.add(subnetId);
453 //Populate the map for VpnId-to-Rd
454 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
455 rd = VpnUtil.getVpnRd(dataBroker, vpnName);
456 vpnIdRdMap.put(vpnId, rd);
458 } else if (method == TunnelEventProcessingMethod.MANAGEREMOTEROUTES) {
459 Optional<VpnInterfaceOpDataEntry> opVpnInterface = VpnUtil.getVpnInterfaceOpDataEntry(dataBroker,
461 if (opVpnInterface.isPresent()) {
462 VpnInterfaceOpDataEntry vpnInterface = opVpnInterface.get();
463 AdjacenciesOp adjacencies = vpnInterface.getAugmentation(AdjacenciesOp.class);
464 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency()
465 : Collections.emptyList();
466 String prefix = null;
467 long vpnId = VpnUtil.getVpnId(dataBroker, vpnInterface.getVpnInstanceName());
468 if (vpnIdRdMap.containsKey(vpnId)) {
469 rd = vpnIdRdMap.get(vpnId);
470 LOG.info("handleTunnelEventForDPN: Remote DpnId {} VpnId {} rd {} VpnInterface {} srcTepIp "
471 + "{} destTepIp {}", remoteDpnId, vpnId, rd , vpnInterface, srcTepIp, destTepIp);
472 for (Adjacency adj : adjList) {
473 prefix = adj.getIpAddress();
474 long label = adj.getLabel();
475 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
476 && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
477 fibManager.manageRemoteRouteOnDPN(true, srcDpnId, vpnId, rd, prefix, destTepIp, label);
480 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
481 && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
482 fibManager.manageRemoteRouteOnDPN(false, srcDpnId, vpnId, rd, prefix, destTepIp, label);
491 private class UpdateVpnInterfaceOnTunnelEvent implements Callable {
492 private final VpnInterfaceOpDataEntry vpnInterface;
493 private final StateTunnelList stateTunnelList;
494 private final TunnelAction tunnelAction;
495 private final boolean isTepDeletedOnDpn;
497 UpdateVpnInterfaceOnTunnelEvent(TunnelAction tunnelAction,
498 VpnInterfaceOpDataEntry vpnInterface,
499 StateTunnelList stateTunnelList,
500 boolean isTepDeletedOnDpn) {
501 this.stateTunnelList = stateTunnelList;
502 this.vpnInterface = vpnInterface;
503 this.tunnelAction = tunnelAction;
504 this.isTepDeletedOnDpn = isTepDeletedOnDpn;
508 public List<ListenableFuture<Void>> call() {
509 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
510 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
511 List<ListenableFuture<Void>> futures = new ArrayList<>();
513 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
514 vpnInterfaceManager.updateVpnInterfaceOnTepAdd(vpnInterface,
520 if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
521 vpnInterfaceManager.updateVpnInterfaceOnTepDelete(vpnInterface,
527 futures.add(writeOperTxn.submit());
528 futures.add(writeConfigTxn.submit());
533 private int getTunnelType(StateTunnelList stateTunnelList) {
535 if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
536 tunTypeVal = VpnConstants.ITMTunnelLocType.Internal.getValue();
537 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
538 tunTypeVal = VpnConstants.ITMTunnelLocType.External.getValue();
539 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class) {
540 tunTypeVal = VpnConstants.ITMTunnelLocType.Hwvtep.getValue();
542 tunTypeVal = VpnConstants.ITMTunnelLocType.Invalid.getValue();
547 private boolean isGreTunnel(StateTunnelList del) {
548 return del.getTransportType() == TunnelTypeMplsOverGre.class;
551 private void programDcGwLoadBalancingGroup(StateTunnelList tunnelState, int addOrRemove) {
552 IpAddress dcGwIp = tunnelState.getDstInfo().getTepIp();
553 String dcGwIpAddress = String.valueOf(dcGwIp.getValue());
554 List<String> availableDcGws = getDcGwIps();
555 BigInteger dpId = new BigInteger(tunnelState.getSrcInfo().getTepDeviceId());
556 boolean isTunnelUp = TunnelOperStatus.Up == tunnelState.getOperState();
557 fibManager.programDcGwLoadBalancingGroup(availableDcGws, dpId, dcGwIpAddress, addOrRemove, isTunnelUp);
560 private List<String> getDcGwIps() {
561 InstanceIdentifier<DcGatewayIpList> dcGatewayIpListid =
562 InstanceIdentifier.builder(DcGatewayIpList.class).build();
563 DcGatewayIpList dcGatewayIpListConfig =
564 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, dcGatewayIpListid).orNull();
565 if (dcGatewayIpListConfig == null) {
566 return Collections.EMPTY_LIST;
568 return dcGatewayIpListConfig.getDcGatewayIp()
570 .filter(dcGwIp -> dcGwIp.getTunnnelType().equals(TunnelTypeMplsOverGre.class))
571 .map(dcGwIp -> String.valueOf(dcGwIp.getIpAddress().getValue())).sorted()
575 private boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
576 String ifaceName = stateTunnelList.getTunnelInterfaceName();
577 if (getTunnelType(stateTunnelList) == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
578 Interface configIface = InterfaceUtils.getInterface(dataBroker, stateTunnelList.getTunnelInterfaceName());
579 IfTunnel ifTunnel = configIface != null ? configIface.getAugmentation(IfTunnel.class) : null;
580 if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
581 ParentRefs refs = configIface.getAugmentation(ParentRefs.class);
582 if (refs != null && !Strings.isNullOrEmpty(refs.getParentInterface())) {
583 return true; //multiple VxLAN tunnels enabled, i.e. only logical tunnel should be treated
587 LOG.trace("isTunnelInLogicalGroup: MULTIPLE_VxLAN_TUNNELS: ignoring the tunnel event for {}", ifaceName);