Convert to JobCoordinator in fibmanager-impl
[netvirt.git] / vpnservice / policyservice / impl / src / main / java / org / opendaylight / netvirt / policyservice / util / PolicyServiceUtil.java
1 /*
2  * Copyright (c) 2017 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.netvirt.policyservice.util;
10
11 import com.google.common.base.Optional;
12
13 import java.math.BigInteger;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Objects;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.Future;
21 import java.util.stream.Collectors;
22
23 import javax.annotation.Nonnull;
24 import javax.inject.Inject;
25 import javax.inject.Singleton;
26
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
29 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
30 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
31 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
32 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
33 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
34 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
35 import org.opendaylight.netvirt.elanmanager.api.IElanBridgeManager;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AclBase;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceKey;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Actions;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan.L2vlanMode;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.PolicyAcl;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.PolicyProfiles;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.SetPolicyClassifier;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.UnderlayNetworks;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.PolicyProfile;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.PolicyProfileKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile.PolicyAclRule;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile.PolicyAclRuleKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile.PolicyRoute;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile.policy.acl.rule.AceRule;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile.policy.acl.rule.AceRuleBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile.policy.acl.rule.AceRuleKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile.policy.route.route.BasicRoute;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.UnderlayNetwork;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.UnderlayNetworkKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.DpnToInterface;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.DpnToInterfaceBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.DpnToInterfaceKey;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.PolicyProfileBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.dpn.to._interface.TunnelInterface;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.dpn.to._interface.TunnelInterfaceBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.dpn.to._interface.TunnelInterfaceKey;
77 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
78 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
79 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
80 import org.opendaylight.yangtools.yang.common.RpcResult;
81 import org.slf4j.Logger;
82 import org.slf4j.LoggerFactory;
83
84 @SuppressWarnings("deprecation")
85 @Singleton
86 public class PolicyServiceUtil {
87     private static final Logger LOG = LoggerFactory.getLogger(PolicyServiceUtil.class);
88
89     public static final String LOCAL_IPS = "local_ips";
90
91     private final DataBroker dataBroker;
92     private final IElanBridgeManager bridgeManager;
93     private final ItmRpcService itmRpcService;
94     private final IInterfaceManager interfaceManager;
95     private final DataStoreJobCoordinator coordinator;
96
97     @Inject
98     public PolicyServiceUtil(final DataBroker dataBroker, final IElanBridgeManager bridgeManager,
99             final ItmRpcService itmRpcService, final IInterfaceManager interfaceManager) {
100         this.dataBroker = dataBroker;
101         this.bridgeManager = bridgeManager;
102         this.itmRpcService = itmRpcService;
103         this.interfaceManager = interfaceManager;
104         this.coordinator = DataStoreJobCoordinator.getInstance();
105     }
106
107     public Optional<String> getAcePolicyClassifier(Ace ace) {
108         Actions actions = ace.getActions();
109         SetPolicyClassifier setPolicyClassifier = actions.getAugmentation(SetPolicyClassifier.class);
110         if (setPolicyClassifier == null) {
111             LOG.warn("No valid policy action found for ACE rule {}", ace.getRuleName());
112             return Optional.absent();
113         }
114
115         Class<? extends DirectionBase> direction;
116         try {
117             direction = setPolicyClassifier.getDirection();
118         } catch (IllegalArgumentException e) {
119             LOG.warn("Failed to parse policy classifier direction");
120             return Optional.absent();
121         }
122
123         if (direction == null || !direction.isAssignableFrom(DirectionEgress.class)) {
124             LOG.trace("Ignoring non egress policy ACE rule {}", ace.getRuleName());
125             return Optional.absent();
126         }
127
128         return Optional.of(setPolicyClassifier.getPolicyClassifier());
129     }
130
131     public Optional<Ace> getPolicyAce(String aclName, String ruleName) {
132         InstanceIdentifier<Ace> identifier = getAceIdentifier(aclName, ruleName);
133         try {
134             return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
135                     identifier);
136         } catch (ReadFailedException e) {
137             LOG.warn("Failed to get policy ACE rule {} for ACL {}", ruleName, aclName);
138             return Optional.absent();
139         }
140     }
141
142     public List<PolicyProfile> getAllPolicyProfiles() {
143         InstanceIdentifier<PolicyProfiles> identifier = InstanceIdentifier.create(PolicyProfiles.class);
144         try {
145             Optional<PolicyProfiles> optProfiles = SingleTransactionDataBroker.syncReadOptional(dataBroker,
146                     LogicalDatastoreType.CONFIGURATION, identifier);
147             return optProfiles.isPresent() ? optProfiles.get().getPolicyProfile() : Collections.emptyList();
148         } catch (ReadFailedException e) {
149             LOG.warn("Failed to get policy profiles");
150             return Collections.emptyList();
151         }
152     }
153
154     public List<String> getUnderlayNetworksForClassifier(String policyClassifier) {
155         InstanceIdentifier<PolicyProfile> identifier = getPolicyClassifierIdentifier(policyClassifier);
156         try {
157             Optional<PolicyProfile> optProfile = SingleTransactionDataBroker.syncReadOptional(dataBroker,
158                     LogicalDatastoreType.CONFIGURATION, identifier);
159             return optProfile.isPresent() ? getUnderlayNetworksFromPolicyRoutes(optProfile.get().getPolicyRoute())
160                     : Collections.emptyList();
161         } catch (ReadFailedException e) {
162             LOG.warn("Failed to get policy routes for classifier {}", policyClassifier);
163             return Collections.emptyList();
164         }
165     }
166
167     public List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay
168         .network.PolicyProfile> getUnderlayNetworkPolicyProfiles(String underlayNetwork) {
169         InstanceIdentifier<UnderlayNetwork> identifier = getUnderlayNetworkIdentifier(underlayNetwork);
170         try {
171             Optional<UnderlayNetwork> optUnderlayNet = SingleTransactionDataBroker.syncReadOptional(dataBroker,
172                     LogicalDatastoreType.OPERATIONAL, identifier);
173             return optUnderlayNet.isPresent() ? optUnderlayNet.get().getPolicyProfile() : Collections.emptyList();
174         } catch (ReadFailedException e) {
175             LOG.warn("Failed to get policy classifiers for underlay network {}", underlayNetwork);
176             return Collections.emptyList();
177         }
178     }
179
180     public List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile
181         .PolicyAclRule> getPolicyClassifierAclRules(String policyClassifier) {
182         InstanceIdentifier<PolicyProfile> identifier = getPolicyClassifierIdentifier(policyClassifier);
183         try {
184             Optional<PolicyProfile> optProfile = SingleTransactionDataBroker.syncReadOptional(dataBroker,
185                     LogicalDatastoreType.OPERATIONAL, identifier);
186             return optProfile.isPresent() ? optProfile.get().getPolicyAclRule() : Collections.emptyList();
187         } catch (ReadFailedException e) {
188             LOG.warn("Failed to get policy rules for policy classifier {}", policyClassifier);
189             return Collections.emptyList();
190         }
191     }
192
193     public void updateTunnelInterfaceForUnderlayNetwork(String underlayNetwork, BigInteger srcDpId, BigInteger dstDpId,
194             String tunnelInterfaceName, boolean isAdded) {
195         coordinator.enqueueJob(underlayNetwork, () -> {
196             InstanceIdentifier<TunnelInterface> identifier = getUnderlayNetworkTunnelIdentifier(underlayNetwork,
197                     srcDpId, tunnelInterfaceName);
198             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
199             if (isAdded) {
200                 TunnelInterface tunnelInterface = new TunnelInterfaceBuilder().setInterfaceName(tunnelInterfaceName)
201                         .setRemoteDpId(dstDpId).build();
202                 tx.merge(LogicalDatastoreType.OPERATIONAL, identifier, tunnelInterface, true);
203                 LOG.info("Add tunnel {} on DPN {} to underlay network {}", tunnelInterfaceName, srcDpId,
204                         underlayNetwork);
205             } else {
206                 tx.delete(LogicalDatastoreType.OPERATIONAL, identifier);
207                 LOG.info("Remove tunnel {} from DPN {} on underlay network {}", tunnelInterfaceName, srcDpId,
208                         underlayNetwork);
209             }
210             return Collections.singletonList(tx.submit());
211         });
212     }
213
214     public void updateTunnelInterfacesForUnderlayNetwork(String underlayNetwork, BigInteger srcDpId,
215             List<TunnelInterface> tunnelInterfaces, boolean isAdded) {
216         coordinator.enqueueJob(underlayNetwork, () -> {
217             InstanceIdentifier<DpnToInterface> identifier = getUnderlayNetworkDpnIdentifier(underlayNetwork, srcDpId);
218             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
219             if (isAdded) {
220                 DpnToInterface dpnToInterface = new DpnToInterfaceBuilder().setDpId(srcDpId)
221                         .setTunnelInterface(tunnelInterfaces).build();
222                 tx.merge(LogicalDatastoreType.OPERATIONAL, identifier, dpnToInterface, true);
223                 LOG.info("Add tunnel interfaces {} on DPN {} to underlay network {}", tunnelInterfaces, srcDpId,
224                         underlayNetwork);
225             } else {
226                 tx.delete(LogicalDatastoreType.OPERATIONAL, identifier);
227                 LOG.info("Remove tunnel interfaces {} from DPN {} on underlay network {}", tunnelInterfaces, srcDpId,
228                         underlayNetwork);
229             }
230             return Collections.singletonList(tx.submit());
231         });
232     }
233
234     public void updatePolicyClassifierForUnderlayNetworks(List<String> underlayNetworks, String policyClassifier,
235             boolean isAdded) {
236         if (underlayNetworks == null || underlayNetworks.isEmpty()) {
237             LOG.debug("No underlay networks found for policy classifier {}", policyClassifier);
238         }
239
240         underlayNetworks.forEach(underlayNetwork -> coordinator.enqueueJob(underlayNetwork, () -> {
241             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
242             InstanceIdentifier<
243                     org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks
244                     .underlay.network.PolicyProfile> identifier = getUnderlayNetworkPolicyClassifierIdentifier(
245                             policyClassifier, underlayNetwork);
246
247             if (isAdded) {
248                 tx.merge(LogicalDatastoreType.OPERATIONAL, identifier,
249                         new PolicyProfileBuilder().setPolicyClassifier(policyClassifier).build(), true);
250                 LOG.info("Add policy classifier {} to underlay network {}", policyClassifier, underlayNetwork);
251             } else {
252                 tx.delete(LogicalDatastoreType.OPERATIONAL, identifier);
253                 LOG.info("Remove policy classifier {} from underlay network {}", policyClassifier, underlayNetwork);
254             }
255             return Collections.singletonList(tx.submit());
256         }));
257     }
258
259     public void updateAclRuleForPolicyClassifier(String policyClassifier, String aclName, String ruleName,
260             boolean isAdded) {
261         coordinator.enqueueJob(policyClassifier, () -> {
262             InstanceIdentifier<
263                     AceRule> identifier = getPolicyClassifierAceIdentifier(policyClassifier, aclName, ruleName);
264             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
265             if (isAdded) {
266                 tx.merge(LogicalDatastoreType.OPERATIONAL, identifier,
267                         new AceRuleBuilder().setRuleName(ruleName).build(), true);
268                 LOG.info("Add ACL {} rule {} to policy classifier {}", aclName, ruleName, policyClassifier);
269             } else {
270                 tx.delete(LogicalDatastoreType.OPERATIONAL, identifier);
271                 LOG.info("Remove ACL {} rule {} from policy classifier {}", aclName, ruleName, policyClassifier);
272             }
273             return Collections.singletonList(tx.submit());
274         });
275     }
276
277     public List<BigInteger> getUnderlayNetworksDpns(List<String> underlayNetworks) {
278         if (underlayNetworks == null) {
279             return Collections.emptyList();
280         }
281
282         return underlayNetworks.stream().flatMap(t -> getUnderlayNetworkDpns(t).stream()).distinct()
283                 .collect(Collectors.toList());
284     }
285
286     public List<BigInteger> getUnderlayNetworksRemoteDpns(List<String> underlayNetworks) {
287         if (underlayNetworks == null) {
288             return Collections.emptyList();
289         }
290
291         return underlayNetworks.stream().map(this::getUnderlayNetworkRemoteDpns).flatMap(Collection::stream).distinct()
292                 .collect(Collectors.toList());
293     }
294
295     public boolean underlayNetworkContainsDpn(String underlayNetwork, BigInteger dpId) {
296         return dpnToInterfacesContainsDpn(getUnderlayNetworkDpnToInterfaces(underlayNetwork), dpId);
297     }
298
299     public boolean underlayNetworkContainsRemoteDpn(String underlayNetwork, BigInteger dpId) {
300         return dpnToInterfacesContainsRemoteDpn(getUnderlayNetworkDpnToInterfaces(underlayNetwork), dpId);
301     }
302
303     public static boolean dpnToInterfacesContainsDpn(List<DpnToInterface> dpnToInterfaces, BigInteger dpId) {
304         return dpnToInterfaces != null && dpnToInterfaces.stream().anyMatch(
305             dpnToInterface -> dpnToInterface.getDpId().equals(dpId));
306     }
307
308     public static boolean dpnToInterfacesContainsRemoteDpn(List<DpnToInterface> dpnToInterfaces, BigInteger dpId) {
309         return dpnToInterfaces != null && dpnToInterfaces.stream().anyMatch(
310             dpnToInterface -> dpnToInterfaceContainsRemoteDpn(dpnToInterface, dpId));
311     }
312
313     public static boolean dpnToInterfaceContainsRemoteDpn(DpnToInterface dpnToInterface, BigInteger dpId) {
314         List<TunnelInterface> tunnelInterfaces = dpnToInterface.getTunnelInterface();
315         return tunnelInterfaces != null && tunnelInterfaces.stream().anyMatch(
316             tunnelInterface -> tunnelInterface.getRemoteDpId().equals(dpId));
317     }
318
319     public String getTunnelUnderlayNetwork(BigInteger dpId, IpAddress tunnelIp) {
320         Node ovsdbNode = bridgeManager.getBridgeNode(dpId);
321         if (ovsdbNode == null) {
322             LOG.error("Failed to get OVSDB node for DPN {}", dpId);
323             return null;
324         }
325
326         Map<String, String> localIpMap = bridgeManager.getOpenvswitchOtherConfigMap(ovsdbNode, LOCAL_IPS);
327         return localIpMap.get(String.valueOf(tunnelIp.getValue()));
328     }
329
330     public static List<BigInteger> getDpnsFromDpnToInterfaces(List<DpnToInterface> dpnToInterfaces) {
331         if (dpnToInterfaces == null) {
332             return Collections.emptyList();
333         }
334
335         return dpnToInterfaces.stream().map(DpnToInterface::getDpId).collect(Collectors.toList());
336     }
337
338     public static List<BigInteger> getRemoteDpnsFromDpnToInterfaces(List<DpnToInterface> dpnToInterfaces) {
339         if (dpnToInterfaces == null) {
340             return Collections.emptyList();
341         }
342
343         return dpnToInterfaces.stream().map(PolicyServiceUtil::getRemoteDpnsFromDpnToInterface)
344                 .flatMap(Collection::stream).distinct().collect(Collectors.toList());
345     }
346
347     public static List<BigInteger> getRemoteDpnsFromDpnToInterface(DpnToInterface dpnToInterface) {
348         List<TunnelInterface> tunnelInterfaces = dpnToInterface.getTunnelInterface();
349         if (tunnelInterfaces == null) {
350             return Collections.emptyList();
351         }
352
353         return tunnelInterfaces.stream().map(TunnelInterface::getRemoteDpId)
354                 .collect(Collectors.toList());
355     }
356
357     public static List<String> getUnderlayNetworksFromPolicyRoutes(List<PolicyRoute> policyRoutes) {
358         if (policyRoutes == null) {
359             return Collections.emptyList();
360         }
361
362         return policyRoutes.stream().map(PolicyRoute::getRoute)
363                 .filter(route -> route instanceof BasicRoute).map(route -> ((BasicRoute) route).getNetworkName())
364                 .collect(Collectors.toList());
365     }
366
367     public static boolean isPolicyAcl(Class<? extends AclBase> aclType) {
368         return aclType != null && aclType.isAssignableFrom(PolicyAcl.class);
369     }
370
371     @Nonnull
372     public List<DpnToInterface> getUnderlayNetworkDpnToInterfaces(String underlayNetwork) {
373         InstanceIdentifier<UnderlayNetwork> identifier = InstanceIdentifier.create(UnderlayNetworks.class)
374                 .child(UnderlayNetwork.class, new UnderlayNetworkKey(underlayNetwork));
375         try {
376             return SingleTransactionDataBroker
377                     .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier)
378                     .toJavaUtil().map(UnderlayNetwork::getDpnToInterface)
379                     .orElse(Collections.emptyList());
380         } catch (ReadFailedException e) {
381             LOG.warn("Failed to get DPNs for underlay network {}", underlayNetwork);
382             return Collections.emptyList();
383         }
384     }
385
386     public Optional<DpnToInterface> getUnderlayNetworkDpnToInterfaces(String underlayNetwork, BigInteger dpId) {
387         InstanceIdentifier<DpnToInterface> identifier = getUnderlayNetworkDpnIdentifier(underlayNetwork, dpId);
388         try {
389             Optional<DpnToInterface> dpnToInterfaceOpt = SingleTransactionDataBroker.syncReadOptional(dataBroker,
390                     LogicalDatastoreType.OPERATIONAL, identifier);
391             return dpnToInterfaceOpt;
392         } catch (ReadFailedException e) {
393             LOG.warn("Failed to get DPN {} for underlay network {}", dpId, underlayNetwork);
394             return Optional.absent();
395         }
396     }
397
398     private InstanceIdentifier<UnderlayNetwork> getUnderlayNetworkIdentifier(String underlayNetwork) {
399         return InstanceIdentifier.create(UnderlayNetworks.class).child(UnderlayNetwork.class,
400                 new UnderlayNetworkKey(underlayNetwork));
401     }
402
403     private InstanceIdentifier<DpnToInterface> getUnderlayNetworkDpnIdentifier(String underlayNetwork,
404             BigInteger dpId) {
405         return InstanceIdentifier.create(UnderlayNetworks.class)
406                 .child(UnderlayNetwork.class, new UnderlayNetworkKey(underlayNetwork))
407                 .child(DpnToInterface.class, new DpnToInterfaceKey(dpId));
408     }
409
410     private InstanceIdentifier<TunnelInterface> getUnderlayNetworkTunnelIdentifier(String underlayNetwork,
411             BigInteger dpId, String tunnelInterface) {
412         return InstanceIdentifier.create(UnderlayNetworks.class)
413                 .child(UnderlayNetwork.class, new UnderlayNetworkKey(underlayNetwork))
414                 .child(DpnToInterface.class, new DpnToInterfaceKey(dpId))
415                 .child(TunnelInterface.class, new TunnelInterfaceKey(tunnelInterface));
416     }
417
418     private InstanceIdentifier<PolicyProfile> getPolicyClassifierIdentifier(String policyClassifier) {
419         return InstanceIdentifier.create(PolicyProfiles.class).child(PolicyProfile.class,
420                 new PolicyProfileKey(policyClassifier));
421     }
422
423     private InstanceIdentifier<Ace> getAceIdentifier(String aclName, String ruleName) {
424         return InstanceIdentifier.create(AccessLists.class).child(Acl.class, new AclKey(aclName, PolicyAcl.class))
425                 .child(AccessListEntries.class).child(Ace.class, new AceKey(ruleName));
426     }
427
428     private KeyedInstanceIdentifier<AceRule, AceRuleKey> getPolicyClassifierAceIdentifier(String policyClassifier,
429             String aclName, String ruleName) {
430         return InstanceIdentifier.create(PolicyProfiles.class)
431                 .child(PolicyProfile.class, new PolicyProfileKey(policyClassifier))
432                 .child(PolicyAclRule.class, new PolicyAclRuleKey(aclName))
433                 .child(AceRule.class, new AceRuleKey(ruleName));
434     }
435
436     private InstanceIdentifier<
437             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network
438                     .PolicyProfile> getUnderlayNetworkPolicyClassifierIdentifier(String policyClassifier,
439                             String underlayNetwork) {
440         return InstanceIdentifier.create(UnderlayNetworks.class)
441                 .child(UnderlayNetwork.class, new UnderlayNetworkKey(underlayNetwork))
442                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks
443                         .underlay.network.PolicyProfile.class, new org.opendaylight.yang.gen.v1.urn.opendaylight
444                         .netvirt.policy.rev170207.underlay.networks.underlay.network
445                         .PolicyProfileKey(policyClassifier));
446     }
447
448     public List<BigInteger> getUnderlayNetworkDpns(String underlayNetwork) {
449         return getDpnsFromDpnToInterfaces(getUnderlayNetworkDpnToInterfaces(underlayNetwork));
450     }
451
452     public List<BigInteger> getUnderlayNetworkRemoteDpns(String underlayNetwork) {
453         return getRemoteDpnsFromDpnToInterfaces(getUnderlayNetworkDpnToInterfaces(underlayNetwork));
454     }
455
456
457     public Optional<Integer> getLogicalTunnelLportTag(BigInteger srcDpId, BigInteger dstDpId) {
458         Optional<String> logicalTunnelNameOpt = getLogicalTunnelName(srcDpId, dstDpId);
459         if (!logicalTunnelNameOpt.isPresent()) {
460             LOG.debug("Failed to get logical tunnel for source DPN {} dst DPN {}", srcDpId, dstDpId);
461             return Optional.absent();
462         }
463
464         String logicalTunnelName = logicalTunnelNameOpt.get();
465         InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(logicalTunnelName);
466         if (interfaceInfo == null) {
467             LOG.debug("Failed to get interface info for logical tunnel {}", logicalTunnelName);
468             return Optional.absent();
469         }
470
471         return Optional.of(interfaceInfo.getInterfaceTag());
472     }
473
474     public Optional<String> getLogicalTunnelName(BigInteger srcDpId, BigInteger dstDpId) {
475         Future<RpcResult<GetTunnelInterfaceNameOutput>> tunnelInterfaceOutput = itmRpcService
476                 .getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder().setSourceDpid(srcDpId)
477                         .setDestinationDpid(dstDpId).setTunnelType(TunnelTypeLogicalGroup.class).build());
478         try {
479             if (tunnelInterfaceOutput.get().isSuccessful()) {
480                 return Optional.of(tunnelInterfaceOutput.get().getResult().getInterfaceName());
481             }
482         } catch (InterruptedException | ExecutionException e) {
483             LOG.error("Error in RPC call getTunnelInterfaceName {} for source DPN {} dst DPN {}", srcDpId, dstDpId);
484         }
485
486         return Optional.absent();
487     }
488
489
490     public Optional<String> getVlanMemberInterface(String trunkInterface, VlanId vlanId) {
491         List<Interface> vlanMemberInterfaces = interfaceManager.getChildInterfaces(trunkInterface);
492         if (vlanMemberInterfaces == null || vlanMemberInterfaces.isEmpty()) {
493             LOG.debug("No child interfaces found for trunk {}", trunkInterface);
494             return Optional.absent();
495         }
496
497         return vlanMemberInterfaces.stream()
498                 .filter(iface -> isVlanMemberInterface(iface, vlanId))
499                 .findFirst()
500                 .map(Interface::getName)
501                 .map(Optional::of)
502                 .orElseGet(Optional::absent);
503     }
504
505     private boolean isVlanMemberInterface(Interface iface, VlanId vlanId) {
506         IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
507         if (l2vlan == null || !L2vlanMode.TrunkMember.equals(l2vlan.getL2vlanMode())) {
508             LOG.warn("Interface {} is not VLAN member", iface.getName());
509             return false;
510         }
511
512         return Objects.equals(vlanId, l2vlan.getVlanId());
513     }
514 }