2 * Copyright (c) 2016 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 com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.List;
19 import java.util.Objects;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.genius.mdsalutil.MDSALUtil;
23 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
24 import org.opendaylight.netvirt.vpnmanager.VpnOpDataSyncer.VpnOpDataType;
25 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpData;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.SubnetOpData;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.TaskState;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpn;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
47 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
51 public class VpnSubnetRouteHandler {
52 private static final Logger LOG = LoggerFactory.getLogger(VpnSubnetRouteHandler.class);
53 private final DataBroker dataBroker;
54 private final SubnetOpDpnManager subOpDpnManager;
55 private final IBgpManager bgpManager;
56 private final VpnInterfaceManager vpnInterfaceManager;
57 private final IdManagerService idManager;
58 private LockManagerService lockManager;
59 private final VpnOpDataSyncer vpnOpDataSyncer;
61 public VpnSubnetRouteHandler(final DataBroker dataBroker, final SubnetOpDpnManager subnetOpDpnManager,
62 final IBgpManager bgpManager, final VpnInterfaceManager vpnIntfManager, final IdManagerService idManager,
63 LockManagerService lockManagerService, final VpnOpDataSyncer vpnOpDataSyncer) {
64 this.dataBroker = dataBroker;
65 this.subOpDpnManager = subnetOpDpnManager;
66 this.bgpManager = bgpManager;
67 this.vpnInterfaceManager = vpnIntfManager;
68 this.idManager = idManager;
69 this.lockManager = lockManagerService;
70 this.vpnOpDataSyncer = vpnOpDataSyncer;
73 // TODO Clean up the exception handling
74 @SuppressWarnings("checkstyle:IllegalCatch")
75 public void onSubnetAddedToVpn(Subnetmap subnetmap, boolean isBgpVpn, Long elanTag) {
76 Uuid subnetId = subnetmap.getId();
77 String vpnName = subnetmap.getVpnId().getValue();
78 String subnetIp = subnetmap.getSubnetIp();
79 boolean isRouteAdvertised = false;
81 Preconditions.checkNotNull(subnetId, "SubnetId cannot be null or empty!");
82 Preconditions.checkNotNull(subnetIp, "SubnetPrefix cannot be null or empty!");
83 Preconditions.checkNotNull(vpnName, "VpnName cannot be null or empty!");
84 Preconditions.checkNotNull(elanTag, "ElanTag cannot be null or empty!");
86 LOG.info("onSubnetAddedToVpn: Subnet {} being added to vpn", subnetId.getValue());
88 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
89 if (vpnId == VpnConstants.INVALID_ID) {
90 vpnOpDataSyncer.waitForVpnDataReady(VpnOpDataType.vpnInstanceToId, vpnName,
91 VpnConstants.PER_VPN_INSTANCE_MAX_WAIT_TIME_IN_MILLISECONDS);
92 vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
93 if (vpnId == VpnConstants.INVALID_ID) {
95 "onSubnetAddedToVpn: VpnInstance to VPNId mapping not yet available for VpnName {} processing "
96 + "subnet {} with IP {}, bailing out now.", vpnName, subnetId, subnetIp);
101 //TODO(vivek): Change this to use more granularized lock at subnetId level
103 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
105 Subnetmap subMap = null;
107 // Please check if subnetId belongs to an External Network
108 InstanceIdentifier<Subnetmap> subMapid =
109 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
110 new SubnetmapKey(subnetId)).build();
111 Optional<Subnetmap> sm = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, subMapid);
112 if (!sm.isPresent()) {
113 LOG.error("onSubnetAddedToVpn: Unable to retrieve subnetmap entry for subnet : " + subnetId);
119 InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
120 .child(Networks.class, new NetworksKey(subMap.getNetworkId())).build();
121 Optional<Networks> optionalNets = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
123 if (optionalNets.isPresent()) {
124 LOG.info("onSubnetAddedToVpn: subnet {} is an external subnet on external network" + " {},"
125 + " so ignoring this" + " for SubnetRoute",
126 subnetId.getValue(), subMap.getNetworkId().getValue());
130 //Create and add SubnetOpDataEntry object for this subnet to the SubnetOpData container
131 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
132 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
133 new SubnetOpDataEntryKey(subnetId)).build();
134 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
135 LogicalDatastoreType.OPERATIONAL,
137 if (optionalSubs.isPresent()) {
138 LOG.error("onSubnetAddedToVpn: SubnetOpDataEntry for subnet {} already detected to be present",
139 subnetId.getValue());
142 LOG.debug("onSubnetAddedToVpn: Creating new SubnetOpDataEntry node for subnet: " + subnetId.getValue());
143 Map<BigInteger, SubnetToDpn> subDpnMap = new HashMap<>();
144 BigInteger dpnId = null;
145 BigInteger nhDpnId = null;
146 SubnetToDpn subDpn = null;
148 SubnetOpDataEntryBuilder subOpBuilder =
149 new SubnetOpDataEntryBuilder().setKey(new SubnetOpDataEntryKey(subnetId));
150 subOpBuilder.setSubnetId(subnetId);
151 subOpBuilder.setSubnetCidr(subnetIp);
152 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
154 if (isBgpVpn && !VpnUtil.isBgpVpn(vpnName, primaryRd)) {
155 LOG.error("onSubnetAddedToVpn: The VPN Instance name " + vpnName + " does not have RD ");
159 subOpBuilder.setVrfId(primaryRd);
160 subOpBuilder.setVpnName(vpnName);
161 subOpBuilder.setSubnetToDpn(new ArrayList<>());
162 subOpBuilder.setRouteAdvState(TaskState.Na);
163 subOpBuilder.setElanTag(elanTag);
165 // First recover set of ports available in this subnet
166 List<Uuid> portList = subMap.getPortList();
167 if (portList != null) {
168 for (Uuid port: portList) {
169 Interface intfState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker,port.getValue());
170 if (intfState != null) {
172 dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
173 } catch (Exception e) {
174 LOG.error("onSubnetAddedToVpn: Unable to obtain dpnId for interface {},",
175 " subnetroute inclusion for this interface failed with exception {}",
179 if (dpnId.equals(BigInteger.ZERO)) {
180 LOG.info("onSubnetAddedToVpn: Port " + port.getValue()
181 + " is not assigned DPN yet, ignoring ");
184 subOpDpnManager.addPortOpDataEntry(port.getValue(), subnetId, dpnId);
185 if (intfState.getOperStatus() != OperStatus.Up) {
186 LOG.info("onSubnetAddedToVpn: Port " + port.getValue() + " is not UP yet, ignoring ");
189 subDpn = subOpDpnManager.addInterfaceToDpn(subnetId, dpnId, port.getValue());
190 if (intfState.getOperStatus() == OperStatus.Up) {
192 subDpnMap.put(dpnId, subDpn);
193 if (nhDpnId == null) {
198 subOpDpnManager.addPortOpDataEntry(port.getValue(), subnetId, null);
201 if (subDpnMap.size() > 0) {
202 subOpBuilder.setSubnetToDpn(new ArrayList<>(subDpnMap.values()));
206 if (nhDpnId != null) {
207 LOG.info("Next-Hop dpn {} is available for rd {} subnetIp {} vpn {}", nhDpnId, primaryRd,
209 subOpBuilder.setNhDpnId(nhDpnId);
212 Write the subnet route entry to the FIB.
213 And also advertise the subnet route entry via BGP.
215 int label = getLabel(primaryRd, subnetIp);
218 "Unable to fetch label from Id Manager. Bailing out of handling addition of subnet {}"
224 addSubnetRouteToFib(primaryRd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId,
225 isBgpVpn, subMap.getNetworkId().getValue());
226 if (isRouteAdvertised) {
227 subOpBuilder.setRouteAdvState(TaskState.Done);
229 subOpBuilder.setNhDpnId(null);
230 subOpBuilder.setRouteAdvState(TaskState.Na);
232 } catch (Exception ex) {
234 "onSubnetAddedToVpn: FIB rules and Advertising nhDpnId {} information for subnet {} to "
236 nhDpnId, subnetId.getValue(), ex);
237 subOpBuilder.setRouteAdvState(TaskState.Pending);
239 } else if (!isBgpVpn) {
240 addSubnetRouteToFib(primaryRd, subnetIp, null, vpnName, elanTag, 0, subnetId, false,
241 subMap.getNetworkId().getValue());
243 LOG.info("Next-Hop dpn is unavailable for rd {} subnetIp {} vpn {}", primaryRd, subnetIp, vpnName);
246 SubnetOpDataEntry subOpEntry = subOpBuilder.build();
247 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
248 LOG.info("onSubnetAddedToVpn: Added subnetopdataentry to OP Datastore for subnet {}",
249 subnetId.getValue());
250 } catch (Exception ex) {
251 LOG.error("Creation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
253 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
255 } catch (Exception e) {
256 LOG.error("Unable to handle subnet {} added to vpn {} {}", subnetIp, vpnName, e);
260 // TODO Clean up the exception handling
261 @SuppressWarnings("checkstyle:IllegalCatch")
262 public void onSubnetDeletedFromVpn(Subnetmap subnetmap, boolean isBgpVpn) {
263 Uuid subnetId = subnetmap.getId();
264 LOG.info("onSubnetDeletedFromVpn: Subnet " + subnetId.getValue() + " being removed from vpn");
265 //TODO(vivek): Change this to use more granularized lock at subnetId level
267 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
269 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
270 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
271 new SubnetOpDataEntryKey(subnetId)).build();
272 LOG.trace(" Removing the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
273 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
274 LogicalDatastoreType.OPERATIONAL,
276 if (!optionalSubs.isPresent()) {
277 LOG.error("onSubnetDeletedFromVpn: SubnetOpDataEntry for subnet {} not available in datastore",
278 subnetId.getValue());
282 /* If subnet is deleted (or if its removed from VPN), the ports that are DOWN on that subnet
283 * will continue to be stale in portOpData DS, as subDpnList used for portOpData removal will
284 * contain only ports that are UP. So here we explicitly cleanup the ports of the subnet by
285 * going through the list of ports on the subnet
287 InstanceIdentifier<Subnetmap> subMapid =
288 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
289 new SubnetmapKey(subnetId)).build();
290 Optional<Subnetmap> sm = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, subMapid);
291 if (!sm.isPresent()) {
292 LOG.error("Stale ports removal: Unable to retrieve subnetmap entry for subnet : " + subnetId);
294 Subnetmap subMap = sm.get();
295 List<Uuid> portList = subMap.getPortList();
296 if (portList != null) {
297 for (Uuid port : portList) {
298 InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
299 InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
300 new PortOpDataEntryKey(port.getValue())).build();
301 LOG.trace("Deleting portOpData entry for port " + port.getValue());
302 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
307 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
308 String rd = subOpBuilder.getVrfId();
309 String subnetIp = subOpBuilder.getSubnetCidr();
310 String vpnName = subOpBuilder.getVpnName();
311 BigInteger nhDpnId = subOpBuilder.getNhDpnId();
312 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier);
313 LOG.info("onSubnetDeletedFromVpn: Removed subnetopdataentry for subnet {} successfully from Datastore",
314 subnetId.getValue());
316 //Withdraw the routes for all the interfaces on this subnet
317 //Remove subnet route entry from FIB
318 deleteSubnetRouteFromFib(rd, subnetIp, vpnName, isBgpVpn);
319 } catch (Exception ex) {
320 LOG.error("onSubnetAddedToVpn: Withdrawing routes from BGP for subnet {} failed",
321 subnetId.getValue(), ex);
323 } catch (Exception ex) {
324 LOG.error("Removal of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
326 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
328 } catch (Exception e) {
329 LOG.error("Unable to handle subnet {} removed to vpn {}", subnetmap.getSubnetIp(),
330 subnetmap.getVpnId().getValue(), e);
334 public void onSubnetUpdatedInVpn(Subnetmap subnetmap, boolean isBgpVpn, Long elanTag) {
335 Uuid subnetId = subnetmap.getId();
336 String vpnName = subnetmap.getVpnId().getValue();
337 String subnetIp = subnetmap.getSubnetIp();
339 Preconditions.checkNotNull(subnetId, "SubnetId cannot be null or empty!");
340 Preconditions.checkNotNull(subnetIp, "SubnetPrefix cannot be null or empty!");
341 Preconditions.checkNotNull(vpnName, "VpnName cannot be null or empty!");
342 Preconditions.checkNotNull(elanTag, "ElanTag cannot be null or empty!");
344 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
345 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
346 new SubnetOpDataEntryKey(subnetId)).build();
347 Optional<SubnetOpDataEntry> optionalSubs =
348 VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier);
349 if (optionalSubs.isPresent()) {
351 onSubnetDeletedFromVpn(subnetmap, !isBgpVpn);
353 // TODO(vivek): Something got updated, but we donot know what ?
356 onSubnetAddedToVpn(subnetmap, isBgpVpn, elanTag);
358 // TODO(vivek): Something got updated, but we donot know what ?
362 // TODO Clean up the exception handling
363 @SuppressWarnings("checkstyle:IllegalCatch")
364 public void onPortAddedToSubnet(Subnetmap subnetmap, Uuid portId) {
365 Uuid subnetId = subnetmap.getId();
366 boolean isRouteAdvertised = false;
368 LOG.info("onPortAddedToSubnet: Port " + portId.getValue() + " being added to subnet " + subnetId.getValue());
369 //TODO(vivek): Change this to use more granularized lock at subnetId level
371 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
373 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
374 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
375 new SubnetOpDataEntryKey(subnetId)).build();
377 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
379 if (!optionalSubs.isPresent()) {
380 LOG.info("onPortAddedToSubnet: Port {} is part of a subnet {} that is not in VPN, ignoring",
381 portId.getValue(), subnetId.getValue());
384 Interface intfState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker,portId.getValue());
385 if (intfState == null) {
386 // Interface State not yet available
387 subOpDpnManager.addPortOpDataEntry(portId.getValue(), subnetId, null);
390 BigInteger dpnId = BigInteger.ZERO;
392 dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
393 } catch (Exception e) {
394 LOG.error("onSubnetAddedToVpn: Unable to obtain dpnId for interface {},",
395 " subnetroute inclusion for this interface failed with exception {}",
396 portId.getValue(), e);
399 if (dpnId.equals(BigInteger.ZERO)) {
400 LOG.info("onPortAddedToSubnet: Port " + portId.getValue() + " is not assigned DPN yet, ignoring ");
403 subOpDpnManager.addPortOpDataEntry(portId.getValue(), subnetId, dpnId);
404 if (intfState.getOperStatus() != OperStatus.Up) {
405 LOG.info("onPortAddedToSubnet: Port " + portId.getValue() + " is not UP yet, ignoring ");
408 LOG.debug("onPortAddedToSubnet: Updating the SubnetOpDataEntry node for subnet {}",
409 subnetId.getValue());
410 SubnetToDpn subDpn = subOpDpnManager.addInterfaceToDpn(subnetId, dpnId, portId.getValue());
411 if (subDpn == null) {
414 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
415 List<SubnetToDpn> subDpnList = subOpBuilder.getSubnetToDpn();
416 subDpnList.add(subDpn);
417 subOpBuilder.setSubnetToDpn(subDpnList);
418 if (subOpBuilder.getNhDpnId() == null) {
419 subOpBuilder.setNhDpnId(dpnId);
421 BigInteger nhDpnId = subOpBuilder.getNhDpnId();
422 String rd = subOpBuilder.getVrfId();
423 String subnetIp = subOpBuilder.getSubnetCidr();
424 String vpnName = subOpBuilder.getVpnName();
425 Long elanTag = subOpBuilder.getElanTag();
426 if ((subOpBuilder.getRouteAdvState() == TaskState.Pending)
427 || (subOpBuilder.getRouteAdvState() == TaskState.Na)) {
429 // Write the Subnet Route Entry to FIB
430 // Advertise BGP Route here and set route_adv_state to DONE
431 int label = getLabel(rd, subnetIp);
434 "Unable to fetch label from Id Manager. Bailing out of handling addition of port {} "
435 + "to subnet {} in vpn {}",
436 portId.getValue(), subnetIp, vpnName);
440 addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
441 if (isRouteAdvertised) {
442 subOpBuilder.setRouteAdvState(TaskState.Done);
444 subOpBuilder.setNhDpnId(null);
445 subOpBuilder.setRouteAdvState(TaskState.Na);
447 } catch (Exception ex) {
449 "onPortAddedToSubnet: Advertising NextHopDPN {} information for subnet {} to BGP failed",
450 nhDpnId, subnetId.getValue(), ex);
453 SubnetOpDataEntry subOpEntry = subOpBuilder.build();
454 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
455 LOG.info("onPortAddedToSubnet: Updated subnetopdataentry to OP Datastore for port {}",
458 } catch (Exception ex) {
459 LOG.error("Creation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
461 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
463 } catch (Exception e) {
464 LOG.error("Unable to handle port {} added to subnet {} {}", portId.getValue(), subnetId.getValue(), e);
468 // TODO Clean up the exception handling
469 @SuppressWarnings("checkstyle:IllegalCatch")
470 public void onPortRemovedFromSubnet(Subnetmap subnetmap, Uuid portId) {
471 Uuid subnetId = subnetmap.getId();
472 boolean isRouteAdvertised = false;
475 "onPortRemovedFromSubnet: Port " + portId.getValue() + " being removed from subnet " + subnetId.getValue());
476 //TODO(vivek): Change this to use more granularized lock at subnetId level
478 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
480 PortOpDataEntry portOpEntry = subOpDpnManager.removePortOpDataEntry(portId.getValue());
481 if (portOpEntry == null) {
484 BigInteger dpnId = portOpEntry.getDpnId();
486 LOG.debug("onPortRemovedFromSubnet: Port {} does not have a DPNId associated, ignoring",
491 "onPortRemovedFromSubnet: Updating the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
492 boolean last = subOpDpnManager.removeInterfaceFromDpn(subnetId, dpnId, portId.getValue());
493 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
494 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
495 new SubnetOpDataEntryKey(subnetId)).build();
496 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
498 if (!optionalSubs.isPresent()) {
499 LOG.info("onPortRemovedFromSubnet: Port {} is part of a subnet {} that is not in VPN, ignoring",
500 portId.getValue(), subnetId.getValue());
503 SubnetOpDataEntry subOpEntry = null;
504 List<SubnetToDpn> subDpnList = null;
505 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
506 String rd = subOpBuilder.getVrfId();
507 String subnetIp = subOpBuilder.getSubnetCidr();
508 String vpnName = subOpBuilder.getVpnName();
509 Long elanTag = subOpBuilder.getElanTag();
510 BigInteger nhDpnId = subOpBuilder.getNhDpnId();
511 if ((nhDpnId != null) && (nhDpnId.equals(dpnId))) {
512 // select another NhDpnId
514 LOG.debug("onPortRemovedFromSubnet: Last port {} on the subnet {}", portId,
515 subnetId.getValue());
516 // last port on this DPN, so we need to swap the NHDpnId
517 subDpnList = subOpBuilder.getSubnetToDpn();
518 if (subDpnList.isEmpty()) {
519 subOpBuilder.setNhDpnId(null);
521 // withdraw route from BGP
522 deleteSubnetRouteFromFib(rd, subnetIp, vpnName, true /* isBgpVpn*/);
523 subOpBuilder.setRouteAdvState(TaskState.Na);
524 } catch (Exception ex) {
526 "onPortRemovedFromSubnet: Withdrawing NextHopDPN {} information for subnet {} "
527 + "from BGP failed ",
528 dpnId, subnetId.getValue(), ex);
529 subOpBuilder.setRouteAdvState(TaskState.Pending);
532 nhDpnId = subDpnList.get(0).getDpnId();
533 subOpBuilder.setNhDpnId(nhDpnId);
534 LOG.debug("onInterfaceDown: Swapping the Designated DPN to {} for subnet {}", nhDpnId,
535 subnetId.getValue());
537 // Best effort Withdrawal of route from BGP for this subnet
538 // Advertise the new NexthopIP to BGP for this subnet
539 //withdrawSubnetRoutefromBgp(rd, subnetIp);
540 int label = getLabel(rd, subnetIp);
543 "Unable to fetch label from Id Manager. Bailing out of handling removal of "
544 + "port {} from subnet {} in vpn {}",
545 portId.getValue(), subnetIp, vpnName);
549 addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
550 if (isRouteAdvertised) {
551 subOpBuilder.setRouteAdvState(TaskState.Done);
553 subOpBuilder.setNhDpnId(null);
554 subOpBuilder.setRouteAdvState(TaskState.Na);
556 } catch (Exception ex) {
558 "onPortRemovedFromSubnet: Swapping Withdrawing NextHopDPN {} information for "
559 + "subnet {} to BGP failed",
560 dpnId, subnetId.getValue(), ex);
561 subOpBuilder.setRouteAdvState(TaskState.Pending);
566 subOpEntry = subOpBuilder.build();
567 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
569 "onPortRemovedFromSubnet: Updated subnetopdataentry to OP Datastore removing port " + portId
571 } catch (Exception ex) {
572 LOG.error("Creation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
574 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
576 } catch (Exception e) {
577 LOG.error("Unable to handle port {} removed from subnet {} {}", portId.getValue(), subnetId.getValue(),
582 // TODO Clean up the exception handling
583 @SuppressWarnings("checkstyle:IllegalCatch")
584 public void onInterfaceUp(BigInteger dpnId, String intfName) {
585 LOG.info("onInterfaceUp: Port " + intfName);
586 //TODO(vivek): Change this to use more granularized lock at subnetId level
587 SubnetToDpn subDpn = null;
588 boolean isRouteAdvertised = false;
589 PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(intfName);
590 if (portOpEntry == null) {
591 LOG.info("onInterfaceUp: Port " + intfName + "is part of a subnet not in VPN, ignoring");
594 if ((dpnId == null) || (Objects.equals(dpnId, BigInteger.ZERO))) {
595 dpnId = portOpEntry.getDpnId();
597 LOG.error("onInterfaceUp: Unable to determine the DPNID for port " + intfName);
601 Uuid subnetId = portOpEntry.getSubnetId();
603 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
605 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
606 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
607 new SubnetOpDataEntryKey(subnetId)).build();
608 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
610 if (!optionalSubs.isPresent()) {
611 LOG.error("onInterfaceUp: SubnetOpDataEntry for subnet {} is not available", subnetId.getValue());
615 LOG.debug("onInterfaceUp: Updating the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
616 subOpDpnManager.addPortOpDataEntry(intfName, subnetId, dpnId);
617 subDpn = subOpDpnManager.addInterfaceToDpn(subnetId, dpnId, intfName);
618 if (subDpn == null) {
621 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
622 List<SubnetToDpn> subDpnList = subOpBuilder.getSubnetToDpn();
623 subDpnList.add(subDpn);
624 subOpBuilder.setSubnetToDpn(subDpnList);
625 if (subOpBuilder.getNhDpnId() == null) {
626 subOpBuilder.setNhDpnId(dpnId);
628 BigInteger nhDpnId = subOpBuilder.getNhDpnId();
629 String rd = subOpBuilder.getVrfId();
630 String subnetIp = subOpBuilder.getSubnetCidr();
631 String vpnName = subOpBuilder.getVpnName();
632 Long elanTag = subOpBuilder.getElanTag();
633 if ((subOpBuilder.getRouteAdvState() == TaskState.Pending)
634 || (subOpBuilder.getRouteAdvState() == TaskState.Na)) {
636 // Write the Subnet Route Entry to FIB
637 // Advertise BGP Route here and set route_adv_state to DONE
638 int label = getLabel(rd, subnetIp);
641 "Unable to fetch label from Id Manager. Bailing out of handling interface up event "
642 + "for port {} for subnet {} in vpn {}",
643 intfName, subnetIp, vpnName);
647 addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
648 if (isRouteAdvertised) {
649 subOpBuilder.setRouteAdvState(TaskState.Done);
651 subOpBuilder.setNhDpnId(null);
652 subOpBuilder.setRouteAdvState(TaskState.Na);
654 } catch (Exception ex) {
655 LOG.error("onInterfaceUp: Advertising NextHopDPN {} information for subnet {} to BGP failed",
656 nhDpnId, subnetId.getValue(), ex);
659 SubnetOpDataEntry subOpEntry = subOpBuilder.build();
660 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
661 LOG.info("onInterfaceUp: Updated subnetopdataentry to OP Datastore port up " + intfName);
662 } catch (Exception ex) {
663 LOG.error("Creation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
665 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
667 } catch (Exception e) {
668 LOG.error("Unable to handle interface up event for port {} in subnet {} {}", portOpEntry.getPortId(),
669 subnetId.getValue(), e);
673 // TODO Clean up the exception handling
674 @SuppressWarnings("checkstyle:IllegalCatch")
675 public void onInterfaceDown(final BigInteger dpnId, final String interfaceName) {
676 boolean isRouteAdvertised = false;
677 LOG.info("onInterfaceDown: Port " + interfaceName);
678 //TODO(vivek): Change this to use more granularized lock at subnetId level
679 PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(interfaceName);
680 if (portOpEntry == null) {
681 LOG.info("onInterfaceDown: Port " + interfaceName + "is part of a subnet not in VPN, ignoring");
684 if ((dpnId == null) || (Objects.equals(dpnId, BigInteger.ZERO))) {
685 LOG.error("onInterfaceDown: Unable to determine the DPNID for port " + interfaceName);
688 Uuid subnetId = portOpEntry.getSubnetId();
690 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
692 LOG.debug("onInterfaceDown: Updating the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
693 boolean last = subOpDpnManager.removeInterfaceFromDpn(subnetId, dpnId, interfaceName);
694 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
695 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
696 new SubnetOpDataEntryKey(subnetId)).build();
697 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
698 LogicalDatastoreType.OPERATIONAL,
700 if (!optionalSubs.isPresent()) {
701 LOG.error("onInterfaceDown: SubnetOpDataEntry for subnet {} is not available", subnetId.getValue());
704 SubnetOpDataEntry subOpEntry = null;
705 List<SubnetToDpn> subDpnList = null;
706 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
707 String rd = subOpBuilder.getVrfId();
708 String subnetIp = subOpBuilder.getSubnetCidr();
709 String vpnName = subOpBuilder.getVpnName();
710 Long elanTag = subOpBuilder.getElanTag();
711 BigInteger nhDpnId = subOpBuilder.getNhDpnId();
712 if ((nhDpnId != null) && (nhDpnId.equals(dpnId))) {
713 // select another NhDpnId
716 "onInterfaceDown: Last active port " + interfaceName + " on the subnet: " + subnetId
718 // last port on this DPN, so we need to swap the NHDpnId
719 subDpnList = subOpBuilder.getSubnetToDpn();
720 if (subDpnList.isEmpty()) {
721 subOpBuilder.setNhDpnId(null);
723 // Withdraw route from BGP for this subnet
724 deleteSubnetRouteFromFib(rd, subnetIp, vpnName, true /* isBgpVpn*/);
725 subOpBuilder.setRouteAdvState(TaskState.Na);
726 } catch (Exception ex) {
728 "onInterfaceDown: Withdrawing NextHopDPN {} information for subnet {} from BGP "
730 dpnId, subnetId.getValue(), ex);
731 subOpBuilder.setRouteAdvState(TaskState.Pending);
734 nhDpnId = subDpnList.get(0).getDpnId();
735 subOpBuilder.setNhDpnId(nhDpnId);
737 "onInterfaceDown: Swapping the Designated DPN to {} for subnet {}" , nhDpnId,
738 subnetId.getValue());
740 // Best effort Withdrawal of route from BGP for this subnet
741 //withdrawSubnetRoutefromBgp(rd, subnetIp);
742 int label = getLabel(rd, subnetIp);
745 "Unable to fetch label from Id Manager. Bailing out of handling interface "
746 + "down event for port {} in subnet {} for vpn {}",
747 interfaceName, subnetIp, vpnName);
751 addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
752 if (isRouteAdvertised) {
753 subOpBuilder.setRouteAdvState(TaskState.Done);
755 subOpBuilder.setNhDpnId(null);
756 subOpBuilder.setRouteAdvState(TaskState.Na);
758 } catch (Exception ex) {
760 "onInterfaceDown: Swapping Withdrawing NextHopDPN {} information for "
761 + "subnet {} to BGP failed", dpnId, subnetId.getValue(), ex);
762 subOpBuilder.setRouteAdvState(TaskState.Pending);
767 subOpEntry = subOpBuilder.build();
768 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
769 LOG.info("onInterfaceDown: Updated subnetopdataentry to OP Datastore port down " + interfaceName);
770 } catch (Exception ex) {
771 LOG.error("Creation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
773 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
775 } catch (Exception e) {
776 LOG.error("Unable to handle interface down event for port {} in subnet {} {}", portOpEntry.getPortId(),
777 subnetId.getValue(), e);
781 // TODO Clean up the exception handling
782 @SuppressWarnings("checkstyle:IllegalCatch")
783 public void updateSubnetRouteOnTunnelUpEvent(Uuid subnetId, BigInteger dpnId) {
784 boolean isRouteAdvertised = false;
785 LOG.info("updateSubnetRouteOnTunnelUpEvent: Subnet {} Dpn {}", subnetId.getValue(), dpnId.toString());
787 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
789 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
790 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
791 new SubnetOpDataEntryKey(subnetId)).build();
792 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
793 LogicalDatastoreType.OPERATIONAL,
795 if (!optionalSubs.isPresent()) {
796 LOG.error("updateSubnetRouteOnTunnelUpEvent: SubnetOpDataEntry for subnet {} is not available",
797 subnetId.getValue());
800 SubnetOpDataEntry subOpEntry = null;
801 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
802 String rd = subOpBuilder.getVrfId();
803 String subnetIp = subOpBuilder.getSubnetCidr();
804 String vpnName = subOpBuilder.getVpnName();
805 List<SubnetToDpn> subDpnList = subOpBuilder.getSubnetToDpn();
806 long elanTag = subOpBuilder.getElanTag();
807 if ((subOpBuilder.getRouteAdvState() == TaskState.Pending)
808 || (subOpBuilder.getRouteAdvState() == TaskState.Na)) {
809 for (SubnetToDpn subDpn : subDpnList) {
810 if (subDpn.getDpnId().equals(dpnId)) {
811 if (subOpBuilder.getNhDpnId() == null) {
813 subOpBuilder.setNhDpnId(dpnId);
814 int label = getLabel(rd, subnetIp);
816 addSubnetRouteToFib(rd, subnetIp, dpnId, vpnName, elanTag, label, subnetId);
817 if (isRouteAdvertised) {
818 subOpBuilder.setRouteAdvState(TaskState.Done);
820 subOpBuilder.setNhDpnId(null);
821 subOpBuilder.setRouteAdvState(TaskState.Na);
823 } catch (Exception ex) {
825 "updateSubnetRouteOnTunnelUpEvent: Advertising NextHopDPN {} information for "
826 + "subnet {} to BGP failed",
827 dpnId, subnetId.getValue(), ex);
832 subOpEntry = subOpBuilder.build();
833 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
835 "updateSubnetRouteOnTunnelUpEvent: Updated subnetopdataentry to OP Datastore tunnel up on dpn"
836 + " {} for subnet {}",
837 dpnId.toString(), subnetId.getValue());
839 } catch (Exception ex) {
840 LOG.error("Creation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
842 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
844 } catch (Exception e) {
845 LOG.error("Unable to handle tunnel up event for subnetId {} dpnId {}", subnetId.getValue(),
850 // TODO Clean up the exception handling
851 @SuppressWarnings("checkstyle:IllegalCatch")
852 public void updateSubnetRouteOnTunnelDownEvent(Uuid subnetId, BigInteger dpnId) {
853 LOG.info("updateSubnetRouteOnTunnelDownEvent: Subnet {} Dpn {}", subnetId.getValue(), dpnId.toString());
854 //TODO(vivek): Change this to use more granularized lock at subnetId level
856 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
858 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
859 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
860 new SubnetOpDataEntryKey(subnetId)).build();
861 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
862 LogicalDatastoreType.OPERATIONAL,
864 if (!optionalSubs.isPresent()) {
865 LOG.error("updateSubnetRouteOnTunnelDownEvent: SubnetOpDataEntry for subnet {} is not available",
866 subnetId.getValue());
869 SubnetOpDataEntry subOpEntry = null;
870 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
871 BigInteger nhDpnId = subOpBuilder.getNhDpnId();
872 if ((nhDpnId != null) && (nhDpnId.equals(dpnId))) {
873 electNewDPNForSubNetRoute(subOpBuilder, dpnId, subnetId);
874 subOpEntry = subOpBuilder.build();
875 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
877 "updateSubnetRouteOnTunnelDownEvent: Updated subnetopdataentry to OP Datastore tunnnel down "
878 + "on dpn {} for subnet {}",
879 dpnId.toString(), subnetId.getValue());
881 } catch (Exception ex) {
882 LOG.error("Updation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
884 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
886 } catch (Exception e) {
887 LOG.error("Unable to handle tunnel down event for subnetId {} dpnId {}", subnetId.getValue(),
892 private boolean addSubnetRouteToFib(String rd, String subnetIp, BigInteger nhDpnId, String vpnName,
893 Long elanTag, int label, Uuid subnetId) throws Exception {
894 return addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId,
895 true /* isBgpVpn*/, null /* networkId */);
898 // TODO Clean up the exception handling
899 @SuppressWarnings("checkstyle:IllegalCatch")
900 private boolean addSubnetRouteToFib(String rd, String subnetIp, BigInteger nhDpnId, String vpnName,
901 Long elanTag, int label, Uuid subnetId, boolean isBgpVpn, String networkName) throws Exception {
903 Preconditions.checkNotNull(rd, "RouteDistinguisher cannot be null or empty!");
904 Preconditions.checkNotNull(subnetIp, "SubnetRouteIp cannot be null or empty!");
905 Preconditions.checkNotNull(vpnName, "vpnName cannot be null or empty!");
906 Preconditions.checkNotNull(elanTag, "elanTag cannot be null or empty!");
908 String nexthopIp = null;
910 LOG.info("Adding SubnetRoute fib entry for vpnName {}, subnetIP {}, elanTag {}",
911 vpnName, subnetIp, elanTag);
912 vpnInterfaceManager.addSubnetRouteFibEntryToDS(rd, vpnName, subnetIp, nexthopIp, label, elanTag, nhDpnId,
913 networkName, null /* WriteTransaction */);
918 nexthopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, nhDpnId);
919 } catch (Exception e) {
920 LOG.warn("Unable to find nexthopip for subnetroute subnetip {}", subnetIp);
923 if (nexthopIp != null) {
924 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
925 VpnUtil.getPrefixToInterfaceIdentifier(VpnUtil.getVpnId(dataBroker, vpnName), subnetIp),
926 VpnUtil.getPrefixToInterface(nhDpnId, subnetId.getValue(), subnetIp, subnetId, true /* isNatPrefix*/));
927 vpnInterfaceManager.addSubnetRouteFibEntryToDS(rd, vpnName, subnetIp, nexthopIp, label, elanTag, nhDpnId,
930 // BGP manager will handle withdraw and advertise internally if prefix
932 bgpManager.advertisePrefix(rd, null /*macAddress*/, subnetIp, Collections.singletonList(nexthopIp),
933 VrfEntry.EncapType.Mplsgre, label, 0 /*l3vni*/, 0 /*l2vni*/, null /*gatewayMacAddress*/);
934 } catch (Exception e) {
935 LOG.error("Fail: Subnet route not advertised for rd {} subnetIp {}", rd, subnetIp, e);
939 LOG.warn("The nexthopip is empty for subnetroute subnetip {}, ignoring fib route addition", subnetIp);
945 private int getLabel(String rd, String subnetIp) {
946 int label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
947 VpnUtil.getNextHopLabelKey(rd, subnetIp));
948 LOG.trace("Allocated subnetroute label {} for rd {} prefix {}", label, rd, subnetIp);
952 // TODO Clean up the exception handling
953 @SuppressWarnings("checkstyle:IllegalCatch")
954 private void deleteSubnetRouteFromFib(String rd, String subnetIp, String vpnName, boolean isBgpVpn)
956 Preconditions.checkNotNull(rd, "RouteDistinguisher cannot be null or empty!");
957 Preconditions.checkNotNull(subnetIp, "SubnetRouteIp cannot be null or empty!");
958 vpnInterfaceManager.deleteSubnetRouteFibEntryFromDS(rd, subnetIp, vpnName);
961 bgpManager.withdrawPrefix(rd, subnetIp);
962 } catch (Exception e) {
963 LOG.error("Fail: Subnet route not withdrawn for rd {} subnetIp {}", rd, subnetIp, e);
969 // TODO Clean up the exception handling
970 @SuppressWarnings("checkstyle:IllegalCatch")
971 private void electNewDPNForSubNetRoute(SubnetOpDataEntryBuilder subOpBuilder, BigInteger dpnId, Uuid subnetId) {
972 List<SubnetToDpn> subDpnList = null;
973 boolean isRouteAdvertised = false;
974 subDpnList = subOpBuilder.getSubnetToDpn();
975 String rd = subOpBuilder.getVrfId();
976 String subnetIp = subOpBuilder.getSubnetCidr();
977 String vpnName = subOpBuilder.getVpnName();
978 long elanTag = subOpBuilder.getElanTag();
979 BigInteger nhDpnId = null;
980 boolean isAlternateDpnSelected = false;
981 Iterator<SubnetToDpn> subNetIt = subDpnList.iterator();
982 int label = getLabel(rd, subnetIp);
983 while (subNetIt.hasNext()) {
984 SubnetToDpn subnetToDpn = subNetIt.next();
985 nhDpnId = subnetToDpn.getDpnId();
986 if (!nhDpnId.equals(dpnId)) {
988 //update the VRF entry for the subnetroute.
989 isRouteAdvertised = addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
990 if (isRouteAdvertised) {
991 subOpBuilder.setRouteAdvState(TaskState.Done);
992 subOpBuilder.setNhDpnId(nhDpnId);
993 isAlternateDpnSelected = true;
996 } catch (Exception ex) {
998 "electNewDPNForSubNetRoute: Swapping and trying to configure NextHopDPN {} for subnet {} "
1000 dpnId.toString(), subnetId.getValue(), ex);
1001 subOpBuilder.setRouteAdvState(TaskState.Na);
1006 //If no alternate Dpn is selected as nextHopDpn ,withdraw the subnetroute.
1007 if (!isAlternateDpnSelected) {
1008 LOG.info("No alternate DPN available for subnet {}.Prefix withdrawn from BGP", subnetIp);
1010 // Withdraw route from BGP for this subnet
1011 deleteSubnetRouteFromFib(rd, subnetIp, vpnName, true /* isBgpVpn*/);
1012 subOpBuilder.setNhDpnId(null);
1013 subOpBuilder.setRouteAdvState(TaskState.Na);
1014 } catch (Exception ex) {
1016 "electNewDPNForSubNetRoute: Withdrawing NextHopDPN " + dpnId.toString() + " information for subnet "
1018 subnetId.getValue() + " from BGP failed {}" + ex);
1019 subOpBuilder.setRouteAdvState(TaskState.Pending);