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