Merge "Bug 8023 CSIT failures with ELAN drop rule"
[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
9 package org.opendaylight.genius.interfacemanager.commons;
10
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.concurrent.ConcurrentHashMap;
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
19 import java.util.stream.Collectors;
20 import org.apache.commons.lang3.BooleanUtils;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.genius.interfacemanager.IfmConstants;
25 import org.opendaylight.genius.interfacemanager.IfmUtil;
26 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
27 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.BatchingUtils;
28 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
29 import org.opendaylight.genius.mdsalutil.FlowEntity;
30 import org.opendaylight.genius.mdsalutil.InstructionInfo;
31 import org.opendaylight.genius.mdsalutil.MDSALUtil;
32 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
33 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
34 import org.opendaylight.genius.mdsalutil.NwConstants;
35 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
36 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
37 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
38 import org.opendaylight.genius.mdsalutil.matches.MatchInPort;
39 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchTunnelDestinationIp;
40 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchTunnelSourceIp;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.DpnToInterfaceList;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntryKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntryBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.DpnToInterface;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.DpnToInterfaceKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.dpn.to._interface.InterfaceNameEntry;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.dpn.to._interface.InterfaceNameEntryBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.dpn.to._interface.InterfaceNameEntryKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
71 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
72 import org.slf4j.Logger;
73 import org.slf4j.LoggerFactory;
74
75 public final class InterfaceManagerCommonUtils {
76     private static final Logger LOG = LoggerFactory.getLogger(InterfaceManagerCommonUtils.class);
77     private static ConcurrentHashMap<String, Interface> interfaceConfigMap = new ConcurrentHashMap<>();
78     private static ConcurrentHashMap<String, org.opendaylight.yang.gen.v1.urn.ietf
79         .params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceStateMap =
80         new ConcurrentHashMap<>();
81     private static ConcurrentHashMap<String, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
82         .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus> bfdStateMap =
83             new ConcurrentHashMap<>();
84
85     private static final String NOVA_PORT_REGEX = "(tap|vhu)[0-9a-f]{8}-[0-9a-f]{2}";
86     private static final String TUNNEL_PORT_REGEX = "tun[0-9a-f]{11}";
87     private static final String NOVA_OR_TUNNEL_PORT_REGEX = NOVA_PORT_REGEX + "|" + TUNNEL_PORT_REGEX;
88
89     private static final Pattern NOVA_OR_TUNNEL_PORT_PATTERN = Pattern.compile(NOVA_OR_TUNNEL_PORT_REGEX);
90     private static final Pattern TUNNEL_PORT_PATTERN = Pattern.compile(TUNNEL_PORT_REGEX);
91     private static final Pattern NOVA_PORT_PATTERN = Pattern.compile(NOVA_PORT_REGEX);
92
93     private InterfaceManagerCommonUtils() {
94     }
95
96     public static NodeConnector getNodeConnectorFromInventoryOperDS(NodeConnectorId nodeConnectorId,
97             DataBroker dataBroker) {
98         NodeId nodeId = IfmUtil.getNodeIdFromNodeConnectorId(nodeConnectorId);
99         InstanceIdentifier<NodeConnector> ncIdentifier = InstanceIdentifier.builder(Nodes.class)
100                 .child(Node.class, new NodeKey(nodeId))
101                 .child(NodeConnector.class, new NodeConnectorKey(nodeConnectorId)).build();
102
103         return IfmUtil.read(LogicalDatastoreType.OPERATIONAL, ncIdentifier, dataBroker).orNull();
104     }
105
106     public static boolean isNodePresent(DataBroker dataBroker, NodeConnectorId nodeConnectorId) {
107         NodeId nodeID = IfmUtil.getNodeIdFromNodeConnectorId(nodeConnectorId);
108         InstanceIdentifier<Node> nodeInstanceIdentifier = InstanceIdentifier.builder(Nodes.class)
109                 .child(Node.class, new NodeKey(nodeID)).build();
110         return IfmUtil.read(LogicalDatastoreType.OPERATIONAL, nodeInstanceIdentifier, dataBroker).isPresent();
111     }
112
113     public static InstanceIdentifier<Interface> getInterfaceIdentifier(InterfaceKey interfaceKey) {
114         InstanceIdentifier.InstanceIdentifierBuilder<Interface> interfaceInstanceIdentifierBuilder = InstanceIdentifier
115                 .builder(Interfaces.class).child(Interface.class, interfaceKey);
116         return interfaceInstanceIdentifierBuilder.build();
117     }
118
119     public static List<Interface> getAllTunnelInterfaces(DataBroker dataBroker,
120             InterfaceInfo.InterfaceType interfaceType) {
121         List<Interface> vxlanList = new ArrayList<>();
122         InstanceIdentifier<Interfaces> interfacesInstanceIdentifier = InstanceIdentifier.builder(Interfaces.class)
123                 .build();
124         Optional<Interfaces> interfacesOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION,
125                 interfacesInstanceIdentifier, dataBroker);
126         if (!interfacesOptional.isPresent()) {
127             return vxlanList;
128         }
129         Interfaces interfaces = interfacesOptional.get();
130         List<Interface> interfacesList = interfaces.getInterface();
131         for (Interface iface : interfacesList) {
132             if (IfmUtil.getInterfaceType(iface) == InterfaceInfo.InterfaceType.VXLAN_TRUNK_INTERFACE
133                     && iface.getAugmentation(IfTunnel.class).isInternal()) {
134                 vxlanList.add(iface);
135             }
136         }
137         return vxlanList;
138     }
139
140     public static List<Interface> getAllTunnelInterfacesFromCache() {
141         return interfaceConfigMap.values().stream()
142                 .filter(iface -> IfmUtil.getInterfaceType(iface) == InterfaceInfo.InterfaceType.VXLAN_TRUNK_INTERFACE
143                         && iface.getAugmentation(IfTunnel.class).isInternal())
144                 .collect(Collectors.toList());
145     }
146
147     public static List<Interface> getAllVlanInterfacesFromCache() {
148         return interfaceConfigMap.values().stream()
149                 .filter(iface -> IfmUtil.getInterfaceType(iface) == InterfaceInfo.InterfaceType.VLAN_INTERFACE)
150                 .collect(Collectors.toList());
151     }
152
153     /**
154      * Searches for an interface by its name.
155      *
156      * @param interfaceName
157      *            name of the interface to search for
158      * @param dataBroker
159      *            data tree store to start searching for the interface
160      * @return the Interface object
161      */
162     public static Interface getInterfaceFromConfigDS(String interfaceName, DataBroker dataBroker) {
163         Interface iface = interfaceConfigMap.get(interfaceName);
164         if (iface != null) {
165             return iface;
166         }
167         InstanceIdentifier<Interface> interfaceId = getInterfaceIdentifier(new InterfaceKey(interfaceName));
168         Optional<Interface> interfaceOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION, interfaceId,
169                 dataBroker);
170         if (interfaceOptional.isPresent()) {
171             iface = interfaceOptional.get();
172             interfaceConfigMap.put(iface.getName(), iface);
173         }
174         return iface;
175     }
176
177     @Deprecated
178     public static Interface getInterfaceFromConfigDS(InterfaceKey interfaceKey, DataBroker dataBroker) {
179         return getInterfaceFromConfigDS(interfaceKey.getName(), dataBroker);
180     }
181
182     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
183         .Interface getInterfaceStateFromCache(
184             String interfaceName) {
185         return interfaceStateMap.get(interfaceName);
186     }
187
188     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
189         .Interface  getInterfaceStateFromOperDS(String interfaceName, DataBroker dataBroker) {
190         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
191             ifState = getInterfaceStateFromCache(interfaceName);
192         if (ifState != null) {
193             return ifState;
194         }
195         Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
196                 .Interface> ifStateOptional = IfmUtil.read(LogicalDatastoreType.OPERATIONAL,
197                         IfmUtil.buildStateInterfaceId(interfaceName), dataBroker);
198         if (ifStateOptional.isPresent()) {
199             ifState = ifStateOptional.get();
200             interfaceStateMap.put(ifState.getName(), ifState);
201         }
202         return ifState;
203     }
204
205     @Deprecated
206     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
207         .ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(
208             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
209             .ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId,
210             DataBroker dataBroker) {
211         return IfmUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker).orNull();
212     }
213
214     public static void makeTunnelIngressFlow(List<ListenableFuture<Void>> futures, IMdsalApiManager mdsalApiManager,
215             IfTunnel tunnel, BigInteger dpnId, long portNo, String interfaceName, int ifIndex, int addOrRemoveFlow) {
216         LOG.debug("make tunnel ingress flow for {}", interfaceName);
217         String flowRef = InterfaceManagerCommonUtils.getTunnelInterfaceFlowRef(dpnId,
218                 NwConstants.VLAN_INTERFACE_INGRESS_TABLE, interfaceName);
219         List<MatchInfoBase> matches = new ArrayList<>();
220         List<InstructionInfo> mkInstructions = new ArrayList<>();
221         if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
222             matches.add(new MatchInPort(dpnId, portNo));
223             if (BooleanUtils.isTrue(tunnel.isTunnelRemoteIpFlow())) {
224                 matches.add(new NxMatchTunnelSourceIp(tunnel.getTunnelDestination().getIpv4Address()));
225             }
226             if (BooleanUtils.isTrue(tunnel.isTunnelSourceIpFlow())) {
227                 matches.add(new NxMatchTunnelDestinationIp(tunnel.getTunnelSource().getIpv4Address()));
228             }
229
230             mkInstructions.add(
231                     new InstructionWriteMetadata(MetaDataUtil.getLportTagMetaData(ifIndex).or(BigInteger.ONE),
232                             MetaDataUtil.METADATA_MASK_LPORT_TAG_SH_FLAG));
233             short tableId = tunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeMplsOverGre.class)
234                     ? NwConstants.L3_LFIB_TABLE
235                     : tunnel.isInternal() ? NwConstants.INTERNAL_TUNNEL_TABLE : NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL;
236             mkInstructions.add(new InstructionGotoTable(tableId));
237         }
238
239         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, flowRef,
240                 IfmConstants.DEFAULT_FLOW_PRIORITY, interfaceName, 0, 0, NwConstants.COOKIE_VM_INGRESS_TABLE, matches,
241                 mkInstructions);
242         if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
243             mdsalApiManager.batchedAddFlow(dpnId, flowEntity);
244         } else {
245             mdsalApiManager.batchedRemoveFlow(dpnId, flowEntity);
246         }
247     }
248
249     public static String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
250         return String.valueOf(dpnId) + tableId + ifName;
251     }
252
253     public static void setOpStateForInterface(DataBroker broker, String interfaceName,
254             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
255             .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opStatus) {
256         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
257             .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceId = IfmUtil
258                 .buildStateInterfaceId(interfaceName);
259         InterfaceBuilder ifaceBuilder = new InterfaceBuilder()
260                 .setKey(new org.opendaylight.yang.gen.v1.urn
261                             .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(
262                         interfaceName));
263         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
264             .ietf.interfaces.rev140508.interfaces.state.Interface interfaceData = ifaceBuilder
265                 .setOperStatus(opStatus).build();
266         MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceData);
267     }
268
269     public static void createInterfaceChildEntry(String parentInterface, String childInterface,
270                                                  Optional<WriteTransaction> txOptional) {
271         InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
272         InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(childInterface);
273         InstanceIdentifier<InterfaceChildEntry> intfId = InterfaceMetaUtils
274                 .getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey);
275         InterfaceChildEntryBuilder entryBuilder = new InterfaceChildEntryBuilder().setKey(interfaceChildEntryKey)
276                 .setChildInterface(childInterface);
277         if (!txOptional.isPresent()) {
278             BatchingUtils.write(intfId, entryBuilder.build(), BatchingUtils.EntityType.DEFAULT_CONFIG);
279         } else {
280             txOptional.get().put(LogicalDatastoreType.CONFIGURATION, intfId, entryBuilder.build(), true);
281         }
282     }
283
284     public static void deleteInterfaceChildEntry(String parentInterface, String childInterface) {
285         InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
286         InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(childInterface);
287         InstanceIdentifier<InterfaceChildEntry> intfId = InterfaceMetaUtils
288                 .getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey);
289         BatchingUtils.delete(intfId, BatchingUtils.EntityType.DEFAULT_CONFIG);
290     }
291
292     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
293         .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus updateStateEntry(
294             Interface interfaceNew, DataBroker dataBroker, WriteTransaction transaction,
295             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
296             .ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
297         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
298             .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus;
299         if (!interfaceNew.isEnabled()) {
300             operStatus = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
301                     .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
302         } else {
303             String ncStr = ifState.getLowerLayerIf().get(0);
304             NodeConnectorId nodeConnectorId = new NodeConnectorId(ncStr);
305             NodeConnector nodeConnector = InterfaceManagerCommonUtils
306                     .getNodeConnectorFromInventoryOperDS(nodeConnectorId, dataBroker);
307             FlowCapableNodeConnector flowCapableNodeConnector = nodeConnector
308                     .getAugmentation(FlowCapableNodeConnector.class);
309             // State state = flowCapableNodeConnector.getState();
310             operStatus = flowCapableNodeConnector == null
311                     ? org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
312                             .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down
313                     : org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
314                     .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up;
315         }
316
317         String ifName = interfaceNew.getName();
318         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
319             .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = IfmUtil
320                 .buildStateInterfaceId(interfaceNew.getName());
321         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
322         ifaceBuilder.setOperStatus(operStatus);
323         ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(ifName));
324         transaction.merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build());
325         return operStatus;
326     }
327
328     public static void updateOperStatus(String interfaceName,
329             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
330             .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus,
331             WriteTransaction transaction) {
332         LOG.debug("updating operational status for interface {}", interfaceName);
333         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
334             .ietf.interfaces.rev140508.interfaces.state.Interface> ifChildStateId = IfmUtil
335                 .buildStateInterfaceId(interfaceName);
336         InterfaceBuilder ifaceBuilderChild = new InterfaceBuilder();
337         ifaceBuilderChild.setOperStatus(operStatus);
338         ifaceBuilderChild.setKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
339         transaction.merge(LogicalDatastoreType.OPERATIONAL, ifChildStateId, ifaceBuilderChild.build());
340     }
341
342     public static void addStateEntry(String interfaceName, DataBroker dataBroker,
343                                      IdManagerService idManager, List<ListenableFuture<Void>> futures,
344                                      org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
345                                      .ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
346         WriteTransaction interfaceOperShardTransaction = dataBroker.newWriteOnlyTransaction();
347         addStateEntry(interfaceName, dataBroker, interfaceOperShardTransaction, idManager, futures, ifState);
348         futures.add(interfaceOperShardTransaction.submit());
349     }
350
351     public static void addStateEntry(String interfaceName, DataBroker dataBroker,
352             WriteTransaction interfaceOperShardTransaction,
353             IdManagerService idManager, List<ListenableFuture<Void>> futures,
354                                      org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
355                                      .ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
356         // allocate lport tag and create interface-if-index map.
357         // This is done even if interface-state is not present, so that there is
358         // no throttling
359         // on id allocation even when multiple southbound port_up events come in
360         // one shot
361         Integer ifIndex = IfmUtil.allocateId(idManager, IfmConstants.IFM_IDPOOL_NAME, interfaceName);
362         InterfaceMetaUtils.createLportTagInterfaceMap(interfaceOperShardTransaction, interfaceName, ifIndex);
363         if (ifState == null) {
364             LOG.debug("received null ifState (for parent), cannot add state for {}", interfaceName);
365             return;
366         }
367         LOG.debug("adding interface state for {}", interfaceName);
368         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
369             .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus = ifState
370                 .getOperStatus();
371         PhysAddress physAddress = ifState.getPhysAddress();
372         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
373             .ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus adminStatus = ifState
374                 .getAdminStatus();
375         NodeConnectorId nodeConnectorId = new NodeConnectorId(ifState.getLowerLayerIf().get(0));
376         InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
377         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
378             .ietf.interfaces.rev140508.interfaces.Interface interfaceInfo = InterfaceManagerCommonUtils
379                 .getInterfaceFromConfigDS(interfaceKey, dataBroker);
380
381         if (interfaceInfo != null && !interfaceInfo.isEnabled()) {
382             operStatus = org.opendaylight.yang.gen.v1.urn
383                     .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
384         }
385
386         List<String> childLowerLayerIfList = new ArrayList<>();
387         childLowerLayerIfList.add(0, nodeConnectorId.getValue());
388         InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setAdminStatus(adminStatus).setOperStatus(operStatus)
389                 .setPhysAddress(physAddress).setLowerLayerIf(childLowerLayerIfList);
390         ifaceBuilder.setIfIndex(ifIndex);
391
392         if (interfaceInfo != null) {
393             ifaceBuilder.setType(interfaceInfo.getType());
394         }
395         ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
396         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
397             .ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = IfmUtil
398             .buildStateInterfaceId(interfaceName);
399         interfaceOperShardTransaction.put(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build(), true);
400
401         // install ingress flow
402         BigInteger dpId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
403         long portNo = IfmUtil.getPortNumberFromNodeConnectorId(nodeConnectorId);
404         if (interfaceInfo != null && interfaceInfo.isEnabled() && ifState
405                 .getOperStatus() == org.opendaylight.yang.gen.v1.urn
406                 .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up) {
407             FlowBasedServicesUtils.installLportIngressFlow(dpId, portNo, interfaceInfo, futures, dataBroker, ifIndex);
408             FlowBasedServicesUtils.bindDefaultEgressDispatcherService(dataBroker, futures,
409                         interfaceInfo, Long.toString(portNo), interfaceName, ifIndex);
410         }
411
412         // Update the DpnToInterfaceList OpDS
413         createOrUpdateDpnToInterface(dpId, interfaceName,interfaceOperShardTransaction);
414     }
415
416     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
417         .ietf.interfaces.rev140508.interfaces.state.Interface addStateEntry(
418             Interface interfaceInfo, String interfaceName, WriteTransaction transaction, IdManagerService idManager,
419             PhysAddress physAddress, OperStatus operStatus, AdminStatus adminStatus, NodeConnectorId nodeConnectorId) {
420         LOG.debug("adding interface state for {}", interfaceName);
421         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
422         Integer ifIndex;
423         if (interfaceInfo != null) {
424             if (!interfaceInfo.isEnabled()) {
425                 operStatus = OperStatus.Down;
426             }
427             ifaceBuilder.setType(interfaceInfo.getType());
428             // retrieve if-index only for northbound configured interfaces
429             ifIndex = IfmUtil.allocateId(idManager, IfmConstants.IFM_IDPOOL_NAME, interfaceName);
430             ifaceBuilder.setIfIndex(ifIndex);
431             InterfaceMetaUtils.createLportTagInterfaceMap(transaction, interfaceName, ifIndex);
432         }
433         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
434             .ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = IfmUtil
435                 .buildStateInterfaceId(interfaceName);
436         List<String> childLowerLayerIfList = new ArrayList<>();
437         childLowerLayerIfList.add(0, nodeConnectorId.getValue());
438         ifaceBuilder.setAdminStatus(adminStatus).setOperStatus(operStatus).setPhysAddress(physAddress)
439                 .setLowerLayerIf(childLowerLayerIfList);
440         ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
441         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
442             .ietf.interfaces.rev140508.interfaces.state.Interface ifState = ifaceBuilder
443                 .build();
444         if (InterfaceManagerCommonUtils.isTunnelInterface(interfaceInfo)) {
445             BatchingUtils.write(ifStateId, ifState, BatchingUtils.EntityType.DEFAULT_OPERATIONAL);
446         } else {
447             transaction.put(LogicalDatastoreType.OPERATIONAL, ifStateId, ifState, true);
448         }
449
450         BigInteger dpId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
451         // Update the DpnToInterfaceList OpDS
452         createOrUpdateDpnToInterface(dpId, interfaceName, transaction);
453         return ifState;
454     }
455
456     public static boolean checkIfBfdStateIsDown(String interfaceName) {
457         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
458             .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus = InterfaceManagerCommonUtils
459                 .getBfdStateFromCache(interfaceName);
460         return operStatus == org.opendaylight.yang.gen.v1.urn
461                 .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
462     }
463
464
465     public static void deleteStateEntry(String interfaceName, WriteTransaction transaction) {
466         LOG.debug("removing interface state entry for {}", interfaceName);
467         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
468             .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifChildStateId = IfmUtil
469                 .buildStateInterfaceId(interfaceName);
470         transaction.delete(LogicalDatastoreType.OPERATIONAL, ifChildStateId);
471     }
472
473     public static void deleteInterfaceStateInformation(String interfaceName, WriteTransaction transaction,
474             IdManagerService idManagerService) {
475         LOG.debug("removing interface state information for {}", interfaceName);
476         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
477             .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = IfmUtil
478                 .buildStateInterfaceId(interfaceName);
479         transaction.delete(LogicalDatastoreType.OPERATIONAL, ifStateId);
480         InterfaceMetaUtils.removeLportTagInterfaceMap(idManagerService, transaction, interfaceName);
481     }
482
483     // For trunk interfaces, binding to a parent interface which is already
484     // bound to another trunk interface should not
485     // be allowed
486     public static boolean createInterfaceChildEntryIfNotPresent(DataBroker dataBroker, WriteTransaction tx,
487                                                                 String parentInterface, String childInterface,
488                                                                 IfL2vlan.L2vlanMode l2vlanMode) {
489         InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
490         InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryIdentifier = InterfaceMetaUtils
491                 .getInterfaceParentEntryIdentifier(interfaceParentEntryKey);
492         InterfaceParentEntry interfaceParentEntry = InterfaceMetaUtils
493                 .getInterfaceParentEntryFromConfigDS(interfaceParentEntryIdentifier, dataBroker);
494
495         if (interfaceParentEntry != null) {
496             List<InterfaceChildEntry> interfaceChildEntries = interfaceParentEntry.getInterfaceChildEntry();
497             if (interfaceChildEntries != null && interfaceChildEntries.contains(childInterface)) {
498                 LOG.trace("Child entry for interface {} already exists", childInterface);
499                 return false;
500             }
501
502             if (l2vlanMode == IfL2vlan.L2vlanMode.Trunk && interfaceChildEntries != null) {
503                 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
504                     String curChildInterface = interfaceChildEntry.getChildInterface();
505                     Interface iface = getInterfaceFromConfigDS(curChildInterface, dataBroker);
506                     if (isTrunkInterface(iface)) {
507                         LOG.error(
508                                 "Trying to bind child interface {} of type Trunk to parent interface {},"
509                                         + "but it is already bound to a trunk interface {}",
510                                 childInterface, parentInterface, curChildInterface);
511                         return false;
512                     }
513                 }
514             }
515         }
516
517         LOG.info("Creating child interface {} of type {} bound on parent-interface {}",
518                 childInterface, l2vlanMode, parentInterface);
519         createInterfaceChildEntry(parentInterface, childInterface, Optional.of(tx));
520         return true;
521     }
522
523     public static boolean isTrunkInterface(Interface iface) {
524         if (iface != null) {
525             IfL2vlan ifL2vlan = iface.getAugmentation(IfL2vlan.class);
526             return ifL2vlan != null && IfL2vlan.L2vlanMode.Trunk.equals(ifL2vlan.getL2vlanMode());
527         }
528
529         return false;
530     }
531
532     public static boolean deleteParentInterfaceEntry(String parentInterface) {
533         if (parentInterface == null) {
534             return false;
535         }
536         InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
537         InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryIdentifier = InterfaceMetaUtils
538                 .getInterfaceParentEntryIdentifier(interfaceParentEntryKey);
539         BatchingUtils.delete(interfaceParentEntryIdentifier, BatchingUtils.EntityType.DEFAULT_CONFIG);
540         return true;
541     }
542
543     /*
544      * update operational state of interface based on events like tunnel
545      * monitoring
546      */
547     public static void updateOpState(WriteTransaction transaction, String interfaceName,
548             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
549             .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus) {
550         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
551             .ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = IfmUtil
552                 .buildStateInterfaceId(interfaceName);
553         LOG.debug("updating tep interface state as {} for {}", operStatus.name(), interfaceName);
554         InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setOperStatus(operStatus);
555         ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
556         transaction.merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build(), false);
557     }
558
559     public static boolean isTunnelInterface(Interface interfaceInfo) {
560         return interfaceInfo != null && interfaceInfo.getAugmentation(IfTunnel.class) != null;
561     }
562
563     public static boolean isVlanInterface(Interface interfaceInfo) {
564         return interfaceInfo != null && interfaceInfo.getAugmentation(IfL2vlan.class) != null;
565     }
566
567     // Cache Util methods
568     public static void addInterfaceToCache(Interface iface) {
569         interfaceConfigMap.put(iface.getName(), iface);
570     }
571
572     public static void removeFromInterfaceCache(Interface iface) {
573         interfaceConfigMap.remove(iface.getName());
574     }
575
576     public static void addInterfaceStateToCache(
577             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
578             .ietf.interfaces.rev140508.interfaces.state.Interface iface) {
579         interfaceStateMap.put(iface.getName(), iface);
580     }
581
582     public static void removeFromInterfaceStateCache(
583             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
584             .ietf.interfaces.rev140508.interfaces.state.Interface iface) {
585         interfaceStateMap.remove(iface.getName());
586     }
587
588     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
589         .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus getBfdStateFromCache(String interfaceName) {
590         return bfdStateMap.get(interfaceName);
591     }
592
593     public static void addBfdStateToCache(String interfaceName,
594             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
595                 .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus) {
596         bfdStateMap.put(interfaceName, operStatus);
597     }
598
599     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
600         .ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus removeBfdStateFromCache(
601             String interfaceName) {
602         return bfdStateMap.remove(interfaceName);
603     }
604
605     public static boolean isNovaOrTunnelPort(String portName) {
606         Matcher matcher = NOVA_OR_TUNNEL_PORT_PATTERN.matcher(portName);
607         return matcher.matches();
608     }
609
610     public static boolean isNovaPort(String portName) {
611         Matcher matcher = NOVA_PORT_PATTERN.matcher(portName);
612         return matcher.matches();
613     }
614
615     public static boolean isTunnelPort(String portName) {
616         Matcher matcher = TUNNEL_PORT_PATTERN.matcher(portName);
617         return matcher.matches();
618     }
619
620     public static void createOrUpdateDpnToInterface(BigInteger dpId, String infName, WriteTransaction transaction) {
621         DpnToInterfaceKey dpnToInterfaceKey = new DpnToInterfaceKey(dpId);
622         InterfaceNameEntryKey interfaceNameEntryKey = new InterfaceNameEntryKey(infName);
623         InstanceIdentifier<InterfaceNameEntry> intfid = InstanceIdentifier.builder(DpnToInterfaceList.class)
624                                                         .child(DpnToInterface.class, dpnToInterfaceKey)
625                                                         .child(InterfaceNameEntry.class, interfaceNameEntryKey)
626                                                         .build();
627         InterfaceNameEntryBuilder entryBuilder =
628                 new InterfaceNameEntryBuilder().setKey(interfaceNameEntryKey).setInterfaceName(infName);
629         BatchingUtils.write(intfid, entryBuilder.build(), BatchingUtils.EntityType.DEFAULT_OPERATIONAL);
630     }
631
632     public static void deleteDpnToInterface(DataBroker dataBroker,
633             BigInteger dpId, String infName, WriteTransaction transaction) {
634         DpnToInterfaceKey dpnToInterfaceKey = new DpnToInterfaceKey(dpId);
635         InstanceIdentifier<DpnToInterface> dpnToInterfaceId = InstanceIdentifier.builder(DpnToInterfaceList.class)
636                 .child(DpnToInterface.class, dpnToInterfaceKey).build();
637         Optional<DpnToInterface> dpnToInterfaceOptional =
638                 IfmUtil.read(LogicalDatastoreType.OPERATIONAL, dpnToInterfaceId, dataBroker);
639         if (!dpnToInterfaceOptional.isPresent()) {
640             LOG.debug("DPN {} is already removed from the Operational DS", dpId);
641             return;
642         }
643
644         List<InterfaceNameEntry> interfaceNameEntries = dpnToInterfaceOptional.get().getInterfaceNameEntry();
645         InterfaceNameEntryKey interfaceNameEntryKey = new InterfaceNameEntryKey(infName);
646         InstanceIdentifier<InterfaceNameEntry> intfid = InstanceIdentifier.builder(DpnToInterfaceList.class)
647                 .child(DpnToInterface.class, dpnToInterfaceKey)
648                 .child(InterfaceNameEntry.class, interfaceNameEntryKey)
649                 .build();
650         transaction.delete(LogicalDatastoreType.OPERATIONAL, intfid);
651
652         if (interfaceNameEntries.size() <= 1) {
653             transaction.delete(LogicalDatastoreType.OPERATIONAL, dpnToInterfaceId);
654         }
655     }
656
657     public static String getPortNameForInterface(NodeConnectorId nodeConnectorId, String portName) {
658         if (isNovaOrTunnelPort(portName)) {
659             return portName;
660         } else {
661             return getDpnPrefixedPortName(nodeConnectorId, portName);
662         }
663     }
664
665     public static String getPortNameForInterface(String dpnId, String portName) {
666         if (isNovaOrTunnelPort(portName)) {
667             return portName;
668         } else {
669             return getDpnPrefixedPortName(dpnId, portName);
670         }
671     }
672
673     private static String getDpnPrefixedPortName(NodeConnectorId nodeConnectorId, String portName) {
674         String dpnId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId).toString();
675         return getDpnPrefixedPortName(dpnId, portName);
676     }
677
678     private static String getDpnPrefixedPortName(String dpnId, String portName) {
679         return dpnId + IfmConstants.OF_URI_SEPARATOR + portName;
680     }
681 }