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