2 * Copyright (c) 2017 HPE 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.elan.utils;
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12 import com.google.common.base.Optional;
13 import com.google.common.collect.MapDifference;
14 import com.google.common.collect.MapDifference.ValueDifference;
15 import com.google.common.collect.Maps;
16 import java.math.BigInteger;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.HashSet;
20 import java.util.List;
22 import java.util.Map.Entry;
23 import java.util.Objects;
25 import java.util.concurrent.ExecutionException;
26 import java.util.stream.Collectors;
27 import javax.inject.Inject;
28 import javax.inject.Singleton;
29 import org.eclipse.jdt.annotation.NonNull;
30 import org.eclipse.jdt.annotation.Nullable;
31 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
32 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
33 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
34 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
35 import org.opendaylight.genius.infra.Datastore.Configuration;
36 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
37 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
38 import org.opendaylight.genius.infra.TypedReadTransaction;
39 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
40 import org.opendaylight.genius.infra.TypedWriteTransaction;
41 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
42 import org.opendaylight.netvirt.elan.cache.ElanInstanceCache;
43 import org.opendaylight.netvirt.elan.internal.ElanBridgeManager;
44 import org.opendaylight.netvirt.elanmanager.api.IElanService;
45 import org.opendaylight.ovsdb.utils.mdsal.utils.ControllerMdsalUtils;
46 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.VtepsBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.VtepsKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.config.rev150710.ElanConfig;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
73 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
79 public class TransportZoneNotificationUtil {
80 private static final Logger LOG = LoggerFactory.getLogger(TransportZoneNotificationUtil.class);
81 private static final String TUNNEL_PORT = "tunnel_port";
82 private static final String LOCAL_IP = "local_ip";
83 private static final String LOCAL_IPS = "local_ips";
84 private static final char IP_NETWORK_ZONE_NAME_DELIMITER = '-';
85 private static final String ALL_SUBNETS_GW = "0.0.0.0";
86 private static final String ALL_SUBNETS = "0.0.0.0/0";
87 private final ManagedNewTransactionRunner txRunner;
88 private final SingleTransactionDataBroker singleTxBroker;
89 private final SouthboundUtils southBoundUtils;
90 private final IElanService elanService;
91 private final ElanConfig elanConfig;
92 private final ElanBridgeManager elanBridgeManager;
93 private final ElanInstanceCache elanInstanceCache;
96 public TransportZoneNotificationUtil(final DataBroker dbx,
97 final IElanService elanService, final ElanConfig elanConfig, final ElanBridgeManager elanBridgeManager,
98 final ElanInstanceCache elanInstanceCache) {
99 this.txRunner = new ManagedNewTransactionRunnerImpl(dbx);
100 this.singleTxBroker = new SingleTransactionDataBroker(dbx);
101 this.elanService = elanService;
102 this.elanConfig = elanConfig;
103 this.elanBridgeManager = elanBridgeManager;
104 this.elanInstanceCache = elanInstanceCache;
105 southBoundUtils = new SouthboundUtils(new ControllerMdsalUtils(dbx));
108 public boolean shouldCreateVtep(List<VpnInterfaces> vpnInterfaces) {
109 if (vpnInterfaces == null || vpnInterfaces.isEmpty()) {
113 for (VpnInterfaces vpnInterface : vpnInterfaces) {
114 String interfaceName = vpnInterface.getInterfaceName();
116 ElanInterface elanInt = elanService.getElanInterfaceByElanInterfaceName(interfaceName);
117 if (elanInt == null) {
121 if (ElanUtils.isVxlanNetworkOrVxlanSegment(
122 elanInstanceCache.get(elanInt.getElanInstanceName()).orNull())) {
125 LOG.debug("Non-VXLAN elanInstance: {}", elanInt.getElanInstanceName());
132 private static TransportZone createZone(String subnetIp, String zoneName) {
133 List<Subnets> subnets = new ArrayList<>();
134 subnets.add(buildSubnets(subnetIp));
135 TransportZoneBuilder tzb = new TransportZoneBuilder().withKey(new TransportZoneKey(zoneName))
136 .setTunnelType(TunnelTypeVxlan.class).setZoneName(zoneName).setSubnets(subnets);
140 private static void updateTransportZone(TransportZone zone, BigInteger dpnId,
141 @NonNull TypedWriteTransaction<Configuration> tx) {
142 InstanceIdentifier<TransportZone> path = InstanceIdentifier.builder(TransportZones.class)
143 .child(TransportZone.class, new TransportZoneKey(zone.getZoneName())).build();
145 tx.merge(path, zone);
146 LOG.info("Transport zone {} updated due to dpn {} handling.", zone.getZoneName(), dpnId);
149 public void updateTransportZone(String zoneNamePrefix, BigInteger dpnId) {
150 LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
151 Map<String, String> localIps = getDpnLocalIps(dpnId);
152 if (!localIps.isEmpty()) {
153 LOG.debug("Will use local_ips for transport zone update for dpn {} and zone name prefix {}", dpnId,
155 for (Entry<String, String> entry : localIps.entrySet()) {
156 String localIp = entry.getKey();
157 String underlayNetworkName = entry.getValue();
158 String zoneName = getTzNameForUnderlayNetwork(zoneNamePrefix, underlayNetworkName);
159 updateTransportZone(zoneName, dpnId, localIp, tx);
162 updateTransportZone(zoneNamePrefix, dpnId, getDpnLocalIp(dpnId), tx);
164 }), LOG, "Error updating transport zone");
167 @SuppressWarnings("checkstyle:IllegalCatch")
168 private void updateTransportZone(String zoneName, BigInteger dpnId, @Nullable String localIp,
169 @NonNull TypedReadWriteTransaction<Configuration> tx)
170 throws ExecutionException, InterruptedException {
171 InstanceIdentifier<TransportZone> inst = InstanceIdentifier.create(TransportZones.class)
172 .child(TransportZone.class, new TransportZoneKey(zoneName));
174 // FIXME: Read this through a cache
175 TransportZone zone = tx.read(inst).get().orNull();
178 zone = createZone(ALL_SUBNETS, zoneName);
182 if (addVtep(zone, ALL_SUBNETS, dpnId, localIp)) {
183 updateTransportZone(zone, dpnId, tx);
185 } catch (Exception e) {
186 LOG.error("Failed to add tunnels for dpn {} in zone {}", dpnId, zoneName, e);
190 private static void deleteTransportZone(TransportZone zone, BigInteger dpnId,
191 @NonNull TypedWriteTransaction<Configuration> tx) {
192 InstanceIdentifier<TransportZone> path = InstanceIdentifier.builder(TransportZones.class)
193 .child(TransportZone.class, new TransportZoneKey(zone.getZoneName())).build();
195 LOG.info("Transport zone {} deleted due to dpn {} handling.", zone.getZoneName(), dpnId);
198 public void deleteTransportZone(String zoneNamePrefix, BigInteger dpnId) {
199 LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
200 Map<String, String> localIps = getDpnLocalIps(dpnId);
201 if (!localIps.isEmpty()) {
202 LOG.debug("Will use local_ips for transport zone delete for dpn {} and zone name prefix {}", dpnId,
204 for (String underlayNetworkName : localIps.values()) {
205 String zoneName = getTzNameForUnderlayNetwork(zoneNamePrefix, underlayNetworkName);
206 deleteTransportZone(zoneName, dpnId, tx);
209 deleteTransportZone(zoneNamePrefix, dpnId, tx);
211 }), LOG, "Error deleting transport zone");
214 @SuppressWarnings("checkstyle:IllegalCatch")
215 private static void deleteTransportZone(String zoneName, BigInteger dpnId,
216 @NonNull TypedReadWriteTransaction<Configuration> tx) throws ExecutionException, InterruptedException {
217 InstanceIdentifier<TransportZone> inst = InstanceIdentifier.create(TransportZones.class)
218 .child(TransportZone.class, new TransportZoneKey(zoneName));
220 // FIXME: Read this through a cache
221 TransportZone zone = tx.read(inst).get().orNull();
224 deleteTransportZone(zone, dpnId, tx);
225 } catch (Exception e) {
226 LOG.error("Failed to remove tunnels for dpn {} in zone {}", dpnId, zoneName, e);
233 * Update transport zones based on local_ips TEP ips mapping to underlay
235 * Deleted local_ips will be removed from the VTEP list of the corresponding
236 * transport zones.<br>
237 * Added local_ips will be added to all transport zones currently associated
239 * local_ips for whom the underlay network mapping has been changed will be
240 * updated in the VTEP lists of the corresponding transport zones.
246 * @param managerNodeId
247 * uuid of the OVS manager node
249 public void handleOvsdbNodeUpdate(Node origNode, Node updatedNode, String managerNodeId) {
251 String> origLocalIpMap = java.util.Optional
252 .ofNullable(elanBridgeManager.getOpenvswitchOtherConfigMap(origNode, LOCAL_IPS))
253 .orElse(Collections.emptyMap());
255 String> updatedLocalIpMap = java.util.Optional
256 .ofNullable(elanBridgeManager.getOpenvswitchOtherConfigMap(updatedNode, LOCAL_IPS))
257 .orElse(Collections.emptyMap());
258 MapDifference<String, String> mapDiff = Maps.difference(origLocalIpMap, updatedLocalIpMap);
259 if (mapDiff.areEqual()) {
263 java.util.Optional<BigInteger> dpIdOpt = elanBridgeManager.getDpIdFromManagerNodeId(managerNodeId);
264 if (!dpIdOpt.isPresent()) {
265 LOG.debug("No DPN id found for node {}", managerNodeId);
269 LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
270 BigInteger dpId = dpIdOpt.get();
271 Optional<DPNTEPsInfo> dpnTepsInfoOpt = getDpnTepsInfo(dpId, tx);
272 if (!dpnTepsInfoOpt.isPresent()) {
273 LOG.debug("No DPNTEPsInfo found for DPN id {}", dpId);
277 List<TunnelEndPoints> tunnelEndPoints = dpnTepsInfoOpt.get().getTunnelEndPoints();
278 if (tunnelEndPoints == null || tunnelEndPoints.isEmpty()) {
279 LOG.debug("No tunnel endpoints defined for DPN id {}", dpId);
283 Set<String> zonePrefixes = new HashSet<>();
284 Map<String, List<String>> tepTzMap = tunnelEndPoints.stream().collect(Collectors
285 .toMap(tep -> tep.getIpAddress().stringValue(), this::getTepTransportZoneNames));
286 LOG.trace("Transport zone prefixes {}", tepTzMap);
288 handleRemovedLocalIps(mapDiff.entriesOnlyOnLeft(), dpId, zonePrefixes, tepTzMap, tx);
289 handleChangedLocalIps(mapDiff.entriesDiffering(), dpId, zonePrefixes, tepTzMap, tx);
290 handleAddedLocalIps(mapDiff.entriesOnlyOnRight(), dpId, zonePrefixes, tx);
291 }), LOG, "Error handling OVSDB node update");
294 private void handleAddedLocalIps(Map<String, String> addedEntries, BigInteger dpId, Set<String> zonePrefixes,
295 TypedReadWriteTransaction<Configuration> tx) throws ExecutionException, InterruptedException {
296 if (addedEntries == null || addedEntries.isEmpty()) {
297 LOG.trace("No added local_ips found for DPN {}", dpId);
301 LOG.debug("Added local_ips {} on DPN {}", addedEntries.keySet(), dpId);
302 for (Map.Entry<String, String> addedEntry : addedEntries.entrySet()) {
303 String ipAddress = addedEntry.getKey();
304 String underlayNetworkName = addedEntry.getValue();
305 for (String zonePrefix : zonePrefixes) {
306 String zoneName = getTzNameForUnderlayNetwork(zonePrefix, underlayNetworkName);
307 updateTransportZone(zoneName, dpId, ipAddress, tx);
312 private void handleChangedLocalIps(Map<String, ValueDifference<String>> changedEntries, BigInteger dpId,
313 Set<String> zonePrefixes, Map<String, List<String>> tepTzMap,
314 @NonNull TypedReadWriteTransaction<Configuration> tx) throws ExecutionException, InterruptedException {
315 if (changedEntries == null || changedEntries.isEmpty()) {
316 LOG.trace("No changed local_ips found for DPN {}", dpId);
320 LOG.debug("Changing underlay network mapping for local_ips {} on DPN {}", changedEntries.keySet(), dpId);
321 for (Map.Entry<String, ValueDifference<String>> changedEntry : changedEntries.entrySet()) {
322 String ipAddress = changedEntry.getKey();
323 ValueDifference<String> underlayNetworkDiff = changedEntry.getValue();
324 List<String> zoneNames = tepTzMap.get(ipAddress);
325 if (zoneNames != null) {
326 for (String zoneName : zoneNames) {
327 String removedUnderlayNetwork = underlayNetworkDiff.leftValue();
328 String addedUnderlayNetwork = underlayNetworkDiff.rightValue();
329 Optional<String> zonePrefixOpt = getZonePrefixForUnderlayNetwork(zoneName, removedUnderlayNetwork);
330 if (zonePrefixOpt.isPresent()) {
331 String zonePrefix = zonePrefixOpt.get();
332 removeVtep(zoneName, dpId, tx);
333 zonePrefixes.add(zonePrefix);
334 String newZoneName = getTzNameForUnderlayNetwork(zonePrefix, addedUnderlayNetwork);
335 updateTransportZone(newZoneName, dpId, ipAddress, tx);
342 private static void handleRemovedLocalIps(Map<String, String> removedEntries, BigInteger dpId,
343 Set<String> zonePrefixes, Map<String, List<String>> tepTzMap,
344 @NonNull TypedWriteTransaction<Configuration> tx) {
345 if (removedEntries == null || removedEntries.isEmpty()) {
346 LOG.trace("No removed local_ips found on DPN {}", dpId);
350 LOG.debug("Removed local_ips {} for DPN {}", removedEntries.keySet(), dpId);
351 removedEntries.forEach((ipAddress, underlayNetworkName) -> {
352 List<String> zoneNames = tepTzMap.get(ipAddress);
353 if (zoneNames != null) {
354 for (String zoneName : zoneNames) {
355 Optional<String> zonePrefix = getZonePrefixForUnderlayNetwork(zoneName, underlayNetworkName);
356 if (zonePrefix.isPresent()) {
357 removeVtep(zoneName, dpId, tx);
358 zonePrefixes.add(zonePrefix.get());
365 private List<String> getTepTransportZoneNames(TunnelEndPoints tep) {
366 List<TzMembership> tzMembershipList = tep.getTzMembership();
367 if (tzMembershipList == null) {
368 LOG.debug("No TZ membership exist for TEP ip {}", tep.getIpAddress().stringValue());
369 return Collections.emptyList();
372 return tzMembershipList.stream().map(TzMembership::getZoneName).distinct()
373 .collect(Collectors.toList());
376 private static Optional<DPNTEPsInfo> getDpnTepsInfo(BigInteger dpId, TypedReadTransaction<Configuration> tx) {
377 InstanceIdentifier<DPNTEPsInfo> identifier = InstanceIdentifier.builder(DpnEndpoints.class)
378 .child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpId)).build();
380 return tx.read(identifier).get();
381 } catch (InterruptedException | ExecutionException e) {
382 LOG.warn("Failed to read DPNTEPsInfo for DPN id {}", dpId);
383 return Optional.absent();
388 * Tries to add a vtep for a transport zone.
390 * @return Whether a vtep was added or not.
392 private boolean addVtep(TransportZone zone, String subnetIp, BigInteger dpnId, @Nullable String localIp) {
393 List<Subnets> zoneSubnets = zone.getSubnets();
394 if (zoneSubnets == null) {
398 Subnets subnets = getOrAddSubnet(zoneSubnets, subnetIp);
399 for (Vteps existingVtep : subnets.nonnullVteps()) {
400 if (Objects.equals(existingVtep.getDpnId(), dpnId)) {
405 if (localIp != null) {
406 IpAddress nodeIp = IpAddressBuilder.getDefaultInstance(localIp);
407 VtepsBuilder vtepsBuilder = new VtepsBuilder().setDpnId(dpnId).setIpAddress(nodeIp)
408 .setPortname(TUNNEL_PORT).setOptionOfTunnel(elanConfig.isUseOfTunnels());
409 subnets.getVteps().add(vtepsBuilder.build());
416 private static void removeVtep(String zoneName, BigInteger dpId, @NonNull TypedWriteTransaction<Configuration> tx) {
417 InstanceIdentifier<Vteps> path = InstanceIdentifier.builder(TransportZones.class)
418 .child(TransportZone.class, new TransportZoneKey(zoneName))
419 .child(Subnets.class, new SubnetsKey(IpPrefixBuilder.getDefaultInstance(ALL_SUBNETS)))
420 .child(Vteps.class, new VtepsKey(dpId, TUNNEL_PORT)).build();
424 // search for relevant subnets for the given subnetIP, add one if it is
426 private static Subnets getOrAddSubnet(@NonNull List<Subnets> subnets, @NonNull String subnetIp) {
427 IpPrefix subnetPrefix = IpPrefixBuilder.getDefaultInstance(subnetIp);
429 for (Subnets subnet : subnets) {
430 if (Objects.equals(subnet.getPrefix(), subnetPrefix)) {
435 Subnets retSubnet = buildSubnets(subnetIp);
436 subnets.add(retSubnet);
441 private static Subnets buildSubnets(String subnetIp) {
442 SubnetsBuilder subnetsBuilder = new SubnetsBuilder().setDeviceVteps(new ArrayList<>())
443 .setGatewayIp(IpAddressBuilder.getDefaultInstance(ALL_SUBNETS_GW))
444 .withKey(new SubnetsKey(IpPrefixBuilder.getDefaultInstance(subnetIp))).setVlanId(0)
445 .setVteps(new ArrayList<>());
446 return subnetsBuilder.build();
450 private String getDpnLocalIp(BigInteger dpId) throws ReadFailedException {
451 Optional<Node> node = getPortsNode(dpId);
453 if (node.isPresent()) {
454 String localIp = southBoundUtils.getOpenvswitchOtherConfig(node.get(), LOCAL_IP);
455 if (localIp == null) {
456 LOG.error("missing local_ip key in ovsdb:openvswitch-other-configs in operational"
457 + " network-topology for node: {}", node.get().getNodeId().getValue());
467 private Map<String, String> getDpnLocalIps(BigInteger dpId) throws ReadFailedException {
468 // Example of local IPs from other_config:
469 // local_ips="10.0.43.159:MPLS,11.11.11.11:DSL,ip:underlay-network"
470 return getPortsNode(dpId).toJavaUtil().map(
471 node -> elanBridgeManager.getOpenvswitchOtherConfigMap(node, LOCAL_IPS)).orElse(Collections.emptyMap());
474 @SuppressWarnings("unchecked")
475 private Optional<Node> getPortsNode(BigInteger dpnId) throws ReadFailedException {
476 InstanceIdentifier<BridgeRefEntry> bridgeRefInfoPath = InstanceIdentifier.create(BridgeRefInfo.class)
477 .child(BridgeRefEntry.class, new BridgeRefEntryKey(dpnId));
479 // FIXME: Read this through a cache
480 Optional<BridgeRefEntry> optionalBridgeRefEntry =
481 singleTxBroker.syncReadOptional(LogicalDatastoreType.OPERATIONAL, bridgeRefInfoPath);
482 if (!optionalBridgeRefEntry.isPresent()) {
483 LOG.error("no bridge ref entry found for dpnId {}", dpnId);
484 return Optional.absent();
487 InstanceIdentifier<Node> nodeId =
488 optionalBridgeRefEntry.get().getBridgeReference().getValue().firstIdentifierOf(Node.class);
490 // FIXME: Read this through a cache
491 Optional<Node> optionalNode = singleTxBroker.syncReadOptional(LogicalDatastoreType.OPERATIONAL, nodeId);
492 if (!optionalNode.isPresent()) {
493 LOG.error("missing node for dpnId {}", dpnId);
498 private static String getTzNameForUnderlayNetwork(String zoneNamePrefix, String underlayNetworkName) {
499 return zoneNamePrefix + IP_NETWORK_ZONE_NAME_DELIMITER + underlayNetworkName;
502 private static Optional<String> getZonePrefixForUnderlayNetwork(String zoneName, String underlayNetworkName) {
503 String[] zoneParts = zoneName.split(IP_NETWORK_ZONE_NAME_DELIMITER + underlayNetworkName);
504 return zoneParts.length == 2 ? Optional.of(zoneParts[0]) : Optional.absent();