2 * Copyright © 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.commons;
10 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.time.ZonedDateTime;
14 import java.time.format.DateTimeFormatter;
15 import java.util.ArrayList;
16 import java.util.List;
18 import java.util.Optional;
19 import java.util.concurrent.ConcurrentHashMap;
20 import java.util.concurrent.ExecutionException;
21 import java.util.function.Consumer;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24 import java.util.stream.Collectors;
25 import javax.inject.Inject;
26 import javax.inject.Singleton;
27 import org.apache.aries.blueprint.annotation.service.Reference;
28 import org.apache.commons.lang3.BooleanUtils;
29 import org.apache.commons.lang3.tuple.Pair;
30 import org.eclipse.jdt.annotation.NonNull;
31 import org.eclipse.jdt.annotation.Nullable;
32 import org.opendaylight.genius.infra.Datastore.Configuration;
33 import org.opendaylight.genius.infra.Datastore.Operational;
34 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
35 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
36 import org.opendaylight.genius.infra.TypedReadTransaction;
37 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
38 import org.opendaylight.genius.infra.TypedWriteTransaction;
39 import org.opendaylight.genius.interfacemanager.IfmConstants;
40 import org.opendaylight.genius.interfacemanager.IfmUtil;
41 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
42 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.BatchingUtils;
43 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils;
44 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
45 import org.opendaylight.genius.mdsalutil.FlowEntity;
46 import org.opendaylight.genius.mdsalutil.InstructionInfo;
47 import org.opendaylight.genius.mdsalutil.MDSALUtil;
48 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
49 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
50 import org.opendaylight.genius.mdsalutil.NwConstants;
51 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
52 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
53 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
54 import org.opendaylight.genius.mdsalutil.matches.MatchInPort;
55 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchTunnelDestinationIp;
56 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchTunnelSourceIp;
57 import org.opendaylight.mdsal.binding.api.DataBroker;
58 import org.opendaylight.mdsal.binding.api.ReadTransaction;
59 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Other;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
66 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
67 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
68 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state._interface.StatisticsBuilder;
69 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
70 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.DpnToInterfaceList;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntryKey;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntryBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.DpnToInterface;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.DpnToInterfaceKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.dpn.to._interface.InterfaceNameEntry;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.dpn.to._interface.InterfaceNameEntryBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.dpn.to._interface.InterfaceNameEntryKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
96 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
97 import org.opendaylight.yangtools.yang.common.Uint64;
98 import org.slf4j.Logger;
99 import org.slf4j.LoggerFactory;
102 public final class InterfaceManagerCommonUtils {
103 private static final Logger LOG = LoggerFactory.getLogger(InterfaceManagerCommonUtils.class);
104 private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
106 private static final String NOVA_PORT_REGEX = "(tap|vhu)[0-9a-f]{8}-[0-9a-f]{2}";
107 private static final String TUNNEL_PORT_REGEX = "tun[0-9a-f]{11}";
108 private static final String K8S_CNI_PORT_REGEX = "veth[0-9a-f]{8}";
109 private static final String NOVA_OR_TUNNEL_PORT_REGEX = NOVA_PORT_REGEX + "|" + TUNNEL_PORT_REGEX;
111 private static final Pattern NOVA_OR_TUNNEL_PORT_PATTERN = Pattern.compile(NOVA_OR_TUNNEL_PORT_REGEX);
112 private static final Pattern TUNNEL_PORT_PATTERN = Pattern.compile(TUNNEL_PORT_REGEX);
113 private static final Pattern NOVA_PORT_PATTERN = Pattern.compile(NOVA_PORT_REGEX);
114 private static final Pattern K8S_CNI_PORT_PATTERN = Pattern.compile(K8S_CNI_PORT_REGEX);
116 private final ConcurrentHashMap<String, Interface> interfaceConfigMap = new ConcurrentHashMap<>();
117 private final ConcurrentHashMap<String, org.opendaylight.yang.gen.v1.urn.ietf
118 .params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceStateMap =
119 new ConcurrentHashMap<>();
120 private final ConcurrentHashMap<String, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
121 .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus> bfdStateMap =
122 new ConcurrentHashMap<>();
123 private final DataBroker dataBroker;
124 private final ManagedNewTransactionRunner txRunner;
125 private final IMdsalApiManager mdsalApiManager;
126 private final IdManagerService idManager;
127 private final InterfaceMetaUtils interfaceMetaUtils;
128 private final BatchingUtils batchingUtils;
130 public ConcurrentHashMap<String, OperStatus> getBfdStateMap() {
135 public InterfaceManagerCommonUtils(@Reference DataBroker dataBroker,
136 @Reference IMdsalApiManager mdsalApiManager,
137 IdManagerService idManager,
138 InterfaceMetaUtils interfaceMetaUtils,
139 BatchingUtils batchingUtils) {
140 this.dataBroker = dataBroker;
141 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
142 this.mdsalApiManager = mdsalApiManager;
143 this.idManager = idManager;
144 this.interfaceMetaUtils = interfaceMetaUtils;
145 this.batchingUtils = batchingUtils;
148 public NodeConnector getNodeConnectorFromInventoryOperDS(NodeConnectorId nodeConnectorId) {
149 NodeId nodeId = IfmUtil.getNodeIdFromNodeConnectorId(nodeConnectorId);
150 InstanceIdentifier<NodeConnector> ncIdentifier = InstanceIdentifier.builder(Nodes.class)
151 .child(Node.class, new NodeKey(nodeId))
152 .child(NodeConnector.class, new NodeConnectorKey(nodeConnectorId)).build();
154 return IfmUtil.read(LogicalDatastoreType.OPERATIONAL, ncIdentifier, dataBroker).orElse(null);
157 public boolean isNodePresent(ReadTransaction tx, NodeConnectorId nodeConnectorId) throws
158 ExecutionException, InterruptedException {
159 NodeId nodeID = IfmUtil.getNodeIdFromNodeConnectorId(nodeConnectorId);
160 InstanceIdentifier<Node> nodeInstanceIdentifier = InstanceIdentifier.builder(Nodes.class)
161 .child(Node.class, new NodeKey(nodeID)).build();
162 return tx.exists(LogicalDatastoreType.OPERATIONAL, nodeInstanceIdentifier).get();
165 public static InstanceIdentifier<Interface> getInterfaceIdentifier(InterfaceKey interfaceKey) {
166 InstanceIdentifier.InstanceIdentifierBuilder<Interface> interfaceInstanceIdentifierBuilder = InstanceIdentifier
167 .builder(Interfaces.class).child(Interface.class, interfaceKey);
168 return interfaceInstanceIdentifierBuilder.build();
171 public List<Interface> getAllTunnelInterfacesFromCache() {
172 return interfaceConfigMap.values().stream()
173 .filter(iface -> IfmUtil.getInterfaceType(iface) == InterfaceInfo.InterfaceType.VXLAN_TRUNK_INTERFACE
174 && iface.augmentation(IfTunnel.class).isInternal())
175 .collect(Collectors.toList());
178 public List<Interface> getAllVlanInterfacesFromCache() {
179 return interfaceConfigMap.values().stream()
180 .filter(iface -> IfmUtil.getInterfaceType(iface) == InterfaceInfo.InterfaceType.VLAN_INTERFACE)
181 .collect(Collectors.toList());
185 * Searches for an interface by its name.
187 * @param interfaceName
188 * name of the interface to search for
189 * @return the Interface object
193 public Interface getInterfaceFromConfigDS(String interfaceName) {
194 try (ReadTransaction tx = dataBroker.newReadOnlyTransaction()) {
195 return getInterfaceFromConfigDS(tx, interfaceName);
196 } catch (ExecutionException | InterruptedException e) {
197 LOG.error("Error retrieving interface {} from config", interfaceName, e);
198 throw new RuntimeException("Error retrieving interface " + interfaceName + " from config", e);
203 public Interface getInterfaceFromConfigDS(ReadTransaction tx, String interfaceName) throws
204 ExecutionException, InterruptedException {
205 Interface iface = interfaceConfigMap.get(interfaceName);
209 InstanceIdentifier<Interface> interfaceId = getInterfaceIdentifier(new InterfaceKey(interfaceName));
210 Optional<Interface> interfaceOptional = tx.read(LogicalDatastoreType.CONFIGURATION, interfaceId).get();
211 if (interfaceOptional.isPresent()) {
212 iface = interfaceOptional.get();
218 public Interface getInterfaceFromConfigDS(InterfaceKey interfaceKey) {
219 return getInterfaceFromConfigDS(interfaceKey.getName());
222 public Interface getInterfaceFromConfigDS(ReadTransaction tx, InterfaceKey interfaceKey)
223 throws ExecutionException, InterruptedException {
224 return getInterfaceFromConfigDS(tx, interfaceKey.getName());
227 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
228 .Interface getInterfaceStateFromCache(
229 String interfaceName) {
230 return interfaceStateMap.get(interfaceName);
234 * This utility tries to fetch interface-state from cache first,
235 * and if not present tries to read it from operational DS.
238 * @param interfaceName
239 * name of the logical interface.
240 * @return If the data at the supplied path exists, returns interfaces-state object;
241 * if the data at the supplied path does not exist, returns null;
244 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
245 .Interface getInterfaceState(String interfaceName) {
246 return interfaceStateMap.computeIfAbsent(interfaceName, this::getInterfaceStateFromOperDS);
249 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
250 .Interface getInterfaceState(TypedReadTransaction<Operational> tx, String interfaceName)
251 throws ExecutionException, InterruptedException {
252 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
253 ifState = getInterfaceStateFromCache(interfaceName);
254 if (ifState != null) {
257 ifState = getInterfaceStateFromOperDS(tx, interfaceName);
261 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
262 .ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(String interfaceName) {
263 return IfmUtil.read(LogicalDatastoreType.OPERATIONAL,
264 IfmUtil.buildStateInterfaceId(interfaceName), dataBroker).orElse(null);
267 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
268 .ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(
269 TypedReadTransaction<Operational> tx, String interfaceName)
270 throws ExecutionException, InterruptedException {
271 return tx.read(IfmUtil.buildStateInterfaceId(interfaceName)).get().orElse(null);
275 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
276 .ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(
277 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
278 .ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId) {
279 return IfmUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker).orElse(null);
282 public void addTunnelIngressFlow(TypedWriteTransaction<Configuration> tx, IfTunnel tunnel, Uint64 dpnId,
283 long portNo, String interfaceName, int ifIndex) {
284 if (isTunnelWithoutIngressFlow(tunnel)) {
287 LOG.debug("add tunnel ingress flow for {}", interfaceName);
289 List<MatchInfoBase> matches = new ArrayList<>();
290 matches.add(new MatchInPort(dpnId, portNo));
291 if (BooleanUtils.isTrue(tunnel.isTunnelRemoteIpFlow())) {
292 matches.add(new NxMatchTunnelSourceIp(tunnel.getTunnelDestination().getIpv4Address()));
294 if (BooleanUtils.isTrue(tunnel.isTunnelSourceIpFlow())) {
295 matches.add(new NxMatchTunnelDestinationIp(tunnel.getTunnelSource().getIpv4Address()));
298 List<InstructionInfo> mkInstructions = new ArrayList<>();
300 new InstructionWriteMetadata(
301 Uint64.fromLongBits(MetaDataUtil.getLportTagMetaData(ifIndex).longValue() | 1L),
302 MetaDataUtil.METADATA_MASK_LPORT_TAG_SH_FLAG));
303 short tableId = tunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeMplsOverGre.class)
304 ? NwConstants.L3_LFIB_TABLE
305 : tunnel.isInternal() ? NwConstants.INTERNAL_TUNNEL_TABLE : NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL;
306 mkInstructions.add(new InstructionGotoTable(tableId));
308 mdsalApiManager.addFlow(tx, buildTunnelIngressFlowEntity(dpnId, interfaceName, matches, mkInstructions));
311 public void removeTunnelIngressFlow(TypedReadWriteTransaction<Configuration> tx, IfTunnel tunnel, Uint64 dpnId,
312 String interfaceName) throws ExecutionException, InterruptedException {
313 if (isTunnelWithoutIngressFlow(tunnel)) {
316 LOG.debug("remove tunnel ingress flow for {}", interfaceName);
317 mdsalApiManager.removeFlow(tx, dpnId,
318 InterfaceManagerCommonUtils.getTunnelInterfaceFlowRef(dpnId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE,
319 interfaceName), NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
322 private static boolean isTunnelWithoutIngressFlow(IfTunnel tunnel) {
323 return tunnel != null && tunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeLogicalGroup.class);
327 private static FlowEntity buildTunnelIngressFlowEntity(Uint64 dpnId, String interfaceName,
328 List<MatchInfoBase> matches, List<InstructionInfo> mkInstructions) {
329 String flowRef = InterfaceManagerCommonUtils.getTunnelInterfaceFlowRef(dpnId,
330 NwConstants.VLAN_INTERFACE_INGRESS_TABLE, interfaceName);
331 return MDSALUtil.buildFlowEntity(dpnId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, flowRef,
332 IfmConstants.DEFAULT_FLOW_PRIORITY, interfaceName, 0, 0, NwConstants.COOKIE_VM_INGRESS_TABLE, matches,
336 public static String getTunnelInterfaceFlowRef(Uint64 dpnId, short tableId, String ifName) {
337 return String.valueOf(dpnId) + tableId + ifName;
340 public static void setOpStateForInterface(TypedWriteTransaction<Operational> tx, String interfaceName,
341 OperStatus opStatus) {
342 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
343 .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceId = IfmUtil
344 .buildStateInterfaceId(interfaceName);
345 InterfaceBuilder ifaceBuilder = new InterfaceBuilder()
346 .withKey(new org.opendaylight.yang.gen.v1.urn
347 .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(
349 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
350 .ietf.interfaces.rev140508.interfaces.state.Interface interfaceData = ifaceBuilder
351 .setOperStatus(opStatus).build();
352 tx.mergeParentStructureMerge(interfaceId, interfaceData);
355 public void createInterfaceChildEntry(@NonNull TypedWriteTransaction<Configuration> tx, String parentInterface,
356 String childInterface) {
357 createInterfaceChildEntry(parentInterface, childInterface,
358 pair -> tx.mergeParentStructurePut(pair.getKey(), pair.getValue()));
361 private void createInterfaceChildEntry(String parentInterface, String childInterface,
362 Consumer<Pair<InstanceIdentifier<InterfaceChildEntry>, InterfaceChildEntry>> writer) {
363 InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
364 InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(childInterface);
365 InstanceIdentifier<InterfaceChildEntry> interfaceChildEntryIdentifier = InterfaceMetaUtils
366 .getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey);
367 InterfaceChildEntry interfaceChildEntry = new InterfaceChildEntryBuilder()
368 .withKey(interfaceChildEntryKey)
369 .setChildInterface(childInterface)
371 writer.accept(Pair.of(interfaceChildEntryIdentifier, interfaceChildEntry));
374 public void deleteInterfaceChildEntry(String parentInterface, String childInterface) {
375 InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
376 InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(childInterface);
377 InstanceIdentifier<InterfaceChildEntry> intfId = InterfaceMetaUtils
378 .getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey);
379 batchingUtils.delete(intfId, BatchingUtils.EntityType.DEFAULT_CONFIG);
382 public OperStatus updateStateEntry(Interface interfaceNew, TypedWriteTransaction<Operational> transaction,
383 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
384 .rev140508.interfaces.state.Interface ifState) {
385 final OperStatus operStatus;
386 if (!interfaceNew.isEnabled()) {
387 operStatus = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
388 .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
390 String ncStr = ifState.getLowerLayerIf().get(0);
391 NodeConnectorId nodeConnectorId = new NodeConnectorId(ncStr);
392 NodeConnector nodeConnector = getNodeConnectorFromInventoryOperDS(nodeConnectorId);
393 FlowCapableNodeConnector flowCapableNodeConnector = nodeConnector
394 .augmentation(FlowCapableNodeConnector.class);
395 operStatus = getOpState(flowCapableNodeConnector);
398 updateOperStatus(interfaceNew.getName(), operStatus,transaction);
403 public static OperStatus getOpState(FlowCapableNodeConnector flowCapableNodeConnector) {
404 OperStatus operStatus = flowCapableNodeConnector.getState().isLive()
405 && !flowCapableNodeConnector.getConfiguration().isPORTDOWN() ? OperStatus.Up : OperStatus.Down;
409 public static void updateOperStatus(String interfaceName,
410 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
411 .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus,
412 TypedWriteTransaction<Operational> transaction) {
413 LOG.info("updating operational status {} for interface {}", interfaceName, operStatus);
414 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
415 .ietf.interfaces.rev140508.interfaces.state.Interface> ifChildStateId = IfmUtil
416 .buildStateInterfaceId(interfaceName);
417 InterfaceBuilder ifaceBuilderChild = new InterfaceBuilder();
418 ifaceBuilderChild.setOperStatus(operStatus);
419 ifaceBuilderChild.withKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
420 transaction.merge(ifChildStateId, ifaceBuilderChild.build());
423 public void addStateEntry(String interfaceName, List<ListenableFuture<Void>> futures,
424 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
425 .ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
426 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL,
427 tx -> addStateEntry(tx, interfaceName, futures, ifState)));
430 public void addStateEntry(TypedWriteTransaction<Operational> tx, String interfaceName,
431 List<ListenableFuture<Void>> futures, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
432 .ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
433 // allocate lport tag and create interface-if-index map.
434 // This is done even if interface-state is not present, so that there is
436 // on id allocation even when multiple southbound port_up events come in
438 Integer ifIndex = IfmUtil.allocateId(idManager, IfmConstants.IFM_IDPOOL_NAME, interfaceName);
439 interfaceMetaUtils.createLportTagInterfaceMap(interfaceName, ifIndex);
440 if (ifState == null) {
441 LOG.debug("could not retrieve interface state corresponding to {}, processing will be resumed when "
442 + "interface-state is available", interfaceName);
445 EVENT_LOGGER.debug("IFM-OvsInterfaceConfig,Interface-State,ADD {}", interfaceName);
446 LOG.debug("adding interface state for {}", interfaceName);
447 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
448 .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus = ifState
450 PhysAddress physAddress = ifState.getPhysAddress();
451 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
452 .ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus adminStatus = ifState
454 NodeConnectorId nodeConnectorId = new NodeConnectorId(ifState.getLowerLayerIf().get(0));
455 InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
456 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
457 .ietf.interfaces.rev140508.interfaces.Interface interfaceInfo = getInterfaceFromConfigDS(interfaceKey);
459 if (interfaceInfo != null && !interfaceInfo.isEnabled()) {
460 operStatus = org.opendaylight.yang.gen.v1.urn
461 .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
464 List<String> childLowerLayerIfList = new ArrayList<>();
465 childLowerLayerIfList.add(0, nodeConnectorId.getValue());
466 InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setAdminStatus(adminStatus).setOperStatus(operStatus)
467 .setPhysAddress(physAddress).setLowerLayerIf(childLowerLayerIfList);
468 ifaceBuilder.setIfIndex(ifIndex).setType(Other.class);
469 Class<? extends InterfaceType> interfaceType = null;
470 if (interfaceInfo != null) {
471 interfaceType = interfaceInfo.getType();
472 ifaceBuilder.setType(interfaceType);
474 ifaceBuilder.withKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
475 ifaceBuilder.setStatistics(new StatisticsBuilder().setDiscontinuityTime(DateAndTime
476 .getDefaultInstance(ZonedDateTime.now().format(DateTimeFormatter.ISO_INSTANT))).build());
477 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
478 .ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = IfmUtil
479 .buildStateInterfaceId(interfaceName);
480 tx.mergeParentStructurePut(ifStateId, ifaceBuilder.build());
482 // install ingress flow
483 Uint64 dpId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
484 long portNo = IfmUtil.getPortNumberFromNodeConnectorId(nodeConnectorId);
485 if (interfaceInfo != null && interfaceInfo.isEnabled() && ifState
486 .getOperStatus() == org.opendaylight.yang.gen.v1.urn
487 .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up) {
488 FlowBasedServicesUtils.installLportIngressFlow(dpId, portNo, interfaceInfo, futures, txRunner, ifIndex);
489 futures.add(FlowBasedServicesUtils.bindDefaultEgressDispatcherService(txRunner,
490 interfaceInfo, Long.toString(portNo), interfaceName, ifIndex));
493 // Update the DpnToInterfaceList OpDS
494 createOrUpdateDpnToInterface(dpId, interfaceName, interfaceType);
497 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
498 .ietf.interfaces.rev140508.interfaces.state.Interface addStateEntry(
499 Interface interfaceInfo, String interfaceName, TypedWriteTransaction<Operational> tx, PhysAddress physAddress,
500 OperStatus operStatus, AdminStatus adminStatus, NodeConnectorId nodeConnectorId) {
501 LOG.debug("adding interface state for {}", interfaceName);
502 InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setType(Other.class)
503 .setIfIndex(IfmConstants.DEFAULT_IFINDEX);
505 Class<? extends InterfaceType> interfaceType = null;
506 if (interfaceInfo != null) {
507 if (!interfaceInfo.isEnabled()) {
508 operStatus = OperStatus.Down;
510 interfaceType = interfaceInfo.getType();
511 ifaceBuilder.setType(interfaceType);
512 // retrieve if-index only for northbound configured interfaces
513 ifIndex = IfmUtil.allocateId(idManager, IfmConstants.IFM_IDPOOL_NAME, interfaceName);
514 ifaceBuilder.setIfIndex(ifIndex);
515 interfaceMetaUtils.createLportTagInterfaceMap(interfaceName, ifIndex);
517 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
518 .ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = IfmUtil
519 .buildStateInterfaceId(interfaceName);
520 List<String> childLowerLayerIfList = new ArrayList<>();
521 if (nodeConnectorId != null) {
522 childLowerLayerIfList.add(0, nodeConnectorId.getValue());
524 //logical tunnel group doesn't have OF port
525 ParentRefs parentRefs = interfaceInfo.augmentation(ParentRefs.class);
526 if (parentRefs != null) {
527 Uint64 dpId = parentRefs.getDatapathNodeIdentifier();
528 String lowref = MDSALUtil.NODE_PREFIX + MDSALUtil.SEPARATOR + dpId + MDSALUtil.SEPARATOR + 0;
529 childLowerLayerIfList.add(0, lowref);
532 ifaceBuilder.setAdminStatus(adminStatus).setOperStatus(operStatus).setLowerLayerIf(childLowerLayerIfList);
533 if (physAddress != null) {
534 ifaceBuilder.setPhysAddress(physAddress);
536 ifaceBuilder.withKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
537 ifaceBuilder.setStatistics(new StatisticsBuilder().setDiscontinuityTime(DateAndTime
538 .getDefaultInstance(ZonedDateTime.now().format(DateTimeFormatter.ISO_INSTANT))).build());
539 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
540 .ietf.interfaces.rev140508.interfaces.state.Interface ifState = ifaceBuilder
542 boolean isTunnelInterface = InterfaceManagerCommonUtils.isTunnelInterface(interfaceInfo);
543 boolean isOfTunnelInterface = InterfaceManagerCommonUtils.isOfTunnelInterface(interfaceInfo);
544 if (isTunnelInterface && !isOfTunnelInterface) {
545 batchingUtils.write(ifStateId, ifState, BatchingUtils.EntityType.DEFAULT_OPERATIONAL);
547 tx.mergeParentStructurePut(ifStateId, ifState);
549 if (nodeConnectorId != null) {
550 Uint64 dpId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
551 // Update the DpnToInterfaceList OpDS
552 createOrUpdateDpnToInterface(dpId, interfaceName, interfaceType);
558 public static void deleteStateEntry(TypedWriteTransaction<Operational> tx, String interfaceName) {
559 LOG.debug("removing interface state entry for {}", interfaceName);
560 tx.delete(IfmUtil.buildStateInterfaceId(interfaceName));
563 public void deleteInterfaceStateInformation(String interfaceName, TypedWriteTransaction<Operational> transaction) {
564 LOG.debug("removing interface state information for {}", interfaceName);
565 transaction.delete(IfmUtil.buildStateInterfaceId(interfaceName));
566 interfaceMetaUtils.removeLportTagInterfaceMap(transaction, interfaceName);
569 // For trunk interfaces, binding to a parent interface which is already
570 // bound to another trunk interface should not
572 public boolean createInterfaceChildEntryIfNotPresent(TypedWriteTransaction<Configuration> tx,
573 String parentInterface, String childInterface, IfL2vlan.L2vlanMode l2vlanMode) {
574 InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
575 InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryIdentifier = InterfaceMetaUtils
576 .getInterfaceParentEntryIdentifier(interfaceParentEntryKey);
577 InterfaceParentEntry interfaceParentEntry = interfaceMetaUtils
578 .getInterfaceParentEntryFromConfigDS(interfaceParentEntryIdentifier);
580 if (interfaceParentEntry != null) {
581 Map<InterfaceChildEntryKey, InterfaceChildEntry> interfaceChildEntries =
582 interfaceParentEntry.getInterfaceChildEntry();
583 if (interfaceChildEntries != null) {
584 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries.values()) {
585 String curChildInterface = interfaceChildEntry.getChildInterface();
586 if (childInterface.equals(curChildInterface)) {
587 LOG.trace("Child entry for interface {} already exists", childInterface);
591 Interface iface = getInterfaceFromConfigDS(curChildInterface);
592 if (l2vlanMode == IfL2vlan.L2vlanMode.Trunk && isTrunkInterface(iface)) {
594 "Trying to bind child interface {} of type Trunk to parent interface {},"
595 + "but it is already bound to a trunk interface {}",
596 childInterface, parentInterface, curChildInterface);
603 LOG.info("Creating child interface {} of type {} bound on parent-interface {}",
604 childInterface, l2vlanMode, parentInterface);
605 createInterfaceChildEntry(tx, parentInterface, childInterface);
609 public static boolean isTrunkInterface(Interface iface) {
611 IfL2vlan ifL2vlan = iface.augmentation(IfL2vlan.class);
612 return ifL2vlan != null && IfL2vlan.L2vlanMode.Trunk.equals(ifL2vlan.getL2vlanMode());
618 public boolean deleteParentInterfaceEntry(String parentInterface) {
619 if (parentInterface == null) {
622 InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
623 InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryIdentifier = InterfaceMetaUtils
624 .getInterfaceParentEntryIdentifier(interfaceParentEntryKey);
625 batchingUtils.delete(interfaceParentEntryIdentifier, BatchingUtils.EntityType.DEFAULT_CONFIG);
630 * update operational state of interface based on events like tunnel
633 public static void updateOpState(TypedWriteTransaction<Operational> tx, String interfaceName,
634 OperStatus operStatus) {
635 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
636 .ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = IfmUtil
637 .buildStateInterfaceId(interfaceName);
638 LOG.debug("updating tep interface state as {} for {}", operStatus.name(), interfaceName);
639 InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setOperStatus(operStatus);
640 ifaceBuilder.withKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
641 tx.merge(ifStateId, ifaceBuilder.build());
644 public static boolean isTunnelInterface(Interface interfaceInfo) {
645 return interfaceInfo != null && interfaceInfo.augmentation(IfTunnel.class) != null;
648 public static boolean isOfTunnelInterface(Interface interfaceInfo) {
649 return isTunnelInterface(interfaceInfo)
650 && SouthboundUtils.isOfTunnel(interfaceInfo.augmentation(IfTunnel.class));
653 public static boolean isVlanInterface(Interface interfaceInfo) {
654 return interfaceInfo != null && interfaceInfo.augmentation(IfL2vlan.class) != null;
657 // Cache Util methods
658 public void addInterfaceToCache(Interface iface) {
659 interfaceConfigMap.put(iface.getName(), iface);
662 public void removeFromInterfaceCache(Interface iface) {
663 interfaceConfigMap.remove(iface.getName());
666 public void addInterfaceStateToCache(
667 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
668 .ietf.interfaces.rev140508.interfaces.state.Interface iface) {
669 interfaceStateMap.put(iface.getName(), iface);
672 public void removeFromInterfaceStateCache(
673 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
674 .ietf.interfaces.rev140508.interfaces.state.Interface iface) {
675 interfaceStateMap.remove(iface.getName());
678 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
679 .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus getBfdStateFromCache(String interfaceName) {
680 return bfdStateMap.get(interfaceName);
683 public void addBfdStateToCache(String interfaceName,
684 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
685 .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus) {
686 bfdStateMap.put(interfaceName, operStatus);
689 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
690 .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus removeBfdStateFromCache(
691 String interfaceName) {
692 return bfdStateMap.remove(interfaceName);
695 public static boolean isNovaOrTunnelPort(String portName) {
696 Matcher matcher = NOVA_OR_TUNNEL_PORT_PATTERN.matcher(portName);
697 return matcher.matches();
700 public static boolean isNovaPort(String portName) {
701 Matcher matcher = NOVA_PORT_PATTERN.matcher(portName);
702 return matcher.matches();
705 public static boolean isTunnelPort(String portName) {
706 Matcher matcher = TUNNEL_PORT_PATTERN.matcher(portName);
707 return matcher.matches();
710 public static boolean isK8SPort(String portName) {
711 Matcher matcher = K8S_CNI_PORT_PATTERN.matcher(portName);
712 return matcher.matches();
715 public void createOrUpdateDpnToInterface(Uint64 dpId, String infName,
716 Class<? extends InterfaceType> interfaceType) {
717 DpnToInterfaceKey dpnToInterfaceKey = new DpnToInterfaceKey(dpId);
718 InterfaceNameEntryKey interfaceNameEntryKey = new InterfaceNameEntryKey(infName);
719 InstanceIdentifier<InterfaceNameEntry> intfid = InstanceIdentifier.builder(DpnToInterfaceList.class)
720 .child(DpnToInterface.class, dpnToInterfaceKey)
721 .child(InterfaceNameEntry.class, interfaceNameEntryKey)
723 InterfaceNameEntryBuilder entryBuilder =
724 new InterfaceNameEntryBuilder().withKey(interfaceNameEntryKey).setInterfaceName(infName);
725 if (interfaceType != null) {
726 entryBuilder.setInterfaceType(interfaceType);
728 batchingUtils.write(intfid, entryBuilder.build(), BatchingUtils.EntityType.DEFAULT_OPERATIONAL);
731 public Map<InterfaceNameEntryKey, InterfaceNameEntry> getAllInterfaces(Uint64 dpnId) {
732 DpnToInterfaceKey dpnToInterfaceKey = new DpnToInterfaceKey(dpnId);
733 InstanceIdentifier<DpnToInterface> dpninterfaceListId =
734 InstanceIdentifier.builder(DpnToInterfaceList.class).child(DpnToInterface.class, dpnToInterfaceKey).build();
735 Optional<DpnToInterface> interfaceList = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, dpninterfaceListId,
737 if (interfaceList.isPresent()) {
738 return interfaceList.get().getInterfaceNameEntry();
743 public static void deleteDpnToInterface(Uint64 dpId, String infName, TypedReadWriteTransaction<Operational> tx)
744 throws ExecutionException, InterruptedException {
745 DpnToInterfaceKey dpnToInterfaceKey = new DpnToInterfaceKey(dpId);
746 InstanceIdentifier<DpnToInterface> dpnToInterfaceId = InstanceIdentifier.builder(DpnToInterfaceList.class)
747 .child(DpnToInterface.class, dpnToInterfaceKey).build();
748 Optional<DpnToInterface> dpnToInterfaceOptional = tx.read(dpnToInterfaceId).get();
749 if (!dpnToInterfaceOptional.isPresent()) {
750 LOG.debug("DPN {} is already removed from the Operational DS", dpId);
754 Map<InterfaceNameEntryKey, InterfaceNameEntry> interfaceNameEntries =
755 dpnToInterfaceOptional.get().getInterfaceNameEntry();
756 InterfaceNameEntryKey interfaceNameEntryKey = new InterfaceNameEntryKey(infName);
757 InstanceIdentifier<InterfaceNameEntry> intfid = InstanceIdentifier.builder(DpnToInterfaceList.class)
758 .child(DpnToInterface.class, dpnToInterfaceKey)
759 .child(InterfaceNameEntry.class, interfaceNameEntryKey)
763 if (interfaceNameEntries != null && interfaceNameEntries.size() <= 1) {
764 tx.delete(dpnToInterfaceId);
768 public static String getPortNameForInterface(NodeConnectorId nodeConnectorId, String portName) {
769 if (isNovaOrTunnelPort(portName) || isK8SPort(portName)) {
772 return getDpnPrefixedPortName(nodeConnectorId, portName);
776 public static String getPortNameForInterface(String dpnId, String portName) {
777 if (isNovaOrTunnelPort(portName) || isK8SPort(portName)) {
780 return getDpnPrefixedPortName(dpnId, portName);
784 private static String getDpnPrefixedPortName(NodeConnectorId nodeConnectorId, String portName) {
785 String dpnId = IfmUtil.getDpnStringFromNodeConnectorId(nodeConnectorId);
786 return getDpnPrefixedPortName(dpnId, portName);
789 private static String getDpnPrefixedPortName(String dpnId, String portName) {
790 return dpnId + IfmConstants.OF_URI_SEPARATOR + portName;
793 public boolean isTunnelInternal(String interfaceName) {
794 return isTunnelPort(interfaceName) && getInterfaceFromConfigDS(interfaceName) == null;