MRI version bump for Aluminium
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / commons / InterfaceManagerCommonUtils.java
1 /*
2  * Copyright © 2016, 2017 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.commons;
9
10 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
11
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;
17 import java.util.Map;
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;
100
101 @Singleton
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");
105
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;
110
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);
115
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;
129
130     public ConcurrentHashMap<String, OperStatus> getBfdStateMap() {
131         return bfdStateMap;
132     }
133
134     @Inject
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;
146     }
147
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();
153
154         return IfmUtil.read(LogicalDatastoreType.OPERATIONAL, ncIdentifier, dataBroker).orElse(null);
155     }
156
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();
163     }
164
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();
169     }
170
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());
176     }
177
178     public List<Interface> getAllVlanInterfacesFromCache() {
179         return interfaceConfigMap.values().stream()
180                 .filter(iface -> IfmUtil.getInterfaceType(iface) == InterfaceInfo.InterfaceType.VLAN_INTERFACE)
181                 .collect(Collectors.toList());
182     }
183
184     /**
185      * Searches for an interface by its name.
186      *
187      * @param interfaceName
188      *            name of the interface to search for
189      * @return the Interface object
190      */
191     @Deprecated
192     @Nullable
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);
199         }
200     }
201
202     @Nullable
203     public Interface getInterfaceFromConfigDS(ReadTransaction tx, String interfaceName) throws
204             ExecutionException, InterruptedException {
205         Interface iface = interfaceConfigMap.get(interfaceName);
206         if (iface != null) {
207             return iface;
208         }
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();
213         }
214         return iface;
215     }
216
217     @Deprecated
218     public Interface getInterfaceFromConfigDS(InterfaceKey interfaceKey) {
219         return getInterfaceFromConfigDS(interfaceKey.getName());
220     }
221
222     public Interface getInterfaceFromConfigDS(ReadTransaction tx, InterfaceKey interfaceKey)
223             throws ExecutionException, InterruptedException {
224         return getInterfaceFromConfigDS(tx, interfaceKey.getName());
225     }
226
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);
231     }
232
233     /**
234      * This utility tries to fetch interface-state from cache first,
235      * and if not present tries to read it from operational DS.
236      *
237      *
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;
242      *
243      */
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);
247     }
248
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) {
255             return ifState;
256         }
257         ifState = getInterfaceStateFromOperDS(tx, interfaceName);
258         return ifState;
259     }
260
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);
265     }
266
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);
272     }
273
274     @Deprecated
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);
280     }
281
282     public void addTunnelIngressFlow(TypedWriteTransaction<Configuration> tx, IfTunnel tunnel, Uint64 dpnId,
283         long portNo, String interfaceName, int ifIndex) {
284         if (isTunnelWithoutIngressFlow(tunnel)) {
285             return;
286         }
287         LOG.debug("add tunnel ingress flow for {}", interfaceName);
288
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()));
293         }
294         if (BooleanUtils.isTrue(tunnel.isTunnelSourceIpFlow())) {
295             matches.add(new NxMatchTunnelDestinationIp(tunnel.getTunnelSource().getIpv4Address()));
296         }
297
298         List<InstructionInfo> mkInstructions = new ArrayList<>();
299         mkInstructions.add(
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));
307
308         mdsalApiManager.addFlow(tx, buildTunnelIngressFlowEntity(dpnId, interfaceName, matches, mkInstructions));
309     }
310
311     public void removeTunnelIngressFlow(TypedReadWriteTransaction<Configuration> tx, IfTunnel tunnel, Uint64 dpnId,
312         String interfaceName) throws ExecutionException, InterruptedException {
313         if (isTunnelWithoutIngressFlow(tunnel)) {
314             return;
315         }
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);
320     }
321
322     private static boolean isTunnelWithoutIngressFlow(IfTunnel tunnel) {
323         return tunnel != null && tunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeLogicalGroup.class);
324     }
325
326     @NonNull
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,
333                 mkInstructions);
334     }
335
336     public static String getTunnelInterfaceFlowRef(Uint64 dpnId, short tableId, String ifName) {
337         return String.valueOf(dpnId) + tableId + ifName;
338     }
339
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(
348                         interfaceName));
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);
353     }
354
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()));
359     }
360
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)
370                 .build();
371         writer.accept(Pair.of(interfaceChildEntryIdentifier, interfaceChildEntry));
372     }
373
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);
380     }
381
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;
389         } else {
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);
396         }
397
398         updateOperStatus(interfaceNew.getName(), operStatus,transaction);
399         return operStatus;
400     }
401
402
403     public static OperStatus getOpState(FlowCapableNodeConnector flowCapableNodeConnector) {
404         OperStatus operStatus = flowCapableNodeConnector.getState().isLive()
405             && !flowCapableNodeConnector.getConfiguration().isPORTDOWN() ? OperStatus.Up : OperStatus.Down;
406         return operStatus;
407     }
408
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());
421     }
422
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)));
428     }
429
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
435         // no throttling
436         // on id allocation even when multiple southbound port_up events come in
437         // one shot
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);
443             return;
444         }
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
449                 .getOperStatus();
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
453                 .getAdminStatus();
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);
458
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;
462         }
463
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);
473         }
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());
481
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));
491         }
492
493         // Update the DpnToInterfaceList OpDS
494         createOrUpdateDpnToInterface(dpId, interfaceName, interfaceType);
495     }
496
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);
504         Integer ifIndex;
505         Class<? extends InterfaceType> interfaceType = null;
506         if (interfaceInfo != null) {
507             if (!interfaceInfo.isEnabled()) {
508                 operStatus = OperStatus.Down;
509             }
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);
516         }
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());
523         } else {
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);
530             }
531         }
532         ifaceBuilder.setAdminStatus(adminStatus).setOperStatus(operStatus).setLowerLayerIf(childLowerLayerIfList);
533         if (physAddress != null) {
534             ifaceBuilder.setPhysAddress(physAddress);
535         }
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
541                 .build();
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);
546         } else {
547             tx.mergeParentStructurePut(ifStateId, ifState);
548         }
549         if (nodeConnectorId != null) {
550             Uint64 dpId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
551             // Update the DpnToInterfaceList OpDS
552             createOrUpdateDpnToInterface(dpId, interfaceName, interfaceType);
553         }
554         return ifState;
555     }
556
557
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));
561     }
562
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);
567     }
568
569     // For trunk interfaces, binding to a parent interface which is already
570     // bound to another trunk interface should not
571     // be allowed
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);
579
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);
588                         return false;
589                     }
590
591                     Interface iface = getInterfaceFromConfigDS(curChildInterface);
592                     if (l2vlanMode == IfL2vlan.L2vlanMode.Trunk && isTrunkInterface(iface)) {
593                         LOG.error(
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);
597                         return false;
598                     }
599                 }
600             }
601         }
602
603         LOG.info("Creating child interface {} of type {} bound on parent-interface {}",
604                 childInterface, l2vlanMode, parentInterface);
605         createInterfaceChildEntry(tx, parentInterface, childInterface);
606         return true;
607     }
608
609     public static boolean isTrunkInterface(Interface iface) {
610         if (iface != null) {
611             IfL2vlan ifL2vlan = iface.augmentation(IfL2vlan.class);
612             return ifL2vlan != null && IfL2vlan.L2vlanMode.Trunk.equals(ifL2vlan.getL2vlanMode());
613         }
614
615         return false;
616     }
617
618     public boolean deleteParentInterfaceEntry(String parentInterface) {
619         if (parentInterface == null) {
620             return false;
621         }
622         InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
623         InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryIdentifier = InterfaceMetaUtils
624                 .getInterfaceParentEntryIdentifier(interfaceParentEntryKey);
625         batchingUtils.delete(interfaceParentEntryIdentifier, BatchingUtils.EntityType.DEFAULT_CONFIG);
626         return true;
627     }
628
629     /*
630      * update operational state of interface based on events like tunnel
631      * monitoring
632      */
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());
642     }
643
644     public static boolean isTunnelInterface(Interface interfaceInfo) {
645         return interfaceInfo != null && interfaceInfo.augmentation(IfTunnel.class) != null;
646     }
647
648     public static boolean isOfTunnelInterface(Interface interfaceInfo) {
649         return isTunnelInterface(interfaceInfo)
650                 && SouthboundUtils.isOfTunnel(interfaceInfo.augmentation(IfTunnel.class));
651     }
652
653     public static boolean isVlanInterface(Interface interfaceInfo) {
654         return interfaceInfo != null && interfaceInfo.augmentation(IfL2vlan.class) != null;
655     }
656
657     // Cache Util methods
658     public void addInterfaceToCache(Interface iface) {
659         interfaceConfigMap.put(iface.getName(), iface);
660     }
661
662     public void removeFromInterfaceCache(Interface iface) {
663         interfaceConfigMap.remove(iface.getName());
664     }
665
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);
670     }
671
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());
676     }
677
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);
681     }
682
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);
687     }
688
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);
693     }
694
695     public static boolean isNovaOrTunnelPort(String portName) {
696         Matcher matcher = NOVA_OR_TUNNEL_PORT_PATTERN.matcher(portName);
697         return matcher.matches();
698     }
699
700     public static boolean isNovaPort(String portName) {
701         Matcher matcher = NOVA_PORT_PATTERN.matcher(portName);
702         return matcher.matches();
703     }
704
705     public static boolean isTunnelPort(String portName) {
706         Matcher matcher = TUNNEL_PORT_PATTERN.matcher(portName);
707         return matcher.matches();
708     }
709
710     public static boolean isK8SPort(String portName) {
711         Matcher matcher = K8S_CNI_PORT_PATTERN.matcher(portName);
712         return matcher.matches();
713     }
714
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)
722                                                         .build();
723         InterfaceNameEntryBuilder entryBuilder =
724                 new InterfaceNameEntryBuilder().withKey(interfaceNameEntryKey).setInterfaceName(infName);
725         if (interfaceType != null) {
726             entryBuilder.setInterfaceType(interfaceType);
727         }
728         batchingUtils.write(intfid, entryBuilder.build(), BatchingUtils.EntityType.DEFAULT_OPERATIONAL);
729     }
730
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,
736             dataBroker);
737         if (interfaceList.isPresent()) {
738             return interfaceList.get().getInterfaceNameEntry();
739         }
740         return null;
741     }
742
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);
751             return;
752         }
753
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)
760                 .build();
761         tx.delete(intfid);
762
763         if (interfaceNameEntries != null && interfaceNameEntries.size() <= 1) {
764             tx.delete(dpnToInterfaceId);
765         }
766     }
767
768     public static String getPortNameForInterface(NodeConnectorId nodeConnectorId, String portName) {
769         if (isNovaOrTunnelPort(portName) || isK8SPort(portName)) {
770             return portName;
771         } else {
772             return getDpnPrefixedPortName(nodeConnectorId, portName);
773         }
774     }
775
776     public static String getPortNameForInterface(String dpnId, String portName) {
777         if (isNovaOrTunnelPort(portName) || isK8SPort(portName)) {
778             return portName;
779         } else {
780             return getDpnPrefixedPortName(dpnId, portName);
781         }
782     }
783
784     private static String getDpnPrefixedPortName(NodeConnectorId nodeConnectorId, String portName) {
785         String dpnId = IfmUtil.getDpnStringFromNodeConnectorId(nodeConnectorId);
786         return getDpnPrefixedPortName(dpnId, portName);
787     }
788
789     private static String getDpnPrefixedPortName(String dpnId, String portName) {
790         return dpnId + IfmConstants.OF_URI_SEPARATOR + portName;
791     }
792
793     public boolean isTunnelInternal(String interfaceName) {
794         return isTunnelPort(interfaceName) && getInterfaceFromConfigDS(interfaceName) == null;
795     }
796 }