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.Arrays;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.List;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.genius.mdsalutil.MDSALUtil;
22 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
23 import org.opendaylight.netvirt.vpnmanager.VpnOpDataSyncer.VpnOpDataType;
24 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpData;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.SubnetOpData;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.TaskState;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpn;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnListener;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.PortAddedToSubnet;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.PortRemovedFromSubnet;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetAddedToVpn;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetAddedToVpnBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetDeletedFromVpn;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetDeletedFromVpnBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetUpdatedInVpn;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
55 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
59 public class VpnSubnetRouteHandler implements NeutronvpnListener {
60 private static final Logger LOG = LoggerFactory.getLogger(VpnSubnetRouteHandler.class);
61 private final DataBroker dataBroker;
62 private final SubnetOpDpnManager subOpDpnManager;
63 private final IBgpManager bgpManager;
64 private final VpnInterfaceManager vpnInterfaceManager;
65 private final IdManagerService idManager;
66 private LockManagerService lockManager;
67 private final VpnOpDataSyncer vpnOpDataSyncer;
69 public VpnSubnetRouteHandler(final DataBroker dataBroker, final SubnetOpDpnManager subnetOpDpnManager,
70 final IBgpManager bgpManager, final VpnInterfaceManager vpnIntfManager, final IdManagerService idManager,
71 LockManagerService lockManagerService, final VpnOpDataSyncer vpnOpDataSyncer) {
72 this.dataBroker = dataBroker;
73 this.subOpDpnManager = subnetOpDpnManager;
74 this.bgpManager = bgpManager;
75 this.vpnInterfaceManager = vpnIntfManager;
76 this.idManager = idManager;
77 this.lockManager = lockManagerService;
78 this.vpnOpDataSyncer = vpnOpDataSyncer;
81 // TODO Clean up the exception handling
82 @SuppressWarnings("checkstyle:IllegalCatch")
84 public void onSubnetAddedToVpn(SubnetAddedToVpn notification) {
85 if (!notification.isExternalVpn()) {
89 Uuid subnetId = notification.getSubnetId();
90 String vpnName = notification.getVpnName();
91 String subnetIp = notification.getSubnetIp();
92 Long elanTag = notification.getElanTag();
93 boolean isRouteAdvertised = false;
95 Preconditions.checkNotNull(subnetId, "SubnetId cannot be null or empty!");
96 Preconditions.checkNotNull(subnetIp, "SubnetPrefix cannot be null or empty!");
97 Preconditions.checkNotNull(vpnName, "VpnName cannot be null or empty!");
98 Preconditions.checkNotNull(elanTag, "ElanTag cannot be null or empty!");
100 LOG.info("onSubnetAddedToVpn: Subnet {} being added to vpn", subnetId.getValue());
101 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
102 if (vpnId == VpnConstants.INVALID_ID) {
103 vpnOpDataSyncer.waitForVpnDataReady(VpnOpDataType.vpnInstanceToId, vpnName,
104 VpnConstants.PER_VPN_INSTANCE_MAX_WAIT_TIME_IN_MILLISECONDS);
105 vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
106 if (vpnId == VpnConstants.INVALID_ID) {
108 "onSubnetAddedToVpn: VpnInstance to VPNId mapping not yet available for VpnName {} processing "
109 + "subnet {} with IP {}, bailing out now.", vpnName, subnetId, subnetIp);
113 //TODO(vivek): Change this to use more granularized lock at subnetId level
115 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
117 Subnetmap subMap = null;
119 // Please check if subnetId belongs to an External Network
120 InstanceIdentifier<Subnetmap> subMapid =
121 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
122 new SubnetmapKey(subnetId)).build();
123 Optional<Subnetmap> sm = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, subMapid);
124 if (!sm.isPresent()) {
125 LOG.error("onSubnetAddedToVpn: Unable to retrieve subnetmap entry for subnet : " + subnetId);
129 InstanceIdentifier<Networks> netsIdentifier =
130 InstanceIdentifier.builder(ExternalNetworks.class).child(Networks.class,
131 new NetworksKey(subMap.getNetworkId())).build();
132 Optional<Networks> optionalNets =
133 VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, netsIdentifier);
134 if (optionalNets.isPresent()) {
136 "onSubnetAddedToVpn: subnet {} is an external subnet on external network {}, so ignoring this"
137 + " for SubnetRoute", subnetId.getValue(), subMap.getNetworkId().getValue());
140 //Create and add SubnetOpDataEntry object for this subnet to the SubnetOpData container
141 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
142 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
143 new SubnetOpDataEntryKey(subnetId)).build();
144 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
145 LogicalDatastoreType.OPERATIONAL,
147 if (optionalSubs.isPresent()) {
148 LOG.error("onSubnetAddedToVpn: SubnetOpDataEntry for subnet {} already detected to be present",
149 subnetId.getValue());
152 LOG.debug("onSubnetAddedToVpn: Creating new SubnetOpDataEntry node for subnet: " + subnetId.getValue());
153 Map<BigInteger, SubnetToDpn> subDpnMap = new HashMap<BigInteger, SubnetToDpn>();
154 BigInteger dpnId = null;
155 BigInteger nhDpnId = null;
156 SubnetToDpn subDpn = null;
158 SubnetOpDataEntryBuilder subOpBuilder =
159 new SubnetOpDataEntryBuilder().setKey(new SubnetOpDataEntryKey(subnetId));
160 subOpBuilder.setSubnetId(subnetId);
161 subOpBuilder.setSubnetCidr(subnetIp);
162 String rd = VpnUtil.getVpnRdFromVpnInstanceConfig(dataBroker, vpnName);
164 LOG.error("onSubnetAddedToVpn: The VPN Instance name {} does not have RD",
165 notification.getVpnName());
168 subOpBuilder.setVrfId(rd);
169 subOpBuilder.setVpnName(vpnName);
170 subOpBuilder.setSubnetToDpn(new ArrayList<SubnetToDpn>());
171 subOpBuilder.setRouteAdvState(TaskState.Na);
172 subOpBuilder.setElanTag(elanTag);
174 // First recover set of ports available in this subnet
175 List<Uuid> portList = subMap.getPortList();
176 if (portList != null) {
177 for (Uuid port: portList) {
178 Interface intfState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker,port.getValue());
179 if (intfState != null) {
181 dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
182 } catch (Exception e) {
183 LOG.error("onSubnetAddedToVpn: Unable to obtain dpnId for interface {},",
184 " subnetroute inclusion for this interface failed with exception {}",
188 if (dpnId.equals(BigInteger.ZERO)) {
189 LOG.info("onSubnetAddedToVpn: Port " + port.getValue()
190 + " is not assigned DPN yet, ignoring ");
193 subOpDpnManager.addPortOpDataEntry(port.getValue(), subnetId, dpnId);
194 if (intfState.getOperStatus() != OperStatus.Up) {
195 LOG.info("onSubnetAddedToVpn: Port " + port.getValue() + " is not UP yet, ignoring ");
198 subDpn = subOpDpnManager.addInterfaceToDpn(subnetId, dpnId, port.getValue());
199 if (intfState.getOperStatus() == OperStatus.Up) {
201 subDpnMap.put(dpnId, subDpn);
202 if (nhDpnId == null) {
207 subOpDpnManager.addPortOpDataEntry(port.getValue(), subnetId, null);
210 if (subDpnMap.size() > 0) {
211 subOpBuilder.setSubnetToDpn(new ArrayList<SubnetToDpn>(subDpnMap.values()));
215 if (nhDpnId != null) {
216 LOG.info("Next-Hop dpn {} is available for rd {} subnetIp {} vpn {}", nhDpnId, rd, subnetIp,
218 subOpBuilder.setNhDpnId(nhDpnId);
221 Write the subnet route entry to the FIB.
222 And also advertise the subnet route entry via BGP.
224 int label = getLabel(rd, subnetIp);
227 "Unable to fetch label from Id Manager. Bailing out of handling addition of subnet {}"
233 addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
234 if (isRouteAdvertised) {
235 subOpBuilder.setRouteAdvState(TaskState.Done);
237 subOpBuilder.setNhDpnId(null);
238 subOpBuilder.setRouteAdvState(TaskState.Na);
240 } catch (Exception ex) {
242 "onSubnetAddedToVpn: FIB rules and Advertising nhDpnId {} information for subnet {} to "
244 nhDpnId, subnetId.getValue(), ex);
245 subOpBuilder.setRouteAdvState(TaskState.Pending);
248 LOG.info("Next-Hop dpn is unavailable for rd {} subnetIp {} vpn {}", rd, subnetIp, vpnName);
251 SubnetOpDataEntry subOpEntry = subOpBuilder.build();
252 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
253 LOG.info("onSubnetAddedToVpn: Added subnetopdataentry to OP Datastore for subnet {}",
254 subnetId.getValue());
255 } catch (Exception ex) {
256 LOG.error("Creation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
258 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
260 } catch (Exception e) {
261 LOG.error("Unable to handle subnet {} added to vpn {} {}", subnetIp, vpnName, e);
265 // TODO Clean up the exception handling
266 @SuppressWarnings("checkstyle:IllegalCatch")
268 public void onSubnetDeletedFromVpn(SubnetDeletedFromVpn notification) {
269 Uuid subnetId = notification.getSubnetId();
271 if (!notification.isExternalVpn()) {
274 LOG.info("onSubnetDeletedFromVpn: Subnet " + subnetId.getValue() + " being removed from vpn");
275 //TODO(vivek): Change this to use more granularized lock at subnetId level
277 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
279 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
280 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
281 new SubnetOpDataEntryKey(subnetId)).build();
282 LOG.trace(" Removing the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
283 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
284 LogicalDatastoreType.OPERATIONAL,
286 if (!optionalSubs.isPresent()) {
287 LOG.error("onSubnetDeletedFromVpn: SubnetOpDataEntry for subnet {} not available in datastore",
288 subnetId.getValue());
292 /* If subnet is deleted (or if its removed from VPN), the ports that are DOWN on that subnet
293 * will continue to be stale in portOpData DS, as subDpnList used for portOpData removal will
294 * contain only ports that are UP. So here we explicitly cleanup the ports of the subnet by
295 * going through the list of ports on the subnet
297 InstanceIdentifier<Subnetmap> subMapid =
298 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
299 new SubnetmapKey(subnetId)).build();
300 Optional<Subnetmap> sm = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, subMapid);
301 if (!sm.isPresent()) {
302 LOG.error("Stale ports removal: Unable to retrieve subnetmap entry for subnet : " + subnetId);
304 Subnetmap subMap = sm.get();
305 List<Uuid> portList = subMap.getPortList();
306 if (portList != null) {
307 for (Uuid port : portList) {
308 InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
309 InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
310 new PortOpDataEntryKey(port.getValue())).build();
311 LOG.trace("Deleting portOpData entry for port " + port.getValue());
312 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
317 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
318 String rd = subOpBuilder.getVrfId();
319 String subnetIp = subOpBuilder.getSubnetCidr();
320 String vpnName = subOpBuilder.getVpnName();
321 BigInteger nhDpnId = subOpBuilder.getNhDpnId();
322 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier);
323 LOG.info("onSubnetDeletedFromVpn: Removed subnetopdataentry for subnet {} successfully from Datastore",
324 subnetId.getValue());
326 //Withdraw the routes for all the interfaces on this subnet
327 //Remove subnet route entry from FIB
328 deleteSubnetRouteFromFib(rd, subnetIp, vpnName);
329 } catch (Exception ex) {
330 LOG.error("onSubnetAddedToVpn: Withdrawing routes from BGP for subnet {} failed",
331 subnetId.getValue(), ex);
333 } catch (Exception ex) {
334 LOG.error("Removal of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
336 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
338 } catch (Exception e) {
339 LOG.error("Unable to handle subnet {} removed to vpn {}", notification.getSubnetIp(),
340 notification.getVpnName(), e);
345 public void onSubnetUpdatedInVpn(SubnetUpdatedInVpn notification) {
346 Uuid subnetId = notification.getSubnetId();
347 String vpnName = notification.getVpnName();
348 String subnetIp = notification.getSubnetIp();
349 Long elanTag = notification.getElanTag();
351 Preconditions.checkNotNull(subnetId, "SubnetId cannot be null or empty!");
352 Preconditions.checkNotNull(subnetIp, "SubnetPrefix cannot be null or empty!");
353 Preconditions.checkNotNull(vpnName, "VpnName cannot be null or empty!");
354 Preconditions.checkNotNull(elanTag, "ElanTag cannot be null or empty!");
356 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
357 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
358 new SubnetOpDataEntryKey(subnetId)).build();
359 Optional<SubnetOpDataEntry> optionalSubs =
360 VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier);
361 if (optionalSubs.isPresent()) {
362 if (!notification.isExternalVpn()) {
363 SubnetDeletedFromVpnBuilder bldr = new SubnetDeletedFromVpnBuilder().setVpnName(vpnName);
364 bldr.setElanTag(elanTag).setExternalVpn(true).setSubnetIp(subnetIp).setSubnetId(subnetId);
365 onSubnetDeletedFromVpn(bldr.build());
367 // TODO(vivek): Something got updated, but we donot know what ?
369 if (notification.isExternalVpn()) {
370 SubnetAddedToVpnBuilder bldr = new SubnetAddedToVpnBuilder().setVpnName(vpnName).setElanTag(elanTag);
371 bldr.setSubnetIp(subnetIp).setSubnetId(subnetId).setExternalVpn(true);
372 onSubnetAddedToVpn(bldr.build());
374 // TODO(vivek): Something got updated, but we donot know what ?
378 // TODO Clean up the exception handling
379 @SuppressWarnings("checkstyle:IllegalCatch")
381 public void onPortAddedToSubnet(PortAddedToSubnet notification) {
382 Uuid subnetId = notification.getSubnetId();
383 Uuid portId = notification.getPortId();
384 boolean isRouteAdvertised = false;
386 LOG.info("onPortAddedToSubnet: Port " + portId.getValue() + " being added to subnet " + subnetId.getValue());
387 //TODO(vivek): Change this to use more granularized lock at subnetId level
389 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
391 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
392 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
393 new SubnetOpDataEntryKey(subnetId)).build();
395 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
397 if (!optionalSubs.isPresent()) {
398 LOG.info("onPortAddedToSubnet: Port {} is part of a subnet {} that is not in VPN, ignoring",
399 portId.getValue(), subnetId.getValue());
402 Interface intfState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker,portId.getValue());
403 if (intfState == null) {
404 // Interface State not yet available
405 subOpDpnManager.addPortOpDataEntry(portId.getValue(), subnetId, null);
408 BigInteger dpnId = BigInteger.ZERO;
410 dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
411 } catch (Exception e) {
412 LOG.error("onSubnetAddedToVpn: Unable to obtain dpnId for interface {},",
413 " subnetroute inclusion for this interface failed with exception {}",
414 portId.getValue(), e);
417 if (dpnId.equals(BigInteger.ZERO)) {
418 LOG.info("onPortAddedToSubnet: Port " + portId.getValue() + " is not assigned DPN yet, ignoring ");
421 subOpDpnManager.addPortOpDataEntry(portId.getValue(), subnetId, dpnId);
422 if (intfState.getOperStatus() != OperStatus.Up) {
423 LOG.info("onPortAddedToSubnet: Port " + portId.getValue() + " is not UP yet, ignoring ");
426 LOG.debug("onPortAddedToSubnet: Updating the SubnetOpDataEntry node for subnet {}",
427 subnetId.getValue());
428 SubnetToDpn subDpn = subOpDpnManager.addInterfaceToDpn(subnetId, dpnId, portId.getValue());
429 if (subDpn == null) {
432 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
433 List<SubnetToDpn> subDpnList = subOpBuilder.getSubnetToDpn();
434 subDpnList.add(subDpn);
435 subOpBuilder.setSubnetToDpn(subDpnList);
436 if (subOpBuilder.getNhDpnId() == null) {
437 subOpBuilder.setNhDpnId(dpnId);
439 BigInteger nhDpnId = subOpBuilder.getNhDpnId();
440 String rd = subOpBuilder.getVrfId();
441 String subnetIp = subOpBuilder.getSubnetCidr();
442 String vpnName = subOpBuilder.getVpnName();
443 Long elanTag = subOpBuilder.getElanTag();
444 if ((subOpBuilder.getRouteAdvState() == TaskState.Pending)
445 || (subOpBuilder.getRouteAdvState() == TaskState.Na)) {
447 // Write the Subnet Route Entry to FIB
448 // Advertise BGP Route here and set route_adv_state to DONE
449 int label = getLabel(rd, subnetIp);
452 "Unable to fetch label from Id Manager. Bailing out of handling addition of port {} "
453 + "to subnet {} in vpn {}",
454 portId.getValue(), subnetIp, vpnName);
458 addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
459 if (isRouteAdvertised) {
460 subOpBuilder.setRouteAdvState(TaskState.Done);
462 subOpBuilder.setNhDpnId(null);
463 subOpBuilder.setRouteAdvState(TaskState.Na);
465 } catch (Exception ex) {
467 "onPortAddedToSubnet: Advertising NextHopDPN {} information for subnet {} to BGP failed",
468 nhDpnId, subnetId.getValue(), ex);
471 SubnetOpDataEntry subOpEntry = subOpBuilder.build();
472 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
473 LOG.info("onPortAddedToSubnet: Updated subnetopdataentry to OP Datastore for port {}",
476 } catch (Exception ex) {
477 LOG.error("Creation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
479 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
481 } catch (Exception e) {
482 LOG.error("Unable to handle port {} added to subnet {} {}", portId.getValue(), subnetId.getValue(), e);
486 // TODO Clean up the exception handling
487 @SuppressWarnings("checkstyle:IllegalCatch")
489 public void onPortRemovedFromSubnet(PortRemovedFromSubnet notification) {
490 Uuid subnetId = notification.getSubnetId();
491 Uuid portId = notification.getPortId();
492 boolean isRouteAdvertised = false;
495 "onPortRemovedFromSubnet: Port " + portId.getValue() + " being removed from subnet " + subnetId.getValue());
496 //TODO(vivek): Change this to use more granularized lock at subnetId level
498 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
500 PortOpDataEntry portOpEntry = subOpDpnManager.removePortOpDataEntry(portId.getValue());
501 if (portOpEntry == null) {
504 BigInteger dpnId = portOpEntry.getDpnId();
506 LOG.debug("onPortRemovedFromSubnet: Port {} does not have a DPNId associated, ignoring",
511 "onPortRemovedFromSubnet: Updating the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
512 boolean last = subOpDpnManager.removeInterfaceFromDpn(subnetId, dpnId, portId.getValue());
513 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
514 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
515 new SubnetOpDataEntryKey(subnetId)).build();
516 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
518 if (!optionalSubs.isPresent()) {
519 LOG.info("onPortRemovedFromSubnet: Port {} is part of a subnet {} that is not in VPN, ignoring",
520 portId.getValue(), subnetId.getValue());
523 SubnetOpDataEntry subOpEntry = null;
524 List<SubnetToDpn> subDpnList = null;
525 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
526 String rd = subOpBuilder.getVrfId();
527 String subnetIp = subOpBuilder.getSubnetCidr();
528 String vpnName = subOpBuilder.getVpnName();
529 Long elanTag = subOpBuilder.getElanTag();
530 BigInteger nhDpnId = subOpBuilder.getNhDpnId();
531 if ((nhDpnId != null) && (nhDpnId.equals(dpnId))) {
532 // select another NhDpnId
534 LOG.debug("onPortRemovedFromSubnet: Last port {} on the subnet {}", portId,
535 subnetId.getValue());
536 // last port on this DPN, so we need to swap the NHDpnId
537 subDpnList = subOpBuilder.getSubnetToDpn();
538 if (subDpnList.isEmpty()) {
539 subOpBuilder.setNhDpnId(null);
541 // withdraw route from BGP
542 deleteSubnetRouteFromFib(rd, subnetIp, vpnName);
543 subOpBuilder.setRouteAdvState(TaskState.Na);
544 } catch (Exception ex) {
546 "onPortRemovedFromSubnet: Withdrawing NextHopDPN {} information for subnet {} "
547 + "from BGP failed ",
548 dpnId, subnetId.getValue(), ex);
549 subOpBuilder.setRouteAdvState(TaskState.Pending);
552 nhDpnId = subDpnList.get(0).getDpnId();
553 subOpBuilder.setNhDpnId(nhDpnId);
554 LOG.debug("onInterfaceDown: Swapping the Designated DPN to {} for subnet {}", nhDpnId,
555 subnetId.getValue());
557 // Best effort Withdrawal of route from BGP for this subnet
558 // Advertise the new NexthopIP to BGP for this subnet
559 //withdrawSubnetRoutefromBgp(rd, subnetIp);
560 int label = getLabel(rd, subnetIp);
563 "Unable to fetch label from Id Manager. Bailing out of handling removal of "
564 + "port {} from subnet {} in vpn {}",
565 portId.getValue(), subnetIp, vpnName);
569 addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
570 if (isRouteAdvertised) {
571 subOpBuilder.setRouteAdvState(TaskState.Done);
573 subOpBuilder.setNhDpnId(null);
574 subOpBuilder.setRouteAdvState(TaskState.Na);
576 } catch (Exception ex) {
578 "onPortRemovedFromSubnet: Swapping Withdrawing NextHopDPN {} information for "
579 + "subnet {} to BGP failed",
580 dpnId, subnetId.getValue(), ex);
581 subOpBuilder.setRouteAdvState(TaskState.Pending);
586 subOpEntry = subOpBuilder.build();
587 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
589 "onPortRemovedFromSubnet: Updated subnetopdataentry to OP Datastore removing port " + portId
591 } catch (Exception ex) {
592 LOG.error("Creation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
594 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
596 } catch (Exception e) {
597 LOG.error("Unable to handle port {} removed from subnet {} {}", portId.getValue(), subnetId.getValue(),
602 // TODO Clean up the exception handling
603 @SuppressWarnings("checkstyle:IllegalCatch")
604 public void onInterfaceUp(BigInteger dpnId, String intfName) {
605 LOG.info("onInterfaceUp: Port " + intfName);
606 //TODO(vivek): Change this to use more granularized lock at subnetId level
607 SubnetToDpn subDpn = null;
608 boolean isRouteAdvertised = false;
609 PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(intfName);
610 if (portOpEntry == null) {
611 LOG.info("onInterfaceUp: Port " + intfName + "is part of a subnet not in VPN, ignoring");
614 if ((dpnId == null) || (dpnId == BigInteger.ZERO)) {
615 dpnId = portOpEntry.getDpnId();
617 LOG.error("onInterfaceUp: Unable to determine the DPNID for port " + intfName);
621 Uuid subnetId = portOpEntry.getSubnetId();
623 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
625 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
626 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
627 new SubnetOpDataEntryKey(subnetId)).build();
628 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
630 if (!optionalSubs.isPresent()) {
631 LOG.error("onInterfaceUp: SubnetOpDataEntry for subnet {} is not available", subnetId.getValue());
635 LOG.debug("onInterfaceUp: Updating the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
636 subOpDpnManager.addPortOpDataEntry(intfName, subnetId, dpnId);
637 subDpn = subOpDpnManager.addInterfaceToDpn(subnetId, dpnId, intfName);
638 if (subDpn == null) {
641 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
642 List<SubnetToDpn> subDpnList = subOpBuilder.getSubnetToDpn();
643 subDpnList.add(subDpn);
644 subOpBuilder.setSubnetToDpn(subDpnList);
645 if (subOpBuilder.getNhDpnId() == null) {
646 subOpBuilder.setNhDpnId(dpnId);
648 BigInteger nhDpnId = subOpBuilder.getNhDpnId();
649 String rd = subOpBuilder.getVrfId();
650 String subnetIp = subOpBuilder.getSubnetCidr();
651 String vpnName = subOpBuilder.getVpnName();
652 Long elanTag = subOpBuilder.getElanTag();
653 if ((subOpBuilder.getRouteAdvState() == TaskState.Pending)
654 || (subOpBuilder.getRouteAdvState() == TaskState.Na)) {
656 // Write the Subnet Route Entry to FIB
657 // Advertise BGP Route here and set route_adv_state to DONE
658 int label = getLabel(rd, subnetIp);
661 "Unable to fetch label from Id Manager. Bailing out of handling interface up event "
662 + "for port {} for subnet {} in vpn {}",
663 intfName, subnetIp, vpnName);
667 addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
668 if (isRouteAdvertised) {
669 subOpBuilder.setRouteAdvState(TaskState.Done);
671 subOpBuilder.setNhDpnId(null);
672 subOpBuilder.setRouteAdvState(TaskState.Na);
674 } catch (Exception ex) {
675 LOG.error("onInterfaceUp: Advertising NextHopDPN {} information for subnet {} to BGP failed",
676 nhDpnId, subnetId.getValue(), ex);
679 SubnetOpDataEntry subOpEntry = subOpBuilder.build();
680 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
681 LOG.info("onInterfaceUp: Updated subnetopdataentry to OP Datastore port up " + intfName);
682 } catch (Exception ex) {
683 LOG.error("Creation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
685 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
687 } catch (Exception e) {
688 LOG.error("Unable to handle interface up event for port {} in subnet {} {}", portOpEntry.getPortId(),
689 subnetId.getValue(), e);
693 // TODO Clean up the exception handling
694 @SuppressWarnings("checkstyle:IllegalCatch")
695 public void onInterfaceDown(final BigInteger dpnId, final String interfaceName) {
696 boolean isRouteAdvertised = false;
697 LOG.info("onInterfaceDown: Port " + interfaceName);
698 //TODO(vivek): Change this to use more granularized lock at subnetId level
699 PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(interfaceName);
700 if (portOpEntry == null) {
701 LOG.info("onInterfaceDown: Port " + interfaceName + "is part of a subnet not in VPN, ignoring");
704 if ((dpnId == null) || (dpnId == BigInteger.ZERO)) {
705 LOG.error("onInterfaceDown: Unable to determine the DPNID for port " + interfaceName);
708 Uuid subnetId = portOpEntry.getSubnetId();
710 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
712 LOG.debug("onInterfaceDown: Updating the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
713 boolean last = subOpDpnManager.removeInterfaceFromDpn(subnetId, dpnId, interfaceName);
714 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
715 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
716 new SubnetOpDataEntryKey(subnetId)).build();
717 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
718 LogicalDatastoreType.OPERATIONAL,
720 if (!optionalSubs.isPresent()) {
721 LOG.error("onInterfaceDown: SubnetOpDataEntry for subnet {} is not available", subnetId.getValue());
724 SubnetOpDataEntry subOpEntry = null;
725 List<SubnetToDpn> subDpnList = null;
726 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
727 String rd = subOpBuilder.getVrfId();
728 String subnetIp = subOpBuilder.getSubnetCidr();
729 String vpnName = subOpBuilder.getVpnName();
730 Long elanTag = subOpBuilder.getElanTag();
731 BigInteger nhDpnId = subOpBuilder.getNhDpnId();
732 if ((nhDpnId != null) && (nhDpnId.equals(dpnId))) {
733 // select another NhDpnId
736 "onInterfaceDown: Last active port " + interfaceName + " on the subnet: " + subnetId
738 // last port on this DPN, so we need to swap the NHDpnId
739 subDpnList = subOpBuilder.getSubnetToDpn();
740 if (subDpnList.isEmpty()) {
741 subOpBuilder.setNhDpnId(null);
743 // Withdraw route from BGP for this subnet
744 deleteSubnetRouteFromFib(rd, subnetIp, vpnName);
745 subOpBuilder.setRouteAdvState(TaskState.Na);
746 } catch (Exception ex) {
748 "onInterfaceDown: Withdrawing NextHopDPN {} information for subnet {} from BGP "
750 dpnId, subnetId.getValue(), ex);
751 subOpBuilder.setRouteAdvState(TaskState.Pending);
754 nhDpnId = subDpnList.get(0).getDpnId();
755 subOpBuilder.setNhDpnId(nhDpnId);
757 "onInterfaceDown: Swapping the Designated DPN to {} for subnet {}" , nhDpnId,
758 subnetId.getValue());
760 // Best effort Withdrawal of route from BGP for this subnet
761 //withdrawSubnetRoutefromBgp(rd, subnetIp);
762 int label = getLabel(rd, subnetIp);
765 "Unable to fetch label from Id Manager. Bailing out of handling interface "
766 + "down event for port {} in subnet {} for vpn {}",
767 interfaceName, subnetIp, vpnName);
771 addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
772 if (isRouteAdvertised) {
773 subOpBuilder.setRouteAdvState(TaskState.Done);
775 subOpBuilder.setNhDpnId(null);
776 subOpBuilder.setRouteAdvState(TaskState.Na);
778 } catch (Exception ex) {
780 "onInterfaceDown: Swapping Withdrawing NextHopDPN {} information for "
781 + "subnet {} to BGP failed", dpnId, subnetId.getValue(), ex);
782 subOpBuilder.setRouteAdvState(TaskState.Pending);
787 subOpEntry = subOpBuilder.build();
788 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
789 LOG.info("onInterfaceDown: Updated subnetopdataentry to OP Datastore port down " + interfaceName);
790 } catch (Exception ex) {
791 LOG.error("Creation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
793 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
795 } catch (Exception e) {
796 LOG.error("Unable to handle interface down event for port {} in subnet {} {}", portOpEntry.getPortId(),
797 subnetId.getValue(), e);
802 public void onRouterAssociatedToVpn(RouterAssociatedToVpn notification) {
806 public void onRouterDisassociatedFromVpn(RouterDisassociatedFromVpn notification) {
809 // TODO Clean up the exception handling
810 @SuppressWarnings("checkstyle:IllegalCatch")
811 public void updateSubnetRouteOnTunnelUpEvent(Uuid subnetId, BigInteger dpnId) {
812 boolean isRouteAdvertised = false;
813 LOG.info("updateSubnetRouteOnTunnelUpEvent: Subnet {} Dpn {}", subnetId.getValue(), dpnId.toString());
815 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
817 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
818 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
819 new SubnetOpDataEntryKey(subnetId)).build();
820 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
821 LogicalDatastoreType.OPERATIONAL,
823 if (!optionalSubs.isPresent()) {
824 LOG.error("updateSubnetRouteOnTunnelUpEvent: SubnetOpDataEntry for subnet {} is not available",
825 subnetId.getValue());
828 SubnetOpDataEntry subOpEntry = null;
829 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
830 String rd = subOpBuilder.getVrfId();
831 String subnetIp = subOpBuilder.getSubnetCidr();
832 String vpnName = subOpBuilder.getVpnName();
833 List<SubnetToDpn> subDpnList = subOpBuilder.getSubnetToDpn();
834 long elanTag = subOpBuilder.getElanTag();
835 if ((subOpBuilder.getRouteAdvState() == TaskState.Pending)
836 || (subOpBuilder.getRouteAdvState() == TaskState.Na)) {
837 for (SubnetToDpn subDpn : subDpnList) {
838 if (subDpn.getDpnId().equals(dpnId)) {
839 if (subOpBuilder.getNhDpnId() == null) {
841 subOpBuilder.setNhDpnId(dpnId);
842 int label = getLabel(rd, subnetIp);
844 addSubnetRouteToFib(rd, subnetIp, dpnId, vpnName, elanTag, label, subnetId);
845 if (isRouteAdvertised) {
846 subOpBuilder.setRouteAdvState(TaskState.Done);
848 subOpBuilder.setNhDpnId(null);
849 subOpBuilder.setRouteAdvState(TaskState.Na);
851 } catch (Exception ex) {
853 "updateSubnetRouteOnTunnelUpEvent: Advertising NextHopDPN {} information for "
854 + "subnet {} to BGP failed",
855 dpnId, subnetId.getValue(), ex);
860 subOpEntry = subOpBuilder.build();
861 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
863 "updateSubnetRouteOnTunnelUpEvent: Updated subnetopdataentry to OP Datastore tunnel up on dpn"
864 + " {} for subnet {}",
865 dpnId.toString(), subnetId.getValue());
867 } catch (Exception ex) {
868 LOG.error("Creation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
870 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
872 } catch (Exception e) {
873 LOG.error("Unable to handle tunnel up event for subnetId {} dpnId {}", subnetId.getValue(),
878 // TODO Clean up the exception handling
879 @SuppressWarnings("checkstyle:IllegalCatch")
880 public void updateSubnetRouteOnTunnelDownEvent(Uuid subnetId, BigInteger dpnId) {
881 LOG.info("updateSubnetRouteOnTunnelDownEvent: Subnet {} Dpn {}", subnetId.getValue(), dpnId.toString());
882 //TODO(vivek): Change this to use more granularized lock at subnetId level
884 VpnUtil.lockSubnet(lockManager, subnetId.getValue());
886 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
887 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
888 new SubnetOpDataEntryKey(subnetId)).build();
889 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
890 LogicalDatastoreType.OPERATIONAL,
892 if (!optionalSubs.isPresent()) {
893 LOG.error("updateSubnetRouteOnTunnelDownEvent: SubnetOpDataEntry for subnet {} is not available",
894 subnetId.getValue());
897 SubnetOpDataEntry subOpEntry = null;
898 SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
899 BigInteger nhDpnId = subOpBuilder.getNhDpnId();
900 if ((nhDpnId != null) && (nhDpnId.equals(dpnId))) {
901 electNewDPNForSubNetRoute(subOpBuilder, dpnId, subnetId);
902 subOpEntry = subOpBuilder.build();
903 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
905 "updateSubnetRouteOnTunnelDownEvent: Updated subnetopdataentry to OP Datastore tunnnel down "
906 + "on dpn {} for subnet {}",
907 dpnId.toString(), subnetId.getValue());
909 } catch (Exception ex) {
910 LOG.error("Updation of SubnetOpDataEntry for subnet {} failed", subnetId.getValue(), ex);
912 VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
914 } catch (Exception e) {
915 LOG.error("Unable to handle tunnel down event for subnetId {} dpnId {}", subnetId.getValue(),
920 // TODO Clean up the exception handling
921 @SuppressWarnings("checkstyle:IllegalCatch")
922 private boolean addSubnetRouteToFib(String rd, String subnetIp, BigInteger nhDpnId, String vpnName,
923 Long elanTag, int label, Uuid subnetId) throws Exception {
924 Preconditions.checkNotNull(rd, "RouteDistinguisher cannot be null or empty!");
925 Preconditions.checkNotNull(subnetIp, "SubnetRouteIp cannot be null or empty!");
926 Preconditions.checkNotNull(vpnName, "vpnName cannot be null or empty!");
927 Preconditions.checkNotNull(elanTag, "elanTag cannot be null or empty!");
928 String nexthopIp = null;
930 nexthopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, nhDpnId);
931 } catch (Exception e) {
932 LOG.warn("Unable to find nexthopip for subnetroute subnetip {}", subnetIp);
935 if (nexthopIp != null) {
936 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
937 VpnUtil.getPrefixToInterfaceIdentifier(VpnUtil.getVpnId(dataBroker, vpnName), subnetIp),
938 VpnUtil.getPrefixToInterface(nhDpnId, subnetId.getValue(), subnetIp));
939 vpnInterfaceManager.addSubnetRouteFibEntryToDS(rd, vpnName, subnetIp, nexthopIp, label, elanTag, nhDpnId,
942 //BGP manager will handle withdraw and advertise internally if prefix
944 bgpManager.advertisePrefix(rd, subnetIp, Arrays.asList(nexthopIp), label);
945 } catch (Exception e) {
946 LOG.error("Fail: Subnet route not advertised for rd {} subnetIp {}", rd, subnetIp, e);
950 LOG.warn("The nexthopip is empty for subnetroute subnetip {}, ignoring fib route addition", subnetIp);
956 private int getLabel(String rd, String subnetIp) {
957 int label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
958 VpnUtil.getNextHopLabelKey(rd, subnetIp));
959 LOG.trace("Allocated subnetroute label {} for rd {} prefix {}", label, rd, subnetIp);
963 // TODO Clean up the exception handling
964 @SuppressWarnings("checkstyle:IllegalCatch")
965 private void deleteSubnetRouteFromFib(String rd, String subnetIp, String vpnName) throws Exception {
966 Preconditions.checkNotNull(rd, "RouteDistinguisher cannot be null or empty!");
967 Preconditions.checkNotNull(subnetIp, "SubnetRouteIp cannot be null or empty!");
968 vpnInterfaceManager.deleteSubnetRouteFibEntryFromDS(rd, subnetIp, vpnName);
970 bgpManager.withdrawPrefix(rd, subnetIp);
971 } catch (Exception e) {
972 LOG.error("Fail: Subnet route not withdrawn for rd {} subnetIp {}", rd, subnetIp, e);
977 // TODO Clean up the exception handling
978 @SuppressWarnings("checkstyle:IllegalCatch")
979 private void electNewDPNForSubNetRoute(SubnetOpDataEntryBuilder subOpBuilder, BigInteger dpnId, Uuid subnetId) {
980 List<SubnetToDpn> subDpnList = null;
981 boolean isRouteAdvertised = false;
982 subDpnList = subOpBuilder.getSubnetToDpn();
983 String rd = subOpBuilder.getVrfId();
984 String subnetIp = subOpBuilder.getSubnetCidr();
985 String vpnName = subOpBuilder.getVpnName();
986 long elanTag = subOpBuilder.getElanTag();
987 BigInteger nhDpnId = null;
988 boolean isAlternateDpnSelected = false;
989 Iterator<SubnetToDpn> subNetIt = subDpnList.iterator();
990 int label = getLabel(rd, subnetIp);
991 while (subNetIt.hasNext()) {
992 SubnetToDpn subnetToDpn = subNetIt.next();
993 nhDpnId = subnetToDpn.getDpnId();
994 if (!nhDpnId.equals(dpnId)) {
996 //update the VRF entry for the subnetroute.
997 isRouteAdvertised = addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
998 if (isRouteAdvertised) {
999 subOpBuilder.setRouteAdvState(TaskState.Done);
1000 subOpBuilder.setNhDpnId(nhDpnId);
1001 isAlternateDpnSelected = true;
1004 } catch (Exception ex) {
1006 "electNewDPNForSubNetRoute: Swapping and trying to configure NextHopDPN {} for subnet {} "
1008 dpnId.toString(), subnetId.getValue(), ex);
1009 subOpBuilder.setRouteAdvState(TaskState.Na);
1014 //If no alternate Dpn is selected as nextHopDpn ,withdraw the subnetroute.
1015 if (!isAlternateDpnSelected) {
1016 LOG.info("No alternate DPN available for subnet {}.Prefix withdrawn from BGP", subnetIp);
1018 // Withdraw route from BGP for this subnet
1019 deleteSubnetRouteFromFib(rd, subnetIp, vpnName);
1020 subOpBuilder.setNhDpnId(null);
1021 subOpBuilder.setRouteAdvState(TaskState.Na);
1022 } catch (Exception ex) {
1024 "electNewDPNForSubNetRoute: Withdrawing NextHopDPN " + dpnId.toString() + " information for subnet "
1026 subnetId.getValue() + " from BGP failed {}" + ex);
1027 subOpBuilder.setRouteAdvState(TaskState.Pending);