Bug 6786: L3VPN is not honoring VTEP add or delete in operational cloud
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / commons / InterfaceManagerCommonUtils.java
1 /*
2  * Copyright (c) 2016 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.LinkedList;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.concurrent.ConcurrentHashMap;
19 import java.util.regex.Matcher;
20 import java.util.regex.Pattern;
21
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.genius.interfacemanager.IfmConstants;
26 import org.opendaylight.genius.interfacemanager.IfmUtil;
27 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
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.InstructionType;
32 import org.opendaylight.genius.mdsalutil.MDSALUtil;
33 import org.opendaylight.genius.mdsalutil.MatchFieldType;
34 import org.opendaylight.genius.mdsalutil.MatchInfo;
35 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
36 import org.opendaylight.genius.mdsalutil.NwConstants;
37 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.DpnToInterfaceList;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntryKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntryBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.DpnToInterface;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.DpnToInterfaceBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.DpnToInterfaceKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.dpn.to._interface.InterfaceNameEntry;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.dpn.to._interface.InterfaceNameEntryBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.dpn.to._interface.list.dpn.to._interface.InterfaceNameEntryKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
67 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70
71 public class InterfaceManagerCommonUtils {
72     private static final Logger LOG = LoggerFactory.getLogger(InterfaceManagerCommonUtils.class);
73     private static ConcurrentHashMap<String, Interface> interfaceConfigMap = new ConcurrentHashMap<>();
74     private static ConcurrentHashMap<String, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceStateMap = new ConcurrentHashMap<>();
75     private static ConcurrentHashMap<String, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus> bfdStateMap =
76             new ConcurrentHashMap<String, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus>();
77
78     private static final String NOVA_OR_TUNNEL_PORT_REGEX = "(tap|vhu)[0-9a-f]{8}-[0-9a-f]{2}|tun[0-9a-f]{11}";
79     private static final Pattern pattern = Pattern.compile(NOVA_OR_TUNNEL_PORT_REGEX);
80
81     public static NodeConnector getNodeConnectorFromInventoryOperDS(NodeConnectorId nodeConnectorId,
82             DataBroker dataBroker) {
83         NodeId nodeId = IfmUtil.getNodeIdFromNodeConnectorId(nodeConnectorId);
84         InstanceIdentifier<NodeConnector> ncIdentifier = InstanceIdentifier.builder(Nodes.class)
85                 .child(Node.class, new NodeKey(nodeId))
86                 .child(NodeConnector.class, new NodeConnectorKey(nodeConnectorId)).build();
87
88         Optional<NodeConnector> nodeConnectorOptional = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, ncIdentifier,
89                 dataBroker);
90         if (!nodeConnectorOptional.isPresent()) {
91             return null;
92         }
93         return nodeConnectorOptional.get();
94     }
95
96     public static boolean isNodePresent(DataBroker dataBroker, NodeConnectorId nodeConnectorId) {
97         NodeId nodeID = IfmUtil.getNodeIdFromNodeConnectorId(nodeConnectorId);
98         InstanceIdentifier<Node> nodeInstanceIdentifier = InstanceIdentifier.builder(Nodes.class)
99                 .child(Node.class, new NodeKey(nodeID)).build();
100         Optional<Node> node = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, nodeInstanceIdentifier, dataBroker);
101
102         if (node.isPresent()) {
103             return true;
104         }
105         return false;
106     }
107
108     public static InstanceIdentifier<Interface> getInterfaceIdentifier(InterfaceKey interfaceKey) {
109         InstanceIdentifier.InstanceIdentifierBuilder<Interface> interfaceInstanceIdentifierBuilder = InstanceIdentifier
110                 .builder(Interfaces.class).child(Interface.class, interfaceKey);
111         return interfaceInstanceIdentifierBuilder.build();
112     }
113
114     public static List<Interface> getAllTunnelInterfaces(DataBroker dataBroker,
115             InterfaceInfo.InterfaceType interfaceType) {
116         List<Interface> vxlanList = new ArrayList<>();
117         InstanceIdentifier<Interfaces> interfacesInstanceIdentifier = InstanceIdentifier.builder(Interfaces.class)
118                 .build();
119         Optional<Interfaces> interfacesOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION,
120                 interfacesInstanceIdentifier, dataBroker);
121         if (!interfacesOptional.isPresent()) {
122             return vxlanList;
123         }
124         Interfaces interfaces = interfacesOptional.get();
125         List<Interface> interfacesList = interfaces.getInterface();
126         for (Interface iface : interfacesList) {
127             if (IfmUtil.getInterfaceType(iface) == InterfaceInfo.InterfaceType.VXLAN_TRUNK_INTERFACE
128                     && iface.getAugmentation(IfTunnel.class).isInternal()) {
129                 vxlanList.add(iface);
130             }
131         }
132         return vxlanList;
133     }
134
135     /**
136      * Searches for an interface by its name
137      * @param interfaceName name of the interface to search for
138      * @param dataBroker data tree store to start searching for the interface
139      * @return the Interface object
140      *
141      */
142     public static Interface getInterfaceFromConfigDS (String interfaceName, DataBroker dataBroker) {
143         Interface iface = interfaceConfigMap.get(interfaceName);
144         if (iface != null) {
145             return iface;
146         }
147         InstanceIdentifier<Interface> interfaceId = getInterfaceIdentifier(new InterfaceKey(interfaceName));
148         Optional<Interface> interfaceOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION, interfaceId,
149                 dataBroker);
150         if (interfaceOptional.isPresent()) {
151             iface = interfaceOptional.get();
152             interfaceConfigMap.put(iface.getName(), iface);
153         }
154         return iface;
155     }
156
157     @Deprecated
158     public static Interface getInterfaceFromConfigDS (InterfaceKey interfaceKey, DataBroker dataBroker) {
159         return getInterfaceFromConfigDS(interfaceKey.getName(), dataBroker);
160     }
161
162     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(
163             String interfaceName, DataBroker dataBroker) {
164         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState = interfaceStateMap
165                 .get(interfaceName);
166         if (ifState != null) {
167             return ifState;
168         }
169         Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional = IfmUtil
170                 .read(LogicalDatastoreType.OPERATIONAL, IfmUtil.buildStateInterfaceId(interfaceName), dataBroker);
171         if (ifStateOptional.isPresent()) {
172             ifState = ifStateOptional.get();
173             interfaceStateMap.put(ifState.getName(), ifState);
174         }
175         return ifState;
176     }
177
178     @Deprecated
179     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(
180             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId,
181             DataBroker dataBroker) {
182         Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional = IfmUtil
183                 .read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker);
184         if (!ifStateOptional.isPresent()) {
185             return null;
186         }
187
188         return ifStateOptional.get();
189     }
190
191     public static void makeTunnelIngressFlow(List<ListenableFuture<Void>> futures, IMdsalApiManager mdsalApiManager,
192             IfTunnel tunnel, BigInteger dpnId, long portNo, String interfaceName, int ifIndex, int addOrRemoveFlow) {
193         LOG.debug("make tunnel ingress flow for {}", interfaceName);
194         String flowRef = InterfaceManagerCommonUtils.getTunnelInterfaceFlowRef(dpnId,
195                 NwConstants.VLAN_INTERFACE_INGRESS_TABLE, interfaceName);
196         List<MatchInfo> matches = new ArrayList<>();
197         List<InstructionInfo> mkInstructions = new ArrayList<>();
198         if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
199             matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] { dpnId, BigInteger.valueOf(portNo) }));
200             mkInstructions.add(new InstructionInfo(InstructionType.write_metadata,
201                     new BigInteger[] { MetaDataUtil.getLportTagMetaData(ifIndex).or(BigInteger.ONE),
202                             MetaDataUtil.METADATA_MASK_LPORT_TAG_SH_FLAG }));
203             short tableId = (tunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeMplsOverGre.class))
204                     ? NwConstants.L3_LFIB_TABLE
205                     : tunnel.isInternal() ? NwConstants.INTERNAL_TUNNEL_TABLE : NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL;
206             mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { tableId }));
207         }
208
209         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, flowRef,
210                 IfmConstants.DEFAULT_FLOW_PRIORITY, interfaceName, 0, 0, NwConstants.COOKIE_VM_INGRESS_TABLE, matches,
211                 mkInstructions);
212         if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
213             futures.add(mdsalApiManager.installFlow(dpnId, flowEntity));
214         } else {
215             futures.add(mdsalApiManager.removeFlow(dpnId, flowEntity));
216         }
217     }
218
219     public static String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
220         return new StringBuilder().append(dpnId).append(tableId).append(ifName).toString();
221     }
222
223     public static void setOpStateForInterface(DataBroker broker, String interfaceName,
224             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opStatus) {
225         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceId = IfmUtil
226                 .buildStateInterfaceId(interfaceName);
227         InterfaceBuilder ifaceBuilder = new InterfaceBuilder()
228                 .setKey(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(
229                         interfaceName));
230         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceData = ifaceBuilder
231                 .setOperStatus(opStatus).build();
232         MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceData);
233     }
234
235     public static void createInterfaceChildEntry(WriteTransaction t, String parentInterface, String childInterface) {
236         InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
237         InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(childInterface);
238         InstanceIdentifier<InterfaceChildEntry> intfId = InterfaceMetaUtils
239                 .getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey);
240         InterfaceChildEntryBuilder entryBuilder = new InterfaceChildEntryBuilder().setKey(interfaceChildEntryKey)
241                 .setChildInterface(childInterface);
242         t.put(LogicalDatastoreType.CONFIGURATION, intfId, entryBuilder.build(), true);
243     }
244
245     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus updateStateEntry(
246             Interface interfaceNew, DataBroker dataBroker, WriteTransaction transaction,
247             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
248         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus;
249         if (!interfaceNew.isEnabled()) {
250             operStatus = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
251         } else {
252             String ncStr = ifState.getLowerLayerIf().get(0);
253             NodeConnectorId nodeConnectorId = new NodeConnectorId(ncStr);
254             NodeConnector nodeConnector = InterfaceManagerCommonUtils
255                     .getNodeConnectorFromInventoryOperDS(nodeConnectorId, dataBroker);
256             FlowCapableNodeConnector flowCapableNodeConnector = nodeConnector
257                     .getAugmentation(FlowCapableNodeConnector.class);
258             // State state = flowCapableNodeConnector.getState();
259             operStatus = flowCapableNodeConnector == null
260                     ? org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down
261                     : org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up;
262         }
263
264         String ifName = interfaceNew.getName();
265         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = IfmUtil
266                 .buildStateInterfaceId(interfaceNew.getName());
267         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
268         ifaceBuilder.setOperStatus(operStatus);
269         ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(ifName));
270         transaction.merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build());
271         return operStatus;
272     }
273
274     public static void updateOperStatus(String interfaceName,
275             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus,
276             WriteTransaction transaction) {
277         LOG.debug("updating operational status for interface {}", interfaceName);
278         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifChildStateId = IfmUtil
279                 .buildStateInterfaceId(interfaceName);
280         InterfaceBuilder ifaceBuilderChild = new InterfaceBuilder();
281         ifaceBuilderChild.setOperStatus(operStatus);
282         ifaceBuilderChild.setKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
283         transaction.merge(LogicalDatastoreType.OPERATIONAL, ifChildStateId, ifaceBuilderChild.build());
284     }
285
286     public static void addStateEntry(String interfaceName, DataBroker dataBroker,
287                                      IdManagerService idManager, List<ListenableFuture<Void>> futures,
288                                      org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
289         WriteTransaction interfaceOperShardTransaction = dataBroker.newWriteOnlyTransaction();
290         addStateEntry(interfaceName, dataBroker, interfaceOperShardTransaction, idManager, futures, ifState);
291         futures.add(interfaceOperShardTransaction.submit());
292     }
293
294     public static void addStateEntry(String interfaceName, DataBroker dataBroker, WriteTransaction interfaceOperShardTransaction,
295                                      IdManagerService idManager, List<ListenableFuture<Void>> futures,
296                                      org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
297         // allocate lport tag and create interface-if-index map.
298         // This is done even if interface-state is not present, so that there is
299         // no throttling
300         // on id allocation even when multiple southbound port_up events come in
301         // one shot
302         Integer ifIndex = IfmUtil.allocateId(idManager, IfmConstants.IFM_IDPOOL_NAME, interfaceName);
303         InterfaceMetaUtils.createLportTagInterfaceMap(interfaceOperShardTransaction, interfaceName, ifIndex);
304         if (ifState == null) {
305             LOG.debug("could not retrieve interface state corresponding to {}", interfaceName);
306             return;
307         }
308         LOG.debug("adding interface state for {}", interfaceName);
309         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus = ifState
310                 .getOperStatus();
311         PhysAddress physAddress = ifState.getPhysAddress();
312         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus adminStatus = ifState
313                 .getAdminStatus();
314         NodeConnectorId nodeConnectorId = new NodeConnectorId(ifState.getLowerLayerIf().get(0));
315         InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
316         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface interfaceInfo = InterfaceManagerCommonUtils
317                 .getInterfaceFromConfigDS(interfaceKey, dataBroker);
318
319         if (interfaceInfo != null && !interfaceInfo.isEnabled()) {
320             operStatus = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
321         }
322
323         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = IfmUtil
324                 .buildStateInterfaceId(interfaceName);
325         List<String> childLowerLayerIfList = new ArrayList<>();
326         childLowerLayerIfList.add(0, nodeConnectorId.getValue());
327         InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setAdminStatus(adminStatus).setOperStatus(operStatus)
328                 .setPhysAddress(physAddress).setLowerLayerIf(childLowerLayerIfList);
329         ifaceBuilder.setIfIndex(ifIndex);
330
331         if (interfaceInfo != null) {
332             ifaceBuilder.setType(interfaceInfo.getType());
333         }
334         ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
335         interfaceOperShardTransaction.put(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build(), true);
336
337         // install ingress flow
338         BigInteger dpId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
339         long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
340         if (interfaceInfo != null && interfaceInfo.isEnabled() && ifState
341                 .getOperStatus() == org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up) {
342             FlowBasedServicesUtils.installLportIngressFlow(dpId, portNo, interfaceInfo, futures, dataBroker, ifIndex);
343             FlowBasedServicesUtils.bindDefaultEgressDispatcherService(dataBroker, futures, interfaceInfo, Long.toString(portNo), interfaceName, ifIndex);
344         }
345
346         // Update the DpnToInterfaceList OpDS
347         createOrUpdateDpnToInterface(dpId, interfaceName,interfaceOperShardTransaction);
348     }
349
350     public static boolean checkIfBfdStateIsDown(String interfaceName){
351         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus =
352                 InterfaceManagerCommonUtils.getBfdStateFromCache(interfaceName);
353         return (operStatus == org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down);
354     }
355
356     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface addStateEntry(
357             DataBroker dataBroker, Interface interfaceInfo, String interfaceName, WriteTransaction transaction, IdManagerService idManager,
358             PhysAddress physAddress,
359             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus,
360             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus adminStatus,
361             NodeConnectorId nodeConnectorId) {
362         LOG.debug("adding interface state for {}", interfaceName);
363         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
364         Integer ifIndex = null;
365         if (interfaceInfo != null) {
366             if(!interfaceInfo.isEnabled() || (InterfaceManagerCommonUtils.isTunnelInterface(interfaceInfo) &&
367                     checkIfBfdStateIsDown(interfaceInfo.getName()))){
368                 operStatus = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
369             }
370
371             ifaceBuilder.setType(interfaceInfo.getType());
372             // retrieve if-index only for northbound configured interfaces
373             ifIndex = IfmUtil.allocateId(idManager, IfmConstants.IFM_IDPOOL_NAME, interfaceName);
374             ifaceBuilder.setIfIndex(ifIndex);
375             InterfaceMetaUtils.createLportTagInterfaceMap(transaction, interfaceName, ifIndex);
376         }
377         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = IfmUtil
378                 .buildStateInterfaceId(interfaceName);
379         List<String> childLowerLayerIfList = new ArrayList<>();
380         childLowerLayerIfList.add(0, nodeConnectorId.getValue());
381         ifaceBuilder.setAdminStatus(adminStatus).setOperStatus(operStatus).setPhysAddress(physAddress)
382                 .setLowerLayerIf(childLowerLayerIfList);
383         ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
384         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState = ifaceBuilder
385                 .build();
386         transaction.put(LogicalDatastoreType.OPERATIONAL, ifStateId, ifState, true);
387
388         BigInteger dpId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
389         // Update the DpnToInterfaceList OpDS
390         createOrUpdateDpnToInterface(dpId, interfaceName, transaction);
391         return ifState;
392     }
393
394     public static void deleteStateEntry(String interfaceName, WriteTransaction transaction) {
395         LOG.debug("removing interface state entry for {}", interfaceName);
396         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifChildStateId = IfmUtil
397                 .buildStateInterfaceId(interfaceName);
398         transaction.delete(LogicalDatastoreType.OPERATIONAL, ifChildStateId);
399     }
400
401     public static void deleteInterfaceStateInformation(String interfaceName, WriteTransaction transaction,
402             IdManagerService idManagerService) {
403         LOG.debug("removing interface state information for {}", interfaceName);
404         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = IfmUtil
405                 .buildStateInterfaceId(interfaceName);
406         transaction.delete(LogicalDatastoreType.OPERATIONAL, ifStateId);
407         InterfaceMetaUtils.removeLportTagInterfaceMap(idManagerService, transaction, interfaceName);
408     }
409
410     // For trunk interfaces, binding to a parent interface which is already
411     // bound to another trunk interface should not
412     // be allowed
413     public static boolean createInterfaceChildEntryIfNotPresent(DataBroker dataBroker, WriteTransaction t,
414             String parentInterface, String childInterface) {
415         InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
416         InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryIdentifier = InterfaceMetaUtils
417                 .getInterfaceParentEntryIdentifier(interfaceParentEntryKey);
418         InterfaceParentEntry interfaceParentEntry = InterfaceMetaUtils
419                 .getInterfaceParentEntryFromConfigDS(interfaceParentEntryIdentifier, dataBroker);
420
421         if (interfaceParentEntry != null) {
422             LOG.error("Trying to bind the same parent interface {} to multiple trunk interfaces. ", parentInterface);
423             return false;
424         }
425
426         LOG.info("First vlan trunk {} bound on parent-interface {}", childInterface, parentInterface);
427         InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(childInterface);
428         InstanceIdentifier<InterfaceChildEntry> intfId = InterfaceMetaUtils
429                 .getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey);
430         InterfaceChildEntryBuilder entryBuilder = new InterfaceChildEntryBuilder().setKey(interfaceChildEntryKey)
431                 .setChildInterface(childInterface);
432         t.put(LogicalDatastoreType.CONFIGURATION, intfId, entryBuilder.build(), true);
433         return true;
434     }
435
436     public static boolean deleteParentInterfaceEntry(WriteTransaction t, String parentInterface) {
437         InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
438         InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryIdentifier = InterfaceMetaUtils
439                 .getInterfaceParentEntryIdentifier(interfaceParentEntryKey);
440         t.delete(LogicalDatastoreType.CONFIGURATION, interfaceParentEntryIdentifier);
441         return true;
442     }
443
444     /*
445      * update operational state of interface based on events like tunnel
446      * monitoring
447      */
448     public static void updateOpState(WriteTransaction transaction, String interfaceName,
449             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus) {
450         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = IfmUtil
451                 .buildStateInterfaceId(interfaceName);
452         LOG.debug("updating tep interface state as {} for {}", operStatus.name(), interfaceName);
453         InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setOperStatus(operStatus);
454         ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
455         transaction.merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build(), false);
456     }
457
458     public static boolean isTunnelInterface(Interface interfaceInfo) {
459         if (interfaceInfo != null && interfaceInfo.getAugmentation(IfTunnel.class) != null) {
460             return true;
461         }
462         return false;
463     }
464
465     public static boolean isVlanInterface(Interface interfaceInfo) {
466         if (interfaceInfo != null && interfaceInfo.getAugmentation(IfL2vlan.class) != null) {
467             return true;
468         }
469         return false;
470     }
471
472     // Cache Util methods
473     public static void addInterfaceToCache(Interface iface) {
474         interfaceConfigMap.put(iface.getName(), iface);
475     }
476
477     public static void removeFromInterfaceCache(Interface iface) {
478         interfaceConfigMap.remove(iface.getName());
479     }
480
481     public static void addInterfaceStateToCache(
482             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface iface) {
483         interfaceStateMap.put(iface.getName(), iface);
484     }
485
486     public static void removeFromInterfaceStateCache(
487             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface iface) {
488         interfaceStateMap.remove(iface.getName());
489     }
490
491     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus getBfdStateFromCache(String interfaceName) {
492         return bfdStateMap.get(interfaceName);
493     }
494
495     public static void addBfdStateToCache(String interfaceName,
496                                           org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus) {
497         bfdStateMap.put(interfaceName, operStatus);
498     }
499
500     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus removeBfdStateFromCache(String interfaceName){
501         return bfdStateMap.remove(interfaceName);
502     }
503
504     public static boolean isNovaOrTunnelPort(String portName) {
505
506         Matcher matcher = pattern.matcher(portName);
507         return matcher.matches();
508     }
509
510
511     public static void createOrUpdateDpnToInterface(BigInteger dpId, String infName, WriteTransaction transaction) {
512         DpnToInterfaceKey dpnToInterfaceKey = new DpnToInterfaceKey(dpId);
513         InterfaceNameEntryKey interfaceNameEntryKey = new InterfaceNameEntryKey(infName);
514         InstanceIdentifier<InterfaceNameEntry> intfid = InstanceIdentifier.builder(DpnToInterfaceList.class)
515                                                         .child(DpnToInterface.class, dpnToInterfaceKey)
516                                                         .child(InterfaceNameEntry.class, interfaceNameEntryKey)
517                                                         .build();
518         InterfaceNameEntryBuilder entryBuilder = new InterfaceNameEntryBuilder().setKey(interfaceNameEntryKey).setInterfaceName(infName);
519         transaction.put(LogicalDatastoreType.OPERATIONAL, intfid, entryBuilder.build(), true);
520     }
521
522     public static void deleteDpnToInterface(DataBroker dataBroker, BigInteger dpId, String infName, WriteTransaction transaction) {
523         DpnToInterfaceKey dpnToInterfaceKey = new DpnToInterfaceKey(dpId);
524         InstanceIdentifier<DpnToInterface> dpnToInterfaceId = InstanceIdentifier.builder(DpnToInterfaceList.class)
525                 .child(DpnToInterface.class, dpnToInterfaceKey).build();
526         Optional<DpnToInterface> dpnToInterfaceOptional = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, dpnToInterfaceId, dataBroker);
527         if (!dpnToInterfaceOptional.isPresent()) {
528             LOG.debug("DPN {} is already removed from the Operational DS", dpId);
529             return;
530         }
531
532         List<InterfaceNameEntry> interfaceNameEntries = dpnToInterfaceOptional.get().getInterfaceNameEntry();
533         InterfaceNameEntryKey interfaceNameEntryKey = new InterfaceNameEntryKey(infName);
534         InstanceIdentifier<InterfaceNameEntry> intfid = InstanceIdentifier.builder(DpnToInterfaceList.class)
535                 .child(DpnToInterface.class, dpnToInterfaceKey)
536                 .child(InterfaceNameEntry.class, interfaceNameEntryKey)
537                 .build();
538         transaction.delete(LogicalDatastoreType.OPERATIONAL, intfid);
539
540         if (interfaceNameEntries.size() <=1) {
541             transaction.delete(LogicalDatastoreType.OPERATIONAL, dpnToInterfaceId);
542         }
543     }
544
545 }