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