2 * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.genius.interfacemanager;
10 import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
11 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.math.BigInteger;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
19 import java.util.concurrent.Callable;
20 import java.util.concurrent.ConcurrentHashMap;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.Future;
23 import javax.annotation.PostConstruct;
24 import javax.annotation.PreDestroy;
25 import javax.inject.Inject;
26 import javax.inject.Singleton;
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
29 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
30 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
31 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
32 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
33 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
34 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
35 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
36 import org.opendaylight.genius.interfacemanager.exceptions.InterfaceAlreadyExistsException;
37 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
38 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo.InterfaceAdminState;
39 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
40 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils;
41 import org.opendaylight.genius.interfacemanager.rpcservice.InterfaceManagerRpcService;
42 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
43 import org.opendaylight.genius.mdsalutil.ActionInfo;
44 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
45 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
46 import org.opendaylight.mdsal.eos.binding.api.Entity;
47 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipCandidateRegistration;
48 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
49 import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.config.rev160406.IfmConfig;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternal;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternalBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEndpointIpForDpnInput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEndpointIpForDpnInputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEndpointIpForDpnOutput;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInputBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceOutput;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
89 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
90 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
91 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
92 import org.opendaylight.yangtools.yang.common.RpcResult;
93 import org.slf4j.Logger;
94 import org.slf4j.LoggerFactory;
97 public class InterfacemgrProvider implements AutoCloseable, IInterfaceManager {
98 private static final Logger LOG = LoggerFactory.getLogger(InterfacemgrProvider.class);
100 private final DataBroker dataBroker;
101 private final ManagedNewTransactionRunner txRunner;
102 private final IdManagerService idManager;
103 private final InterfaceManagerRpcService interfaceManagerRpcService;
104 private final EntityOwnershipService entityOwnershipService;
105 private final JobCoordinator coordinator;
106 private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
107 private final InterfaceMetaUtils interfaceMetaUtils;
108 private final IfmConfig ifmConfig;
109 private Map<String, OvsdbTerminationPointAugmentation> ifaceToTpMap;
110 private Map<String, InstanceIdentifier<Node>> ifaceToNodeIidMap;
111 private Map<InstanceIdentifier<Node>, OvsdbBridgeAugmentation> nodeIidToBridgeMap;
112 private EntityOwnershipCandidateRegistration configEntityCandidate;
113 private EntityOwnershipCandidateRegistration bindingEntityCandidate;
116 public InterfacemgrProvider(final DataBroker dataBroker, final EntityOwnershipService entityOwnershipService,
117 final IdManagerService idManager, final InterfaceManagerRpcService interfaceManagerRpcService,
118 final JobCoordinator coordinator, final InterfaceManagerCommonUtils interfaceManagerCommonUtils,
119 final InterfaceMetaUtils interfaceMetaUtils, final IfmConfig ifmConfig) {
120 this.dataBroker = dataBroker;
121 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
122 this.entityOwnershipService = entityOwnershipService;
123 this.idManager = idManager;
124 this.interfaceManagerRpcService = interfaceManagerRpcService;
125 this.coordinator = coordinator;
126 this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
127 this.interfaceMetaUtils = interfaceMetaUtils;
128 this.ifmConfig = ifmConfig;
132 @SuppressWarnings("checkstyle:IllegalCatch")
133 public void start() {
136 configEntityCandidate = entityOwnershipService.registerCandidate(
137 new Entity(IfmConstants.INTERFACE_CONFIG_ENTITY, IfmConstants.INTERFACE_CONFIG_ENTITY));
138 bindingEntityCandidate = entityOwnershipService.registerCandidate(
139 new Entity(IfmConstants.INTERFACE_SERVICE_BINDING_ENTITY,
140 IfmConstants.INTERFACE_SERVICE_BINDING_ENTITY));
141 } catch (CandidateAlreadyRegisteredException e) {
142 LOG.error("Failed to register entity {} with EntityOwnershipService", e.getEntity());
145 this.ifaceToTpMap = new ConcurrentHashMap<>();
146 this.ifaceToNodeIidMap = new ConcurrentHashMap<>();
147 this.nodeIidToBridgeMap = new ConcurrentHashMap<>();
148 LOG.info("InterfacemgrProvider Started");
153 public void close() throws Exception {
154 if (configEntityCandidate != null) {
155 configEntityCandidate.close();
158 if (bindingEntityCandidate != null) {
159 bindingEntityCandidate.close();
162 LOG.info("InterfacemgrProvider Closed");
165 public EntityOwnershipService getEntityOwnershipService() {
166 return entityOwnershipService;
169 public DataBroker getDataBroker() {
170 return this.dataBroker;
173 private void createIdPool() {
174 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(IfmConstants.IFM_IDPOOL_NAME)
175 .setLow(IfmConstants.IFM_ID_POOL_START).setHigh(IfmConstants.IFM_ID_POOL_END).build();
176 // TODO: Error handling
177 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
179 if (result != null && result.get().isSuccessful()) {
180 LOG.debug("Created IdPool for InterfaceMgr");
182 } catch (InterruptedException | ExecutionException e) {
183 LOG.error("Failed to create idPool for InterfaceMgr", e);
188 public Long getPortForInterface(String ifName) {
189 GetPortFromInterfaceInput input = new GetPortFromInterfaceInputBuilder().setIntfName(ifName).build();
190 Future<RpcResult<GetPortFromInterfaceOutput>> output = interfaceManagerRpcService.getPortFromInterface(input);
192 RpcResult<GetPortFromInterfaceOutput> port = output.get();
193 if (port.isSuccessful()) {
194 return port.getResult().getPortno();
196 } catch (NullPointerException | InterruptedException | ExecutionException e) {
197 LOG.warn("Exception when getting port for interface", e);
203 public Long getPortForInterface(Interface intf) {
204 GetPortFromInterfaceInput input = new GetPortFromInterfaceInputBuilder().setIntfName(intf.getName()).build();
205 Future<RpcResult<GetPortFromInterfaceOutput>> output = interfaceManagerRpcService.getPortFromInterface(input);
207 RpcResult<GetPortFromInterfaceOutput> port = output.get();
208 if (port.isSuccessful()) {
209 return port.getResult().getPortno();
211 } catch (NullPointerException | InterruptedException | ExecutionException e) {
212 LOG.warn("Exception when getting port for interface", e);
218 public InterfaceInfo getInterfaceInfo(String interfaceName) {
220 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
221 .ietf.interfaces.rev140508.interfaces.state.Interface ifState = interfaceManagerCommonUtils
222 .getInterfaceState(interfaceName);
224 if (ifState == null) {
225 LOG.debug("Interface {} is not present", interfaceName);
229 Interface intf = interfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName));
231 LOG.error("Interface {} doesn't exist in config datastore", interfaceName);
235 NodeConnectorId ncId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(intf.getName(),
236 interfaceManagerCommonUtils);
237 InterfaceInfo.InterfaceType interfaceType = IfmUtil.getInterfaceType(intf);
238 InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName);
239 BigInteger dpId = org.opendaylight.genius.interfacemanager.globals.IfmConstants.INVALID_DPID;
240 Integer portNo = org.opendaylight.genius.interfacemanager.globals.IfmConstants.INVALID_PORT_NO;
242 dpId = IfmUtil.getDpnFromNodeConnectorId(ncId);
243 portNo = Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId));
245 if (interfaceType == InterfaceInfo.InterfaceType.VLAN_INTERFACE) {
246 interfaceInfo = IfmUtil.getVlanInterfaceInfo(intf, dpId);
247 } else if (interfaceType == InterfaceInfo.InterfaceType.UNKNOWN_INTERFACE) {
248 LOG.error("Type of Interface {} is unknown", interfaceName);
251 InterfaceInfo.InterfaceOpState opState;
252 if (ifState.getOperStatus() == OperStatus.Up) {
253 opState = InterfaceInfo.InterfaceOpState.UP;
254 } else if (ifState.getOperStatus() == OperStatus.Down) {
255 opState = InterfaceInfo.InterfaceOpState.DOWN;
257 opState = InterfaceInfo.InterfaceOpState.UNKNOWN;
259 interfaceInfo.setDpId(dpId);
260 interfaceInfo.setPortNo(portNo);
261 interfaceInfo.setAdminState(intf.isEnabled() ? InterfaceAdminState.ENABLED : InterfaceAdminState.DISABLED);
262 interfaceInfo.setInterfaceName(interfaceName);
263 Integer lportTag = ifState.getIfIndex();
264 interfaceInfo.setInterfaceTag(lportTag);
265 interfaceInfo.setInterfaceType(interfaceType);
266 interfaceInfo.setGroupId(IfmUtil.getGroupId(lportTag, interfaceType));
267 interfaceInfo.setOpState(opState);
268 PhysAddress phyAddress = ifState.getPhysAddress();
269 if (phyAddress != null) {
270 interfaceInfo.setMacAddress(ifState.getPhysAddress().getValue());
273 return interfaceInfo;
278 public InterfaceInfo getInterfaceInfoFromOperationalDataStore(String interfaceName,
279 InterfaceInfo.InterfaceType interfaceType) {
280 InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName);
281 org.opendaylight.yang.gen.v1.urn
282 .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
283 interfaceManagerCommonUtils.getInterfaceState(interfaceName);
284 if (ifState == null) {
285 LOG.debug("Interface {} is not present", interfaceName);
288 NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(ifState);
290 interfaceInfo.setDpId(IfmUtil.getDpnFromNodeConnectorId(ncId));
291 interfaceInfo.setPortNo(Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId)));
293 InterfaceInfo.InterfaceOpState opState;
294 if (ifState.getOperStatus() == OperStatus.Up) {
295 opState = InterfaceInfo.InterfaceOpState.UP;
296 } else if (ifState.getOperStatus() == OperStatus.Down) {
297 opState = InterfaceInfo.InterfaceOpState.DOWN;
299 opState = InterfaceInfo.InterfaceOpState.UNKNOWN;
301 interfaceInfo.setAdminState(ifState.getAdminStatus() == AdminStatus.Up ? InterfaceAdminState.ENABLED
302 : InterfaceAdminState.DISABLED);
303 interfaceInfo.setInterfaceName(interfaceName);
304 Integer lportTag = ifState.getIfIndex();
305 interfaceInfo.setInterfaceTag(lportTag);
306 interfaceInfo.setInterfaceType(interfaceType);
307 interfaceInfo.setGroupId(IfmUtil.getGroupId(lportTag, interfaceType));
308 interfaceInfo.setOpState(opState);
309 PhysAddress phyAddress = ifState.getPhysAddress();
310 if (phyAddress != null) {
311 interfaceInfo.setMacAddress(ifState.getPhysAddress().getValue());
313 return interfaceInfo;
317 public InterfaceInfo getInterfaceInfoFromOperationalDataStore(String interfaceName) {
318 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
319 .ietf.interfaces.rev140508.interfaces.state.Interface ifState = interfaceManagerCommonUtils
320 .getInterfaceState(interfaceName);
321 if (ifState == null) {
322 LOG.debug("Interface {} is not present", interfaceName);
326 return populateInterfaceInfo(interfaceName, ifState);
329 public InterfaceInfo populateInterfaceInfo(String interfaceName,
330 org.opendaylight.yang.gen.v1.urn
331 .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
332 InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName);
333 NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(ifState);
335 if (Tunnel.class.equals(ifState.getType())) {
336 interfaceInfo.setPortName(interfaceName);
338 Interface iface = interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName);
340 ParentRefs parentRefs = iface.getAugmentation(ParentRefs.class);
341 interfaceInfo.setPortName(parentRefs.getParentInterface());
344 interfaceInfo.setDpId(IfmUtil.getDpnFromNodeConnectorId(ncId));
345 interfaceInfo.setPortNo(Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId)));
347 InterfaceInfo.InterfaceOpState opState;
348 if (ifState.getOperStatus() == OperStatus.Up) {
349 opState = InterfaceInfo.InterfaceOpState.UP;
350 } else if (ifState.getOperStatus() == OperStatus.Down) {
351 opState = InterfaceInfo.InterfaceOpState.DOWN;
353 opState = InterfaceInfo.InterfaceOpState.UNKNOWN;
355 interfaceInfo.setAdminState(ifState.getAdminStatus() == AdminStatus.Up ? InterfaceAdminState.ENABLED
356 : InterfaceAdminState.DISABLED);
357 interfaceInfo.setInterfaceName(interfaceName);
358 Integer lportTag = ifState.getIfIndex();
359 if (lportTag != null) {
360 interfaceInfo.setInterfaceTag(lportTag);
362 interfaceInfo.setOpState(opState);
363 PhysAddress phyAddress = ifState.getPhysAddress();
364 if (phyAddress != null) {
365 interfaceInfo.setMacAddress(ifState.getPhysAddress().getValue());
367 return interfaceInfo;
371 public InterfaceInfo getInterfaceInfoFromOperationalDSCache(String interfaceName) {
372 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
373 .ietf.interfaces.rev140508.interfaces.state.Interface ifState = interfaceManagerCommonUtils
374 .getInterfaceStateFromCache(interfaceName);
375 if (ifState == null) {
376 LOG.warn("Interface {} is not present", interfaceName);
379 return populateInterfaceInfo(interfaceName, ifState);
383 public Interface getInterfaceInfoFromConfigDataStore(String interfaceName) {
384 return interfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName));
388 public void createVLANInterface(String interfaceName, String portName, BigInteger dpId, Integer vlanId,
389 String description, IfL2vlan.L2vlanMode l2vlanMode) throws InterfaceAlreadyExistsException {
390 createVLANInterface(interfaceName, portName, vlanId, description, l2vlanMode);
394 public ListenableFuture<Void> createVLANInterface(String interfaceName, String portName, Integer vlanId,
395 String description, IfL2vlan.L2vlanMode l2vlanMode) throws InterfaceAlreadyExistsException {
396 return createVLANInterface(interfaceName, portName, vlanId, description, l2vlanMode, false);
400 public void createVLANInterface(String interfaceName, String portName, BigInteger dpId, Integer vlanId,
401 String description, IfL2vlan.L2vlanMode l2vlanMode, boolean isExternal)
402 throws InterfaceAlreadyExistsException {
403 createVLANInterface(interfaceName, portName, vlanId, description, l2vlanMode, isExternal);
407 public ListenableFuture<Void> createVLANInterface(String interfaceName, String portName, Integer vlanId,
408 String description, IfL2vlan.L2vlanMode l2vlanMode,
410 throws InterfaceAlreadyExistsException {
412 LOG.info("Create VLAN interface : {}", interfaceName);
413 Interface interfaceOptional = interfaceManagerCommonUtils
414 .getInterfaceFromConfigDS(new InterfaceKey(interfaceName));
415 if (interfaceOptional != null) {
416 LOG.debug("VLAN interface already exists {} ", interfaceOptional.getDescription());
417 throw new InterfaceAlreadyExistsException(interfaceOptional.getName());
419 IfL2vlanBuilder l2vlanBuilder = new IfL2vlanBuilder().setL2vlanMode(l2vlanMode);
420 if (vlanId != null && vlanId > 0) {
421 l2vlanBuilder.setVlanId(new VlanId(vlanId));
423 ParentRefs parentRefs = new ParentRefsBuilder().setParentInterface(portName).build();
424 InterfaceBuilder interfaceBuilder = new InterfaceBuilder().setEnabled(true).setName(interfaceName)
425 .setType(L2vlan.class).addAugmentation(IfL2vlan.class, l2vlanBuilder.build())
426 .addAugmentation(ParentRefs.class, parentRefs).setDescription(description);
428 interfaceBuilder.addAugmentation(IfExternal.class, new IfExternalBuilder().setExternal(true).build());
430 InstanceIdentifier<Interface> interfaceIId = interfaceManagerCommonUtils
431 .getInterfaceIdentifier(new InterfaceKey(interfaceName));
432 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
433 tx -> tx.put(CONFIGURATION, interfaceIId, interfaceBuilder.build(), CREATE_MISSING_PARENTS));
434 ListenableFutures.addErrorLogging(future, LOG, "Failed to (async) write {}", interfaceIId);
438 private boolean isServiceBoundOnInterface(short servicePriority, String interfaceName,
439 Class<? extends ServiceModeBase> serviceMode) {
440 InstanceIdentifier<BoundServices> boundServicesIId = IfmUtil.buildBoundServicesIId(servicePriority,
441 interfaceName, serviceMode);
443 return SingleTransactionDataBroker
444 .syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, boundServicesIId).isPresent();
445 } catch (ReadFailedException e) {
446 LOG.warn("Error while reading [{}]", boundServicesIId, e);
452 public boolean isServiceBoundOnInterfaceForIngress(short servicePriority, String interfaceName) {
453 return isServiceBoundOnInterface(servicePriority, interfaceName, ServiceModeIngress.class);
457 public boolean isServiceBoundOnInterfaceForEgress(short servicePriority, String interfaceName) {
458 return isServiceBoundOnInterface(servicePriority, interfaceName, ServiceModeEgress.class);
462 public void bindService(String interfaceName, Class<? extends ServiceModeBase> serviceMode,
463 BoundServices serviceInfo) {
464 bindService(interfaceName, serviceMode, serviceInfo, /* WriteTransaction */ null);
468 public void bindService(String interfaceName, Class<? extends ServiceModeBase> serviceMode,
469 BoundServices serviceInfo, WriteTransaction tx) {
471 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
472 wtx -> IfmUtil.bindService(wtx, interfaceName, serviceInfo, serviceMode)), LOG,
473 "Error binding the InterfacemgrProvider service");
475 IfmUtil.bindService(tx, interfaceName, serviceInfo, serviceMode);
480 public void unbindService(String interfaceName, Class<? extends ServiceModeBase> serviceMode,
481 BoundServices serviceInfo) {
482 IfmUtil.unbindService(txRunner, coordinator, interfaceName,
483 FlowBasedServicesUtils.buildServiceId(interfaceName, serviceInfo.getServicePriority(), serviceMode));
487 public BigInteger getDpnForInterface(Interface intrf) {
488 return getDpnForInterface(intrf.getName());
492 public BigInteger getDpnForInterface(String ifName) {
493 GetDpidFromInterfaceInput input = new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
494 Future<RpcResult<GetDpidFromInterfaceOutput>> output = interfaceManagerRpcService.getDpidFromInterface(input);
496 RpcResult<GetDpidFromInterfaceOutput> dpn = output.get();
497 if (dpn.isSuccessful()) {
498 return dpn.getResult().getDpid();
500 } catch (NullPointerException | InterruptedException | ExecutionException e) {
501 LOG.warn("Exception when getting port for interface", e);
507 public String getEndpointIpForDpn(BigInteger dpnId) {
508 GetEndpointIpForDpnInput input = new GetEndpointIpForDpnInputBuilder().setDpid(dpnId).build();
509 Future<RpcResult<GetEndpointIpForDpnOutput>> output = interfaceManagerRpcService.getEndpointIpForDpn(input);
511 RpcResult<GetEndpointIpForDpnOutput> ipForDpnOutputRpcResult = output.get();
512 if (ipForDpnOutputRpcResult.isSuccessful()) {
513 List<IpAddress> localIps = ipForDpnOutputRpcResult.getResult().getLocalIps();
514 if (!localIps.isEmpty()) {
515 return localIps.get(0).getIpv4Address().getValue();
518 } catch (NullPointerException | InterruptedException | ExecutionException e) {
519 LOG.warn("Exception when getting port for interface", e);
525 public List<ActionInfo> getInterfaceEgressActions(String ifName) {
526 return IfmUtil.getEgressActionInfosForInterface(ifName, 0, interfaceManagerCommonUtils, false);
530 public List<Interface> getVlanInterfaces() {
531 return interfaceManagerCommonUtils.getAllVlanInterfacesFromCache();
535 public List<Interface> getVxlanInterfaces() {
536 return interfaceManagerCommonUtils.getAllTunnelInterfacesFromCache();
540 public List<Interface> getChildInterfaces(String parentInterface) {
541 InterfaceParentEntry parentEntry = interfaceMetaUtils.getInterfaceParentEntryFromConfigDS(parentInterface);
542 if (parentEntry == null) {
543 LOG.debug("No parent entry found for {}", parentInterface);
544 return Collections.emptyList();
547 List<InterfaceChildEntry> childEntries = parentEntry.getInterfaceChildEntry();
548 if (childEntries == null || childEntries.isEmpty()) {
549 LOG.debug("No child entries found for parent {}", parentInterface);
550 return Collections.emptyList();
553 List<Interface> childInterfaces = new ArrayList<>();
554 for (InterfaceChildEntry childEntry : childEntries) {
555 String interfaceName = childEntry.getChildInterface();
556 Interface iface = interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName);
558 childInterfaces.add(iface);
560 LOG.debug("Child interface {} not found in config DS for parent interface {}", interfaceName,
565 LOG.trace("Found child interfaces {} for parent {}", childInterfaces, parentInterface);
566 return childInterfaces;
570 public boolean isExternalInterface(String interfaceName) {
571 return isExternalInterface(getInterfaceInfoFromConfigDataStore(interfaceName));
574 private boolean isExternalInterface(Interface iface) {
579 IfExternal ifExternal = iface.getAugmentation(IfExternal.class);
580 return ifExternal != null && Boolean.TRUE.equals(ifExternal.isExternal());
584 public String getPortNameForInterface(NodeConnectorId nodeConnectorId, String interfaceName) {
585 return InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId, interfaceName);
589 public String getPortNameForInterface(String dpnId, String interfaceName) {
590 return InterfaceManagerCommonUtils.getPortNameForInterface(dpnId, interfaceName);
594 public Map<String, OvsdbTerminationPointAugmentation> getTerminationPointCache() {
595 return new ConcurrentHashMap<>(this.ifaceToTpMap);
599 public Map<String, OperStatus> getBfdStateCache() {
600 return interfaceManagerCommonUtils.getBfdStateMap();
603 public void addTerminationPointForInterface(String interfaceName,
604 OvsdbTerminationPointAugmentation terminationPoint) {
605 if (interfaceName != null && terminationPoint != null) {
606 LOG.debug("Adding TerminationPoint {} to cache for Interface {}", terminationPoint.getName(),
608 ifaceToTpMap.put(interfaceName, terminationPoint);
612 public OvsdbTerminationPointAugmentation getTerminationPoint(String interfaceName) {
613 return ifaceToTpMap.get(interfaceName);
616 public void removeTerminationPointForInterface(String interfaceName) {
617 LOG.debug("Removing TerminationPoint from cache for Interface {}", interfaceName);
618 if (interfaceName != null) {
619 ifaceToTpMap.remove(interfaceName);
623 public void addNodeIidForInterface(String interfaceName, InstanceIdentifier<Node> nodeIid) {
624 if (interfaceName != null && nodeIid != null) {
625 ifaceToNodeIidMap.put(interfaceName, nodeIid);
629 public void removeNodeIidForInterface(String interfaceName) {
630 if (interfaceName != null) {
631 ifaceToNodeIidMap.remove(interfaceName);
635 public InstanceIdentifier<Node> getNodeIidForInterface(String interfaceName) {
636 if (interfaceName != null) {
637 return ifaceToNodeIidMap.get(interfaceName);
642 private OvsdbBridgeAugmentation getBridgeForInterface(String interfaceName,
643 InstanceIdentifier<Node> nodeInstanceId) {
644 InstanceIdentifier<Node> nodeIid = nodeInstanceId;
645 if (nodeIid == null) {
646 nodeIid = getNodeIidForInterface(interfaceName);
648 return getBridgeForNodeIid(nodeIid);
651 public String getDpidForInterface(String interfaceName) {
652 return getDpidForInterface(interfaceName, null);
655 public String getDpidForInterface(String interfaceName, InstanceIdentifier<Node> nodeInstanceId) {
656 OvsdbBridgeAugmentation bridge = getBridgeForInterface(interfaceName, nodeInstanceId);
657 if (bridge != null) {
658 BigInteger dpid = IfmUtil.getDpnId(bridge.getDatapathId());
659 if (dpid != null && dpid.longValue() != 0) {
660 return String.valueOf(dpid);
666 public void addBridgeForNodeIid(InstanceIdentifier<Node> nodeIid, OvsdbBridgeAugmentation bridge) {
667 if (nodeIid != null && bridge != null) {
668 nodeIidToBridgeMap.put(nodeIid, bridge);
672 public void removeBridgeForNodeIid(InstanceIdentifier<Node> nodeIid) {
673 if (nodeIid != null) {
674 nodeIidToBridgeMap.remove(nodeIid);
678 public OvsdbBridgeAugmentation getBridgeForNodeIid(InstanceIdentifier<Node> nodeIid) {
679 if (nodeIid == null) {
683 OvsdbBridgeAugmentation ret = nodeIidToBridgeMap.get(nodeIid);
688 LOG.info("Node {} not found in cache, reading from md-sal", nodeIid);
691 node = SingleTransactionDataBroker.syncRead(
692 dataBroker, LogicalDatastoreType.OPERATIONAL, nodeIid);
693 } catch (ReadFailedException e) {
694 LOG.error("Failed to read Node for {} ", nodeIid, e);
698 OvsdbBridgeAugmentation bridge = node.getAugmentation(OvsdbBridgeAugmentation.class);
699 if (bridge == null) {
700 LOG.error("Node {} has no bridge augmentation");
704 addBridgeForNodeIid(nodeIid, bridge);
709 public String getParentRefNameForInterface(String interfaceName) {
710 String parentRefName = null;
712 String dpnId = getDpidForInterface(interfaceName, null);
713 OvsdbTerminationPointAugmentation ovsdbTp = getTerminationPoint(interfaceName);
714 if (ovsdbTp != null) {
716 LOG.error("Got NULL dpnId when looking for TP with external ID {}", interfaceName);
719 parentRefName = getPortNameForInterface(dpnId, ovsdbTp.getName());
720 LOG.debug("Building parent ref for interface {}, using parentRefName {} acquired by external ID",
721 interfaceName, parentRefName);
723 LOG.debug("Skipping parent ref for interface {}, as there is no termination point that references "
724 + "this interface yet.", interfaceName);
727 return parentRefName;
731 public void updateInterfaceParentRef(String interfaceName, String parentInterface) {
732 // This should generally be called by EOS Owner for
733 // INTERFACE_CONFIG_ENTITY - runOnlyInLeaderNode()
734 updateInterfaceParentRef(interfaceName, parentInterface, true);
738 public void updateInterfaceParentRef(String interfaceName, String parentInterface,
739 boolean readInterfaceBeforeWrite) {
740 // This should generally be called by EOS Owner for
741 // INTERFACE_CONFIG_ENTITY - runOnlyInLeaderNode()
742 if (interfaceName == null) {
746 ParentRefUpdateWorker parentRefUpdateWorker = new ParentRefUpdateWorker(interfaceName, parentInterface,
747 readInterfaceBeforeWrite);
748 coordinator.enqueueJob(interfaceName, parentRefUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
751 public class ParentRefUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
752 String interfaceName;
753 String parentInterfaceName;
754 Boolean readInterfaceBeforeWrite;
756 public ParentRefUpdateWorker(String interfaceName, String parentInterfaceName,
757 boolean readInterfaceBeforeWrite) {
758 this.interfaceName = interfaceName;
759 this.parentInterfaceName = parentInterfaceName;
760 this.readInterfaceBeforeWrite = readInterfaceBeforeWrite;
764 public List<ListenableFuture<Void>> call() throws Exception {
765 if (readInterfaceBeforeWrite) {
766 Interface iface = interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName);
768 LOG.debug("Interface doesn't exist in config DS - no need to update parentRef, skipping");
772 return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
773 tx -> IfmUtil.updateInterfaceParentRef(tx, interfaceName, parentInterfaceName)));
778 public OvsdbTerminationPointAugmentation getTerminationPointForInterface(String interfaceName) {
779 return getTerminationPoint(interfaceName);
783 public OvsdbBridgeAugmentation getOvsdbBridgeForInterface(String interfaceName) {
784 return getBridgeForInterface(interfaceName, null);
788 public OvsdbBridgeAugmentation getOvsdbBridgeForNodeIid(InstanceIdentifier<Node> nodeIid) {
789 return getBridgeForNodeIid(nodeIid);
794 * Get all termination points on a given DPN.
795 * This API uses read on Operational DS. If there are perf issues in cluster
796 * setup, we can consider caching later.
799 * Datapath Node Identifier
801 * @return If the data at the supplied path exists, returns a list of all termination point
804 public List<OvsdbTerminationPointAugmentation> getPortsOnBridge(BigInteger dpnId) {
805 List<OvsdbTerminationPointAugmentation> ports = new ArrayList<>();
806 List<TerminationPoint> portList = interfaceMetaUtils.getTerminationPointsOnBridge(dpnId);
807 for (TerminationPoint ovsPort : portList) {
808 if (ovsPort.getAugmentation(OvsdbTerminationPointAugmentation.class) != null) {
809 ports.add(ovsPort.getAugmentation(OvsdbTerminationPointAugmentation.class));
812 LOG.debug("Found {} ports on bridge {}", ports.size(), dpnId);
817 * Get all termination points of type tunnel on a given DPN.
820 * Datapath Node Identifier
822 * @return If the data at the supplied path exists, returns a list of all termination point
823 * Augmentations of type tunnel
826 public List<OvsdbTerminationPointAugmentation> getTunnelPortsOnBridge(BigInteger dpnId) {
827 List<OvsdbTerminationPointAugmentation> tunnelPorts = new ArrayList<>();
828 List<TerminationPoint> portList = interfaceMetaUtils.getTerminationPointsOnBridge(dpnId);
829 for (TerminationPoint ovsPort : portList) {
830 OvsdbTerminationPointAugmentation portAug =
831 ovsPort.getAugmentation(OvsdbTerminationPointAugmentation.class);
832 if (portAug != null && SouthboundUtils.isInterfaceTypeTunnel(portAug.getInterfaceType())) {
833 tunnelPorts.add(portAug);
837 LOG.debug("Found {} tunnel ports on bridge {}", tunnelPorts.size(), dpnId);
842 * Get all termination points by type on a given DPN.
845 * Datapath Node Identifier
847 * @return If the data at the supplied path exists, returns a Map where key is interfaceType
848 * and value is list of termination points of given type
851 public Map<Class<? extends InterfaceTypeBase>, List<OvsdbTerminationPointAugmentation>>
852 getPortsOnBridgeByType(BigInteger dpnId) {
854 Map<Class<? extends InterfaceTypeBase>, List<OvsdbTerminationPointAugmentation>> portMap;
855 portMap = new ConcurrentHashMap<>();
856 List<TerminationPoint> ovsPorts = interfaceMetaUtils.getTerminationPointsOnBridge(dpnId);
857 if (ovsPorts != null) {
858 for (TerminationPoint ovsPort : ovsPorts) {
859 OvsdbTerminationPointAugmentation portAug =
860 ovsPort.getAugmentation(OvsdbTerminationPointAugmentation.class);
861 if (portAug != null && portAug.getInterfaceType() != null) {
862 portMap.computeIfAbsent(portAug.getInterfaceType(), k -> new ArrayList<>()).add(portAug);
870 public long getLogicalTunnelSelectGroupId(int lportTag) {
871 return IfmUtil.getLogicalTunnelSelectGroupId(lportTag);
875 public boolean isItmDirectTunnelsEnabled() {
876 return ifmConfig.isItmDirectTunnels();