Fix IInterfaceManager.getBridgeRefEntryMap() return type
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / InterfacemgrProvider.java
1 /*
2  * Copyright (c) 2016, 2018 Ericsson India Global Services Pvt Ltd. 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 package org.opendaylight.genius.interfacemanager;
9
10 import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
11
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.concurrent.Callable;
18 import java.util.concurrent.ConcurrentHashMap;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.Future;
21 import javax.annotation.PreDestroy;
22 import javax.inject.Inject;
23 import javax.inject.Singleton;
24 import org.apache.aries.blueprint.annotation.service.Reference;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.opendaylight.genius.datastoreutils.ExpectedDataObjectNotFoundException;
27 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
28 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
29 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
30 import org.opendaylight.genius.interfacemanager.diagstatus.IfmDiagStatusProvider;
31 import org.opendaylight.genius.interfacemanager.exceptions.InterfaceAlreadyExistsException;
32 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
33 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo.InterfaceAdminState;
34 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
35 import org.opendaylight.genius.interfacemanager.listeners.InternalTunnelCache;
36 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils;
37 import org.opendaylight.genius.interfacemanager.rpcservice.InterfaceManagerRpcService;
38 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
39 import org.opendaylight.genius.mdsalutil.ActionInfo;
40 import org.opendaylight.infrautils.diagstatus.ServiceState;
41 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
42 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
43 import org.opendaylight.mdsal.binding.api.DataBroker;
44 import org.opendaylight.mdsal.binding.api.ReadTransaction;
45 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
46 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
47 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
48 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
49 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
50 import org.opendaylight.mdsal.eos.binding.api.Entity;
51 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipCandidateRegistration;
52 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
53 import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.config.rev160406.IfmConfig;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternal;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternalBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEndpointIpForDpnInput;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEndpointIpForDpnInputBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEndpointIpForDpnOutput;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInput;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInputBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceOutput;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
96 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
97 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
98 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
99 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
100 import org.opendaylight.yangtools.yang.common.RpcResult;
101 import org.opendaylight.yangtools.yang.common.Uint64;
102 import org.slf4j.Logger;
103 import org.slf4j.LoggerFactory;
104
105 @Singleton
106 public class InterfacemgrProvider implements AutoCloseable, IInterfaceManager {
107     private static final Logger LOG = LoggerFactory.getLogger(InterfacemgrProvider.class);
108
109     private final DataBroker dataBroker;
110     private final ManagedNewTransactionRunner txRunner;
111     private final IdManagerService idManager;
112     private final InterfaceManagerRpcService interfaceManagerRpcService;
113     private final EntityOwnershipService entityOwnershipService;
114     private final JobCoordinator coordinator;
115     private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
116     private final InterfaceMetaUtils interfaceMetaUtils;
117     private final IfmConfig ifmConfig;
118     private final IfmDiagStatusProvider ifmStatusProvider;
119     private Map<String, OvsdbTerminationPointAugmentation> ifaceToTpMap;
120     private Map<String, InstanceIdentifier<Node>> ifaceToNodeIidMap;
121     private Map<InstanceIdentifier<Node>, OvsdbBridgeAugmentation> nodeIidToBridgeMap;
122     private EntityOwnershipCandidateRegistration configEntityCandidate;
123     private EntityOwnershipCandidateRegistration bindingEntityCandidate;
124     private final InternalTunnelCache internalTunnelCache;
125
126     @Inject
127     public InterfacemgrProvider(@Reference final DataBroker dataBroker,
128                                 final EntityOwnershipService entityOwnershipService,
129                                 final IdManagerService idManager,
130                                 final InterfaceManagerRpcService interfaceManagerRpcService,
131                                 @Reference final JobCoordinator coordinator,
132                                 final InterfaceManagerCommonUtils interfaceManagerCommonUtils,
133                                 final InterfaceMetaUtils interfaceMetaUtils,
134                                 final IfmConfig ifmConfig,
135                                 final IfmDiagStatusProvider ifmStatusProvider,
136                                 final InternalTunnelCache internalTunnelCache) {
137         this.dataBroker = dataBroker;
138         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
139         this.entityOwnershipService = entityOwnershipService;
140         this.idManager = idManager;
141         this.interfaceManagerRpcService = interfaceManagerRpcService;
142         this.coordinator = coordinator;
143         this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
144         this.interfaceMetaUtils = interfaceMetaUtils;
145         this.ifmConfig = ifmConfig;
146         this.ifmStatusProvider = ifmStatusProvider;
147         this.internalTunnelCache = internalTunnelCache;
148         start();
149     }
150
151     @SuppressWarnings("checkstyle:IllegalCatch")
152     public void start() {
153         try {
154             createIdPool();
155             configEntityCandidate = entityOwnershipService.registerCandidate(
156                     new Entity(IfmConstants.INTERFACE_CONFIG_ENTITY, IfmConstants.INTERFACE_CONFIG_ENTITY));
157             bindingEntityCandidate = entityOwnershipService.registerCandidate(
158                     new Entity(IfmConstants.INTERFACE_SERVICE_BINDING_ENTITY,
159                             IfmConstants.INTERFACE_SERVICE_BINDING_ENTITY));
160             this.ifaceToTpMap = new ConcurrentHashMap<>();
161             this.ifaceToNodeIidMap = new ConcurrentHashMap<>();
162             this.nodeIidToBridgeMap = new ConcurrentHashMap<>();
163             ifmStatusProvider.reportStatus(ServiceState.OPERATIONAL);
164             LOG.info("InterfacemgrProvider Started");
165         } catch (CandidateAlreadyRegisteredException e) {
166             LOG.error("Failed to register entity {} with EntityOwnershipService", e.getEntity());
167             ifmStatusProvider.reportStatus(e);
168         } catch (InterruptedException | ExecutionException e) {
169             LOG.error("Failed to create idPool for InterfaceMgr", e);
170         }
171     }
172
173     @Override
174     @PreDestroy
175     public void close() throws Exception {
176         if (configEntityCandidate != null) {
177             configEntityCandidate.close();
178         }
179
180         if (bindingEntityCandidate != null) {
181             bindingEntityCandidate.close();
182         }
183         ifmStatusProvider.reportStatus(ServiceState.UNREGISTERED);
184         LOG.info("InterfacemgrProvider Closed");
185     }
186
187     public EntityOwnershipService getEntityOwnershipService() {
188         return entityOwnershipService;
189     }
190
191     public DataBroker getDataBroker() {
192         return this.dataBroker;
193     }
194
195     private void createIdPool() throws ExecutionException, InterruptedException {
196         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(IfmConstants.IFM_IDPOOL_NAME)
197                 .setLow(IfmConstants.IFM_ID_POOL_START).setHigh(IfmConstants.IFM_ID_POOL_END).build();
198         // TODO: Error handling
199         ListenableFuture<RpcResult<CreateIdPoolOutput>> result = idManager.createIdPool(createPool);
200         if (result != null && result.get().isSuccessful()) {
201             LOG.debug("Created IdPool for InterfaceMgr");
202         }
203     }
204
205     @Override
206     public Long getPortForInterface(String ifName) {
207         GetPortFromInterfaceInput input = new GetPortFromInterfaceInputBuilder().setIntfName(ifName).build();
208         Future<RpcResult<GetPortFromInterfaceOutput>> output = interfaceManagerRpcService.getPortFromInterface(input);
209         try {
210             RpcResult<GetPortFromInterfaceOutput> port = output.get();
211             if (port.isSuccessful()) {
212                 return port.getResult().getPortno().toJava();
213             }
214         } catch (NullPointerException | InterruptedException | ExecutionException e) {
215             LOG.warn("Exception when getting port for interface", e);
216         }
217         return null;
218     }
219
220     @Override
221     public Long getPortForInterface(Interface intf) {
222         GetPortFromInterfaceInput input = new GetPortFromInterfaceInputBuilder().setIntfName(intf.getName()).build();
223         Future<RpcResult<GetPortFromInterfaceOutput>> output = interfaceManagerRpcService.getPortFromInterface(input);
224         try {
225             RpcResult<GetPortFromInterfaceOutput> port = output.get();
226             if (port.isSuccessful()) {
227                 return port.getResult().getPortno().toJava();
228             }
229         } catch (NullPointerException | InterruptedException | ExecutionException e) {
230             LOG.warn("Exception when getting port for interface", e);
231         }
232         return null;
233     }
234
235     @Override
236     public InterfaceInfo getInterfaceInfo(String interfaceName) {
237
238         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
239             .ietf.interfaces.rev140508.interfaces.state.Interface ifState = interfaceManagerCommonUtils
240                 .getInterfaceState(interfaceName);
241
242         if (ifState == null) {
243             LOG.debug("Interface {} is not present", interfaceName);
244             return null;
245         }
246
247         Interface intf = interfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName));
248         if (intf == null) {
249             LOG.warn("Interface {} doesn't exist in config datastore", interfaceName);
250             return null;
251         }
252
253         NodeConnectorId ncId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(intf.getName(),
254                 interfaceManagerCommonUtils);
255         InterfaceInfo.InterfaceType interfaceType = IfmUtil.getInterfaceType(intf);
256         InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName);
257         Integer portNo = org.opendaylight.genius.interfacemanager.globals.IfmConstants.INVALID_PORT_NO;
258         final Uint64 dpId;
259         if (ncId != null) {
260             dpId = IfmUtil.getDpnFromNodeConnectorId(ncId);
261             portNo = Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId));
262         } else {
263             dpId = null;
264         }
265         if (interfaceType == InterfaceInfo.InterfaceType.VLAN_INTERFACE) {
266             interfaceInfo = IfmUtil.getVlanInterfaceInfo(intf, dpId);
267         } else if (interfaceType == InterfaceInfo.InterfaceType.UNKNOWN_INTERFACE) {
268             LOG.error("Type of Interface {} is unknown", interfaceName);
269             return null;
270         }
271         interfaceInfo.setDpId(dpId);
272         interfaceInfo.setPortNo(portNo);
273         interfaceInfo.setAdminState(intf.isEnabled() ? InterfaceAdminState.ENABLED : InterfaceAdminState.DISABLED);
274         interfaceInfo.setInterfaceName(interfaceName);
275         Integer lportTag = ifState.getIfIndex();
276         interfaceInfo.setInterfaceTag(lportTag);
277         interfaceInfo.setInterfaceType(interfaceType);
278         interfaceInfo.setGroupId(IfmUtil.getGroupId(lportTag, interfaceType));
279         interfaceInfo.setOpState(InterfaceInfo.InterfaceOpState.fromModel(ifState.getOperStatus()));
280         PhysAddress phyAddress = ifState.getPhysAddress();
281         if (phyAddress != null) {
282             interfaceInfo.setMacAddress(ifState.getPhysAddress().getValue());
283         }
284
285         return interfaceInfo;
286
287     }
288
289     @Override
290     public InterfaceInfo getInterfaceInfoFromOperationalDataStore(String interfaceName,
291             InterfaceInfo.InterfaceType interfaceType) {
292         InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName);
293         org.opendaylight.yang.gen.v1.urn
294             .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
295                 interfaceManagerCommonUtils.getInterfaceState(interfaceName);
296         if (ifState == null) {
297             LOG.debug("Interface {} is not present", interfaceName);
298             return null;
299         }
300         NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(ifState);
301         if (ncId != null) {
302             interfaceInfo.setDpId(IfmUtil.getDpnFromNodeConnectorId(ncId));
303             interfaceInfo.setPortNo(Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId)));
304         }
305         interfaceInfo.setAdminState(ifState.getAdminStatus() == AdminStatus.Up ? InterfaceAdminState.ENABLED
306                 : InterfaceAdminState.DISABLED);
307         interfaceInfo.setInterfaceName(interfaceName);
308         Integer lportTag = ifState.getIfIndex();
309         interfaceInfo.setInterfaceTag(lportTag);
310         interfaceInfo.setInterfaceType(interfaceType);
311         interfaceInfo.setGroupId(IfmUtil.getGroupId(lportTag, interfaceType));
312         interfaceInfo.setOpState(InterfaceInfo.InterfaceOpState.fromModel(ifState.getOperStatus()));
313         PhysAddress phyAddress = ifState.getPhysAddress();
314         if (phyAddress != null) {
315             interfaceInfo.setMacAddress(ifState.getPhysAddress().getValue());
316         }
317         return interfaceInfo;
318     }
319
320     @Override
321     public InterfaceInfo getInterfaceInfoFromOperationalDataStore(String interfaceName) {
322         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
323             .ietf.interfaces.rev140508.interfaces.state.Interface ifState = interfaceManagerCommonUtils
324                 .getInterfaceState(interfaceName);
325         if (ifState == null) {
326             LOG.debug("Interface {} is not present", interfaceName);
327             return null;
328         }
329
330         return populateInterfaceInfo(interfaceName, ifState);
331     }
332
333     public InterfaceInfo populateInterfaceInfo(String interfaceName,
334             org.opendaylight.yang.gen.v1.urn
335                 .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
336         InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName);
337         NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(ifState);
338         if (ncId != null) {
339             if (Tunnel.class.equals(ifState.getType())) {
340                 interfaceInfo.setPortName(interfaceName);
341             } else {
342                 Interface iface = interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName);
343                 if (iface != null) {
344                     ParentRefs parentRefs = iface.augmentation(ParentRefs.class);
345                     interfaceInfo.setPortName(parentRefs.getParentInterface());
346                 }
347             }
348             interfaceInfo.setDpId(IfmUtil.getDpnFromNodeConnectorId(ncId));
349             interfaceInfo.setPortNo(Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId)));
350         }
351         interfaceInfo.setAdminState(ifState.getAdminStatus() == AdminStatus.Up ? InterfaceAdminState.ENABLED
352                 : InterfaceAdminState.DISABLED);
353         interfaceInfo.setInterfaceName(interfaceName);
354         Integer lportTag = ifState.getIfIndex();
355         if (lportTag != null) {
356             interfaceInfo.setInterfaceTag(lportTag);
357         }
358         interfaceInfo.setOpState(InterfaceInfo.InterfaceOpState.fromModel(ifState.getOperStatus()));
359         PhysAddress phyAddress = ifState.getPhysAddress();
360         if (phyAddress != null) {
361             interfaceInfo.setMacAddress(ifState.getPhysAddress().getValue());
362         }
363         return interfaceInfo;
364     }
365
366     @Override
367     public InterfaceInfo getInterfaceInfoFromOperationalDSCache(String interfaceName) {
368         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
369             .ietf.interfaces.rev140508.interfaces.state.Interface ifState = interfaceManagerCommonUtils
370                 .getInterfaceStateFromCache(interfaceName);
371         if (ifState == null) {
372             LOG.warn("Interface {} is not present", interfaceName);
373             return null;
374         }
375         return populateInterfaceInfo(interfaceName, ifState);
376     }
377
378     @Override
379     public Interface getInterfaceInfoFromConfigDataStore(String interfaceName) {
380         return interfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName));
381     }
382
383     @Override
384     public Interface getInterfaceInfoFromConfigDataStore(ReadTransaction tx, String interfaceName)
385             throws ExecutionException, InterruptedException {
386         return interfaceManagerCommonUtils.getInterfaceFromConfigDS(tx, new InterfaceKey(interfaceName));
387     }
388
389     @Override
390     public void createVLANInterface(String interfaceName, String portName, Uint64 dpId, Integer vlanId,
391             String description, IfL2vlan.L2vlanMode l2vlanMode) throws InterfaceAlreadyExistsException {
392         createVLANInterface(interfaceName, portName, vlanId, description, l2vlanMode);
393     }
394
395     @Override
396     public ListenableFuture<?> createVLANInterface(String interfaceName, String portName, Integer vlanId,
397             String description, IfL2vlan.L2vlanMode l2vlanMode) throws InterfaceAlreadyExistsException {
398         return createVLANInterface(interfaceName, portName, vlanId, description, l2vlanMode, false);
399     }
400
401     @Override
402     public void createVLANInterface(String interfaceName, String portName, Uint64 dpId, Integer vlanId,
403             String description, IfL2vlan.L2vlanMode l2vlanMode, boolean isExternal)
404             throws InterfaceAlreadyExistsException {
405         createVLANInterface(interfaceName, portName, vlanId, description, l2vlanMode, isExternal);
406     }
407
408     @Override
409     public ListenableFuture<?> createVLANInterface(String interfaceName, String portName, Integer vlanId,
410                                                       String description, IfL2vlan.L2vlanMode l2vlanMode,
411                                                       boolean isExternal)
412             throws InterfaceAlreadyExistsException {
413
414         LOG.info("Create VLAN interface : {}", interfaceName);
415         Interface interfaceOptional = interfaceManagerCommonUtils
416                 .getInterfaceFromConfigDS(new InterfaceKey(interfaceName));
417         if (interfaceOptional != null) {
418             LOG.debug("VLAN interface already exists {} ", interfaceOptional.getDescription());
419             throw new InterfaceAlreadyExistsException(interfaceOptional.getName());
420         }
421         IfL2vlanBuilder l2vlanBuilder = new IfL2vlanBuilder().setL2vlanMode(l2vlanMode);
422         if (vlanId != null && vlanId > 0) {
423             l2vlanBuilder.setVlanId(new VlanId(vlanId));
424         }
425         InterfaceBuilder interfaceBuilder = new InterfaceBuilder().setEnabled(true).setName(interfaceName)
426                 .setType(L2vlan.class).addAugmentation(l2vlanBuilder.build())
427                 .addAugmentation(new ParentRefsBuilder().setParentInterface(portName).build())
428                 .setDescription(description);
429         if (isExternal) {
430             interfaceBuilder.addAugmentation(new IfExternalBuilder().setExternal(true).build());
431         }
432         InstanceIdentifier<Interface> interfaceIId = InterfaceManagerCommonUtils
433                 .getInterfaceIdentifier(new InterfaceKey(interfaceName));
434         return LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
435             tx -> tx.mergeParentStructurePut(interfaceIId, interfaceBuilder.build())),
436             LOG, "Failed to (async) write {}", interfaceIId);
437     }
438
439     private boolean isServiceBoundOnInterface(short servicePriority, String interfaceName,
440             Class<? extends ServiceModeBase> serviceMode) {
441         InstanceIdentifier<BoundServices> boundServicesIId = IfmUtil.buildBoundServicesIId(servicePriority,
442                 interfaceName, serviceMode);
443         try {
444             return SingleTransactionDataBroker
445                     .syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, boundServicesIId).isPresent();
446         } catch (ExecutionException | InterruptedException e) {
447             LOG.warn("Error while reading [{}]", boundServicesIId, e);
448             return false;
449         }
450     }
451
452     @Override
453     public boolean isServiceBoundOnInterfaceForIngress(short servicePriority, String interfaceName) {
454         return isServiceBoundOnInterface(servicePriority, interfaceName, ServiceModeIngress.class);
455     }
456
457     @Override
458     public boolean isServiceBoundOnInterfaceForEgress(short servicePriority, String interfaceName) {
459         return isServiceBoundOnInterface(servicePriority, interfaceName, ServiceModeEgress.class);
460     }
461
462     @Override
463     public void bindService(String interfaceName, Class<? extends ServiceModeBase> serviceMode,
464             BoundServices serviceInfo) {
465         bindService(interfaceName, serviceMode, serviceInfo, /* WriteTransaction */ null);
466     }
467
468     @Override
469     public void bindService(String interfaceName, Class<? extends ServiceModeBase> serviceMode,
470             BoundServices serviceInfo, TypedWriteTransaction<Configuration> tx) {
471         if (tx == null) {
472             LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
473                 wtx -> IfmUtil.bindService(wtx, interfaceName, serviceInfo, serviceMode)), LOG,
474                 "Error binding the InterfacemgrProvider service");
475         } else {
476             IfmUtil.bindService(tx, interfaceName, serviceInfo, serviceMode);
477         }
478     }
479
480     @Override
481     public void unbindService(String interfaceName, Class<? extends ServiceModeBase> serviceMode,
482             BoundServices serviceInfo) {
483         IfmUtil.unbindService(txRunner, coordinator, interfaceName,
484                 FlowBasedServicesUtils.buildServiceId(interfaceName,
485                     serviceInfo.getServicePriority().toJava(), serviceMode));
486     }
487
488     @Override
489     public Uint64 getDpnForInterface(Interface intrf) {
490         return getDpnForInterface(intrf.getName());
491     }
492
493     @Override
494     public Uint64 getDpnForInterface(String ifName) {
495         GetDpidFromInterfaceInput input = new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
496         Future<RpcResult<GetDpidFromInterfaceOutput>> output = interfaceManagerRpcService.getDpidFromInterface(input);
497         try {
498             RpcResult<GetDpidFromInterfaceOutput> dpn = output.get();
499             if (dpn.isSuccessful()) {
500                 return dpn.getResult().getDpid();
501             }
502         } catch (NullPointerException | InterruptedException | ExecutionException e) {
503             LOG.warn("Exception when getting port for interface", e);
504         }
505         return null;
506     }
507
508     @Override
509     public String getEndpointIpForDpn(Uint64 dpnId) {
510         GetEndpointIpForDpnInput input = new GetEndpointIpForDpnInputBuilder().setDpid(dpnId).build();
511         Future<RpcResult<GetEndpointIpForDpnOutput>> output = interfaceManagerRpcService.getEndpointIpForDpn(input);
512         try {
513             RpcResult<GetEndpointIpForDpnOutput> ipForDpnOutputRpcResult = output.get();
514             if (ipForDpnOutputRpcResult.isSuccessful()) {
515                 List<IpAddress> localIps = ipForDpnOutputRpcResult.getResult().getLocalIps();
516                 if (localIps != null && !localIps.isEmpty()) {
517                     return localIps.get(0).getIpv4Address().getValue();
518                 }
519             }
520         } catch (NullPointerException | InterruptedException | ExecutionException e) {
521             LOG.warn("Exception when getting port for interface", e);
522         }
523         return null;
524     }
525
526     @Override
527     public List<ActionInfo> getInterfaceEgressActions(String ifName) {
528         return IfmUtil.getEgressActionInfosForInterface(ifName, 0, interfaceManagerCommonUtils, false);
529     }
530
531     @Override
532     public List<Interface> getVlanInterfaces() {
533         return interfaceManagerCommonUtils.getAllVlanInterfacesFromCache();
534     }
535
536     @Override
537     public List<Interface> getVxlanInterfaces() {
538         return interfaceManagerCommonUtils.getAllTunnelInterfacesFromCache();
539     }
540
541     @Override
542     public List<Interface> getChildInterfaces(String parentInterface) {
543         try (ReadTransaction tx = dataBroker.newReadOnlyTransaction()) {
544             return getChildInterfaces(tx, parentInterface);
545         } catch (ExecutionException | InterruptedException e) {
546             LOG.error("Error retrieving child interfaces of {} from config", parentInterface, e);
547             throw new RuntimeException("Error retrieving child interfaces of " + parentInterface + " from config", e);
548         }
549     }
550
551     @Override
552     public List<Interface> getChildInterfaces(ReadTransaction tx, String parentInterface) throws
553             ExecutionException, InterruptedException {
554         InterfaceParentEntry parentEntry = interfaceMetaUtils.getInterfaceParentEntryFromConfigDS(tx, parentInterface);
555         if (parentEntry == null) {
556             LOG.debug("No parent entry found for {}", parentInterface);
557             return Collections.emptyList();
558         }
559
560         @Nullable Map<InterfaceChildEntryKey, InterfaceChildEntry> childEntries = parentEntry.getInterfaceChildEntry();
561         if (childEntries == null || childEntries.isEmpty()) {
562             LOG.debug("No child entries found for parent {}", parentInterface);
563             return Collections.emptyList();
564         }
565
566         List<Interface> childInterfaces = new ArrayList<>();
567         for (InterfaceChildEntry childEntry : childEntries.values()) {
568             String interfaceName = childEntry.getChildInterface();
569             Interface iface = interfaceManagerCommonUtils.getInterfaceFromConfigDS(tx, interfaceName);
570             if (iface != null) {
571                 childInterfaces.add(iface);
572             } else {
573                 LOG.debug("Child interface {} not found in config DS for parent interface {}", interfaceName,
574                         parentInterface);
575             }
576         }
577
578         LOG.trace("Found child interfaces {} for parent {}", childInterfaces, parentInterface);
579         return childInterfaces;
580     }
581
582     @Override
583     public boolean isExternalInterface(String interfaceName) {
584         return isExternalInterface(getInterfaceInfoFromConfigDataStore(interfaceName));
585     }
586
587     @Override
588     public boolean isExternalInterface(ReadTransaction tx, String interfaceName) throws
589             ExecutionException, InterruptedException {
590         return isExternalInterface(getInterfaceInfoFromConfigDataStore(tx, interfaceName));
591     }
592
593     private boolean isExternalInterface(Interface iface) {
594         if (iface == null) {
595             return false;
596         }
597
598         IfExternal ifExternal = iface.augmentation(IfExternal.class);
599         return ifExternal != null && Boolean.TRUE.equals(ifExternal.isExternal());
600     }
601
602     @Override
603     public String getPortNameForInterface(NodeConnectorId nodeConnectorId, String interfaceName) {
604         return InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId, interfaceName);
605     }
606
607     @Override
608     public String getPortNameForInterface(String dpnId, String interfaceName) {
609         return InterfaceManagerCommonUtils.getPortNameForInterface(dpnId, interfaceName);
610     }
611
612     @Override
613     public Map<String, OvsdbTerminationPointAugmentation> getTerminationPointCache() {
614         return new ConcurrentHashMap<>(this.ifaceToTpMap);
615     }
616
617     @Override
618     public Map<String, OperStatus> getBfdStateCache() {
619         return interfaceManagerCommonUtils.getBfdStateMap();
620     }
621
622     public void addTerminationPointForInterface(String interfaceName,
623             OvsdbTerminationPointAugmentation terminationPoint) {
624         if (interfaceName != null && terminationPoint != null) {
625             LOG.debug("Adding TerminationPoint {} to cache for Interface {}", terminationPoint.getName(),
626                     interfaceName);
627             ifaceToTpMap.put(interfaceName, terminationPoint);
628         }
629     }
630
631     public OvsdbTerminationPointAugmentation getTerminationPoint(String interfaceName) {
632         return ifaceToTpMap.get(interfaceName);
633     }
634
635     public void removeTerminationPointForInterface(String interfaceName) {
636         LOG.debug("Removing TerminationPoint from cache for Interface {}", interfaceName);
637         if (interfaceName != null) {
638             ifaceToTpMap.remove(interfaceName);
639         }
640     }
641
642     public void addNodeIidForInterface(String interfaceName, InstanceIdentifier<Node> nodeIid) {
643         if (interfaceName != null && nodeIid != null) {
644             ifaceToNodeIidMap.put(interfaceName, nodeIid);
645         }
646     }
647
648     public void removeNodeIidForInterface(String interfaceName) {
649         if (interfaceName != null) {
650             ifaceToNodeIidMap.remove(interfaceName);
651         }
652     }
653
654     public InstanceIdentifier<Node> getNodeIidForInterface(String interfaceName) {
655         if (interfaceName != null) {
656             return ifaceToNodeIidMap.get(interfaceName);
657         }
658         return null;
659     }
660
661     private OvsdbBridgeAugmentation getBridgeForInterface(String interfaceName,
662             InstanceIdentifier<Node> nodeInstanceId) {
663         InstanceIdentifier<Node> nodeIid = nodeInstanceId;
664         if (nodeIid == null) {
665             nodeIid = getNodeIidForInterface(interfaceName);
666         }
667         return getBridgeForNodeIid(nodeIid);
668     }
669
670     public String getDpidForInterface(String interfaceName) {
671         return getDpidForInterface(interfaceName, null);
672     }
673
674     public String getDpidForInterface(String interfaceName, InstanceIdentifier<Node> nodeInstanceId) {
675         OvsdbBridgeAugmentation bridge = getBridgeForInterface(interfaceName, nodeInstanceId);
676         if (bridge != null) {
677             Uint64 dpid = IfmUtil.getDpnId(bridge.getDatapathId());
678             if (dpid != null && dpid.longValue() != 0) {
679                 return String.valueOf(dpid);
680             }
681         }
682         return null;
683     }
684
685     public void addBridgeForNodeIid(InstanceIdentifier<Node> nodeIid, OvsdbBridgeAugmentation bridge) {
686         if (nodeIid != null && bridge != null) {
687             nodeIidToBridgeMap.put(nodeIid, bridge);
688         }
689     }
690
691     public void removeBridgeForNodeIid(InstanceIdentifier<Node> nodeIid) {
692         if (nodeIid != null) {
693             nodeIidToBridgeMap.remove(nodeIid);
694         }
695     }
696
697     public OvsdbBridgeAugmentation getBridgeForNodeIid(InstanceIdentifier<Node> nodeIid) {
698         if (nodeIid == null) {
699             return null;
700         }
701
702         OvsdbBridgeAugmentation ret = nodeIidToBridgeMap.get(nodeIid);
703         if (ret != null) {
704             return ret;
705         }
706
707         LOG.info("Node {} not found in cache, reading from md-sal", nodeIid);
708         Node node;
709         try {
710             node = SingleTransactionDataBroker.syncRead(
711                                         dataBroker, LogicalDatastoreType.OPERATIONAL, nodeIid);
712         } catch (ExpectedDataObjectNotFoundException e) {
713             LOG.error("Failed to read Node for {} ", nodeIid, e);
714             return null;
715         }
716
717         OvsdbBridgeAugmentation bridge = node.augmentation(OvsdbBridgeAugmentation.class);
718         if (bridge == null) {
719             LOG.error("Node {} has no bridge augmentation", nodeIid);
720             return null;
721         }
722
723         addBridgeForNodeIid(nodeIid, bridge);
724         return bridge;
725     }
726
727     @Override
728     public String getParentRefNameForInterface(String interfaceName) {
729         String parentRefName = null;
730
731         String dpnId = getDpidForInterface(interfaceName, null);
732         OvsdbTerminationPointAugmentation ovsdbTp = getTerminationPoint(interfaceName);
733         if (ovsdbTp != null) {
734             if (dpnId == null) {
735                 LOG.error("Got NULL dpnId when looking for TP with external ID {}", interfaceName);
736                 return null;
737             }
738             parentRefName = getPortNameForInterface(dpnId, ovsdbTp.getName());
739             LOG.debug("Building parent ref for interface {}, using parentRefName {} acquired by external ID",
740                     interfaceName, parentRefName);
741         } else {
742             LOG.debug("Skipping parent ref for interface {}, as there is no termination point that references "
743                     + "this interface yet.", interfaceName);
744         }
745
746         return parentRefName;
747     }
748
749     @Override
750     public void updateInterfaceParentRef(String interfaceName, String parentInterface) {
751         // This should generally be called by EOS Owner for
752         // INTERFACE_CONFIG_ENTITY - runOnlyInLeaderNode()
753         updateInterfaceParentRef(interfaceName, parentInterface, true);
754     }
755
756     @Override
757     public void updateInterfaceParentRef(String interfaceName, String parentInterface,
758             boolean readInterfaceBeforeWrite) {
759         // This should generally be called by EOS Owner for
760         // INTERFACE_CONFIG_ENTITY - runOnlyInLeaderNode()
761         if (interfaceName == null) {
762             return;
763         }
764
765         ParentRefUpdateWorker parentRefUpdateWorker = new ParentRefUpdateWorker(interfaceName, parentInterface,
766                 readInterfaceBeforeWrite);
767         coordinator.enqueueJob(interfaceName, parentRefUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
768     }
769
770     public class ParentRefUpdateWorker implements Callable<List<? extends ListenableFuture<?>>> {
771         String interfaceName;
772         String parentInterfaceName;
773         Boolean readInterfaceBeforeWrite;
774
775         public ParentRefUpdateWorker(String interfaceName, String parentInterfaceName,
776                 boolean readInterfaceBeforeWrite) {
777             this.interfaceName = interfaceName;
778             this.parentInterfaceName = parentInterfaceName;
779             this.readInterfaceBeforeWrite = readInterfaceBeforeWrite;
780         }
781
782         @Override
783         public List<? extends ListenableFuture<?>> call() {
784             if (readInterfaceBeforeWrite) {
785                 Interface iface = interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName);
786                 if (iface == null) {
787                     LOG.debug("Interface doesn't exist in config DS - no need to update parentRef, skipping");
788                     return null;
789                 }
790             }
791             return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
792                 tx -> IfmUtil.updateInterfaceParentRef(tx, interfaceName, parentInterfaceName)));
793         }
794     }
795
796     @Override
797     public OvsdbTerminationPointAugmentation getTerminationPointForInterface(String interfaceName) {
798         return getTerminationPoint(interfaceName);
799     }
800
801     @Override
802     public OvsdbBridgeAugmentation getOvsdbBridgeForInterface(String interfaceName) {
803         return getBridgeForInterface(interfaceName, null);
804     }
805
806     @Override
807     public OvsdbBridgeAugmentation getOvsdbBridgeForNodeIid(InstanceIdentifier<Node> nodeIid) {
808         return getBridgeForNodeIid(nodeIid);
809     }
810
811     @Override
812     /**
813      * Get all termination points on a given DPN.
814      * This API uses read on Operational DS. If there are perf issues in cluster
815      * setup, we can consider caching later.
816      *
817      * @param dpnId
818      *            Datapath Node Identifier
819      *
820      * @return If the data at the supplied path exists, returns a list of all termination point
821      *         Augmentations
822      */
823     public List<OvsdbTerminationPointAugmentation> getPortsOnBridge(Uint64 dpnId) {
824         List<OvsdbTerminationPointAugmentation> ports = new ArrayList<>();
825         Map<TerminationPointKey, TerminationPoint> portList = interfaceMetaUtils.getTerminationPointsOnBridge(dpnId);
826         for (TerminationPoint ovsPort : portList.values()) {
827             if (ovsPort.augmentation(OvsdbTerminationPointAugmentation.class) != null) {
828                 ports.add(ovsPort.augmentation(OvsdbTerminationPointAugmentation.class));
829             }
830         }
831         LOG.debug("Found {} ports on bridge {}", ports.size(), dpnId);
832         return ports;
833     }
834
835     /**
836      * Get all termination points of type tunnel on a given DPN.
837      *
838      * @param dpnId
839      *            Datapath Node Identifier
840      *
841      * @return If the data at the supplied path exists, returns a list of all termination point
842      *         Augmentations of type tunnel
843      */
844     @Override
845     public List<OvsdbTerminationPointAugmentation> getTunnelPortsOnBridge(Uint64 dpnId) {
846         List<OvsdbTerminationPointAugmentation> tunnelPorts = new ArrayList<>();
847         Map<TerminationPointKey, TerminationPoint> portList = interfaceMetaUtils.getTerminationPointsOnBridge(dpnId);
848         for (TerminationPoint ovsPort : portList.values()) {
849             OvsdbTerminationPointAugmentation portAug =
850                     ovsPort.augmentation(OvsdbTerminationPointAugmentation.class);
851             if (portAug != null && SouthboundUtils.isInterfaceTypeTunnel(portAug.getInterfaceType())) {
852                 tunnelPorts.add(portAug);
853             }
854         }
855
856         LOG.debug("Found {} tunnel ports on bridge {}", tunnelPorts.size(), dpnId);
857         return tunnelPorts;
858     }
859
860     /**
861      * Get all termination points by type on a given DPN.
862      *
863      * @param dpnId
864      *            Datapath Node Identifier
865      *
866      * @return If the data at the supplied path exists, returns a Map where key is interfaceType
867      *         and value is list of termination points of given type
868      */
869     @Override
870     public Map<Class<? extends InterfaceTypeBase>, List<OvsdbTerminationPointAugmentation>>
871         getPortsOnBridgeByType(Uint64 dpnId) {
872
873         Map<Class<? extends InterfaceTypeBase>, List<OvsdbTerminationPointAugmentation>> portMap;
874         portMap = new ConcurrentHashMap<>();
875         Map<TerminationPointKey, TerminationPoint> ovsPorts = interfaceMetaUtils.getTerminationPointsOnBridge(dpnId);
876         if (ovsPorts != null) {
877             for (TerminationPoint ovsPort : ovsPorts.values()) {
878                 OvsdbTerminationPointAugmentation portAug =
879                         ovsPort.augmentation(OvsdbTerminationPointAugmentation.class);
880                 if (portAug != null && portAug.getInterfaceType() != null) {
881                     portMap.computeIfAbsent(portAug.getInterfaceType(), k -> new ArrayList<>()).add(portAug);
882                 }
883             }
884         }
885         return portMap;
886     }
887
888     @Override
889     public long getLogicalTunnelSelectGroupId(int lportTag) {
890         return IfmUtil.getLogicalTunnelSelectGroupId(lportTag);
891     }
892
893     @Override
894     public boolean isItmDirectTunnelsEnabled() {
895         return ifmConfig.isItmDirectTunnels();
896     }
897
898     @Override
899     public Map<Uint64, BridgeRefEntry> getBridgeRefEntryMap() {
900         return interfaceMetaUtils.getBridgeRefEntryMap();
901     }
902
903     @Override
904     public boolean isItmOfTunnelsEnabled() {
905         return ifmConfig.isItmOfTunnels();
906     }
907
908     @Override
909     public void addInternalTunnelToCache(String tunnelName, org.opendaylight.yang.gen.v1.urn.ietf.params
910             .xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface iface) {
911         internalTunnelCache.add(tunnelName,iface);
912     }
913
914     @Override
915     public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
916             .rev140508.interfaces.state.Interface getInternalTunnelCacheInfo(String tunnelName) {
917         return internalTunnelCache.get(tunnelName);
918     }
919
920     @Override
921     public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
922             .rev140508.interfaces.state.Interface removeInternalTunnelFromCache(String tunnelName) {
923         return internalTunnelCache.remove(tunnelName);
924     }
925 }