Interfacemgr: More APIs and calls to IdManager
[vpnservice.git] / interfacemgr / interfacemgr-impl / src / main / java / org / opendaylight / vpnservice / interfacemgr / InterfaceManager.java
1 /*
2  * Copyright (c) 2015 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.vpnservice.interfacemgr;
9
10 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
11
12 import org.opendaylight.vpnservice.mdsalutil.InstructionType;
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.Mpls;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfMpls;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfStackedVlan;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.StackedVlan;
18 import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
19 import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.Pools;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPool;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPoolKey;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.id.pool.GeneratedIds;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdOutput;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInputBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInput;
27 import java.util.concurrent.ExecutionException;
28 import java.util.concurrent.Future;
29 import org.opendaylight.yangtools.yang.common.RpcResult;
30 import org.opendaylight.idmanager.IdManager;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
32 import java.util.ArrayList;
33 import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
35 import java.util.List;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL3tunnel;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.L3tunnel;
38 import java.util.Map;
39 import java.util.concurrent.ConcurrentHashMap;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
42 import com.google.common.util.concurrent.Futures;
43 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
45 import com.google.common.util.concurrent.FutureCallback;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.BaseIds;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
54 import org.opendaylight.vpnservice.AbstractDataChangeListener;
55 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
56 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
57 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
58 import org.opendaylight.yangtools.concepts.ListenerRegistration;
59 import org.opendaylight.yangtools.yang.binding.DataObject;
60 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
62 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
63 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
64 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
66 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
67 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70 import com.google.common.base.Optional;
71
72 public class InterfaceManager extends AbstractDataChangeListener<Interface> implements AutoCloseable {
73     private static final Logger LOG = LoggerFactory.getLogger(InterfaceManager.class);
74     private ListenerRegistration<DataChangeListener> listenerRegistration;
75     private final DataBroker broker;
76     private final IdManager idManager;
77     private final Map<NodeConnectorId, String> mapNcToInterfaceName = new ConcurrentHashMap<>();
78     private final Map<NodeId, String> dbDpnEndpoints = new ConcurrentHashMap<>();
79
80     private static final FutureCallback<Void> DEFAULT_CALLBACK =
81                     new FutureCallback<Void>() {
82                         public void onSuccess(Void result) {
83                             LOG.debug("Success in Datastore write operation");
84                         }
85
86                         public void onFailure(Throwable error) {
87                             LOG.error("Error in Datastore write operation", error);
88                         };
89                     };
90
91     public InterfaceManager(final DataBroker db, final IdManager idmgr) {
92         super(Interface.class);
93         broker = db;
94         idManager = idmgr;
95         registerListener(db);
96     }
97
98     @Override
99     public void close() throws Exception {
100         if (listenerRegistration != null) {
101             try {
102                 listenerRegistration.close();
103             } catch (final Exception e) {
104                 LOG.error("Error when cleaning up DataChangeListener.", e);
105             }
106             listenerRegistration = null;
107         }
108         LOG.info("Interface Manager Closed");
109     }
110
111     private void registerListener(final DataBroker db) {
112         try {
113             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
114                     getWildCardPath(), InterfaceManager.this, DataChangeScope.SUBTREE);
115         } catch (final Exception e) {
116             LOG.error("InterfaceManager DataChange listener registration fail!", e);
117             throw new IllegalStateException("InterfaceManager registration Listener failed.", e);
118         }
119     }
120
121     @Override
122     protected void add(final InstanceIdentifier<Interface> identifier,
123             final Interface imgrInterface) {
124         LOG.trace("Adding interface key: " + identifier + ", value=" + imgrInterface );
125         addInterface(identifier, imgrInterface);
126     }
127
128     private InstanceIdentifier<Interface> buildId(final InstanceIdentifier<Interface> identifier) {
129         //TODO Make this generic and move to AbstractDataChangeListener or Utils.
130         final InterfaceKey key = identifier.firstKeyOf(Interface.class, InterfaceKey.class);
131         return buildId(key.getName());
132     }
133
134     private InstanceIdentifier<Interface> buildId(String interfaceName) {
135         //TODO Make this generic and move to AbstractDataChangeListener or Utils.
136         InstanceIdentifierBuilder<Interface> idBuilder =
137                 InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName));
138         InstanceIdentifier<Interface> id = idBuilder.build();
139         return id;
140     }
141
142     private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
143         //TODO Make this generic and move to AbstractDataChangeListener or Utils.
144         InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder =
145                 InstanceIdentifier.builder(InterfacesState.class)
146                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
147                                 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
148         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder.build();
149         return id;
150     }
151
152     private void addInterface(final InstanceIdentifier<Interface> identifier,
153                               final Interface interf) {
154         NodeConnector nodeConn = getNodeConnectorFromDataStore(interf);
155         NodeConnectorId ncId = null;
156         updateInterfaceState(identifier, interf, nodeConn);
157         if (nodeConn == null) {
158             ncId = getNodeConnectorIdFromInterface(interf);
159         } else {
160             ncId = nodeConn.getId();
161         }
162         mapNcToInterfaceName.put(ncId, interf.getName());
163         LOG.info("interf.getType(: {}",interf.getType());
164         if(interf.getType().isInstance(L3tunnel.class)) {
165             NodeId nodeId = getNodeIdFromNodeConnectorId(ncId);
166             IfL3tunnel l3Tunnel = interf.getAugmentation(IfL3tunnel.class);
167             LOG.info("l3Tunnel: {}",l3Tunnel);
168             this.dbDpnEndpoints.put(nodeId, l3Tunnel.getLocalIp().getIpv4Address().getValue());
169         }
170     }
171
172     private void updateInterfaceState(InstanceIdentifier<Interface> identifier,
173                     Interface interf, NodeConnector nodeConn) {
174         /* Update InterfaceState
175          * 1. Get interfaces-state Identifier
176          * 2. Add interface to interfaces-state/interface
177          * 3. Get interface-id from id manager
178          * 4. Update interface-state with following:
179          *    admin-status = set to enable value
180          *    oper-status = Down [?]
181          *    if-index = interface-id
182         */
183         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id =
184                         buildStateInterfaceId(interf.getName());
185         Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> stateIf =
186                         read(LogicalDatastoreType.OPERATIONAL, id);
187         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface stateIface;
188         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder =
189                         new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder();
190         if(!stateIf.isPresent()) {
191             // TODO: Get interface-id from IdManager
192             String ifName = interf.getName();
193             ifaceBuilder.setAdminStatus((interf.isEnabled()) ?  org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Up :
194                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Down);
195             ifaceBuilder.setOperStatus(getOperStatus(nodeConn));
196
197             ifaceBuilder.setIfIndex(getIfIndex(ifName)).setName(ifName).setType(interf.getType());
198             ifaceBuilder.setKey(getStateInterfaceKeyFromName(ifName));
199             stateIface = ifaceBuilder.build();
200             LOG.trace("Adding stateIface {} and id {} to OPERATIONAL DS", stateIface, id);
201             asyncWrite(LogicalDatastoreType.OPERATIONAL, id, stateIface, DEFAULT_CALLBACK);
202         } else {
203             if(interf.isEnabled() != null) {
204                 ifaceBuilder.setAdminStatus((interf.isEnabled()) ?  org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Up :
205                     org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Down);
206             }
207             if(interf.getType() != null) {
208                 ifaceBuilder.setType(interf.getType());
209             }
210             ifaceBuilder.setOperStatus(getOperStatus(nodeConn));
211             stateIface = ifaceBuilder.build();
212             LOG.trace("updating OPERATIONAL data store with stateIface {} and id {}", stateIface, id);
213             asyncUpdate(LogicalDatastoreType.OPERATIONAL, id, stateIface, DEFAULT_CALLBACK);
214         }
215     }
216
217     /*
218     private void setAugmentations(
219                     org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder,
220                     InstanceIdentifier<Interface> identifier, Interface interf) {
221         // TODO Add code for all augmentations
222         InstanceIdentifier<IfL3tunnel> ifL3TunnelPath = identifier.augmentation(IfL3tunnel.class);
223         Optional<IfL3tunnel> l3Tunnel = read(LogicalDatastoreType.CONFIGURATION, ifL3TunnelPath);
224         String ifName = interf.getName();
225         if(l3Tunnel.isPresent()) {
226             l3Tunnel.get();
227         }
228     }
229     */
230
231     private Integer getIfIndex(String ifName) {
232         GetUniqueIdInput getIdInput = new GetUniqueIdInputBuilder()
233         .setPoolName("interfaces").setIdKey(ifName)
234         .build();
235         //TODO: Proper error handling once IdManager code is complete
236         try {
237             Future<RpcResult<GetUniqueIdOutput>> result = idManager.getUniqueId(getIdInput);
238             RpcResult<GetUniqueIdOutput> rpcResult = result.get();
239             return rpcResult.getResult().getIdValue().intValue();
240         } catch (NullPointerException | InterruptedException | ExecutionException e) {
241             LOG.trace("",e);
242         }
243         /* This currently returns null, so let us get it from IdManager DS
244          * TODO: Start-delete-me
245          */
246
247         InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
248                         InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey("interfaces"));
249         InstanceIdentifier<IdPool> id = idBuilder.build();
250         Optional<IdPool> globalPool = read(LogicalDatastoreType.OPERATIONAL, id);
251         Long newIdValue = null;
252         if (globalPool.isPresent()) {
253             IdPool pool = globalPool.get();
254             List<GeneratedIds> generatedIds = pool.getGeneratedIds();
255             if ((generatedIds != null) && !generatedIds.isEmpty()) {
256                 for (GeneratedIds gen_id : generatedIds) {
257                     if (gen_id.getIdKey().equals(ifName)) {
258                         newIdValue = gen_id.getIdValue();
259                         LOG.debug("Id {} found for interface %s ", newIdValue, ifName);
260                         return newIdValue.intValue();
261                     }
262                 }
263             }
264         }
265         //TODO: End-delete-me
266         LOG.debug("Unable to get valid ifIndex for interface {}", ifName);
267         return 65535;
268     }
269
270     private OperStatus getOperStatus(NodeConnector nodeConn) {
271         LOG.trace("nodeConn is {}", nodeConn);
272         if(nodeConn == null) {
273             return OperStatus.Down;
274         }else {
275             return OperStatus.Up;
276         }
277     }
278
279     private org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey getStateInterfaceKeyFromName(
280                     String name) {
281         return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(name);
282     }
283
284     private NodeConnector getNodeConnectorFromDataStore(Interface interf) {
285         NodeConnectorId ncId = interf.getAugmentation(BaseIds.class).getOfPortId();
286         //TODO: Replace with MDSAL Util method
287         NodeId nodeId = getNodeIdFromNodeConnectorId(ncId);
288         InstanceIdentifier<NodeConnector> ncIdentifier = InstanceIdentifier.builder(Nodes.class)
289                         .child(Node.class, new NodeKey(nodeId))
290                         .child(NodeConnector.class, new NodeConnectorKey(ncId)).build();
291
292         Optional<NodeConnector> nc = read(LogicalDatastoreType.OPERATIONAL, ncIdentifier);
293         if(nc.isPresent()) {
294             NodeConnector nodeConn = nc.get();
295             LOG.trace("nodeConnector: {}",nodeConn);
296             return nodeConn;
297         }
298         return null;
299     }
300
301     private NodeConnectorId getNodeConnectorIdFromInterface(Interface interf) {
302         return interf.getAugmentation(BaseIds.class).getOfPortId();
303     }
304
305     private void delInterface(final InstanceIdentifier<Interface> identifier,
306                               final Interface delInterface) {
307         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id =
308                         buildStateInterfaceId(delInterface.getName());
309         Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> stateIf =
310                         read(LogicalDatastoreType.OPERATIONAL, id);
311         if(stateIf.isPresent()) {
312             LOG.trace("deleting interfaces:state OPERATIONAL data store with id {}", id);
313             asyncRemove(LogicalDatastoreType.OPERATIONAL, id, DEFAULT_CALLBACK);
314             NodeConnectorId ncId = getNodeConnectorIdFromInterface(delInterface);
315             if(ncId != null) {
316                 mapNcToInterfaceName.remove(ncId);
317                 if(delInterface.getType().isInstance(L3tunnel.class)) {
318                     Node node = getNodeFromDataStore(delInterface);
319                     if((node != null) &&(node.getNodeConnector().isEmpty())) {
320                         this.dbDpnEndpoints.remove(node.getId());
321                     }
322                 }
323             }
324         }
325     }
326
327     private Node getNodeFromDataStore(Interface interf) {
328         NodeConnectorId ncId = interf.getAugmentation(BaseIds.class).getOfPortId();
329         //TODO: Replace with MDSAL Util method
330         NodeId nodeId = getNodeIdFromNodeConnectorId(ncId);
331         InstanceIdentifier<Node> ncIdentifier = InstanceIdentifier.builder(Nodes.class)
332                         .child(Node.class, new NodeKey(nodeId)).build();
333
334         Optional<Node> dpn = read(LogicalDatastoreType.OPERATIONAL, ncIdentifier);
335         if(dpn.isPresent()) {
336             Node node = dpn.get();
337             LOG.trace("node: {}",node);
338             return node;
339         }
340         return null;
341     }
342
343     private void updateInterface(final InstanceIdentifier<Interface> identifier,
344                               final Interface original, final Interface update) {
345         InstanceIdentifier<Interface> id = buildId(identifier);
346         Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
347         if(port.isPresent()) {
348             Interface interf = port.get();
349             NodeConnector nc = getNodeConnectorFromDataStore(update);
350             updateInterfaceState(identifier, update, nc);
351             /*
352              * Alternative is to get from interf and update map irrespective if NCID changed or not.
353              */
354             if(nc != null) {
355                 // Name doesn't change. Is it present in update?
356                 mapNcToInterfaceName.put(nc.getId(), original.getName());
357                 if(interf.getType().isInstance(L3tunnel.class)) {
358                     NodeId nodeId = getNodeIdFromNodeConnectorId(nc.getId());
359                     IfL3tunnel l3Tunnel = interf.getAugmentation(IfL3tunnel.class);
360                     this.dbDpnEndpoints.put(nodeId, l3Tunnel.getLocalIp().getIpv4Address().getValue());
361                 }
362             }
363         }
364     }
365
366     private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
367             InstanceIdentifier<T> path) {
368
369         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
370
371         Optional<T> result = Optional.absent();
372         try {
373             result = tx.read(datastoreType, path).get();
374         } catch (Exception e) {
375             throw new RuntimeException(e);
376         }
377
378         return result;
379     }
380
381     private InstanceIdentifier<Interface> getWildCardPath() {
382         return InstanceIdentifier.create(Interfaces.class).child(Interface.class);
383     }
384
385     @Override
386     protected void remove(InstanceIdentifier<Interface> identifier, Interface del) {
387         LOG.trace("remove - key: " + identifier + ", value=" + del );
388         delInterface(identifier, del);
389     }
390
391     @Override
392     protected void update(InstanceIdentifier<Interface> identifier, Interface original, Interface update) {
393         LOG.trace("update - key: " + identifier + ", original=" + original + ", update=" + update );
394         updateInterface(identifier, original, update);
395     }
396
397     private <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
398                     InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
399     WriteTransaction tx = broker.newWriteOnlyTransaction();
400     tx.put(datastoreType, path, data, true);
401     Futures.addCallback(tx.submit(), callback);
402     }
403
404     private <T extends DataObject> void asyncUpdate(LogicalDatastoreType datastoreType,
405                     InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
406     WriteTransaction tx = broker.newWriteOnlyTransaction();
407     tx.merge(datastoreType, path, data, true);
408     Futures.addCallback(tx.submit(), callback);
409     }
410
411     private <T extends DataObject> void asyncRemove(LogicalDatastoreType datastoreType,
412                     InstanceIdentifier<T> path, FutureCallback<Void> callback) {
413     WriteTransaction tx = broker.newWriteOnlyTransaction();
414     tx.delete(datastoreType, path);
415     Futures.addCallback(tx.submit(), callback);
416     }
417
418     void processPortAdd(NodeConnector port) {
419         NodeConnectorId portId = port.getId();
420         FlowCapableNodeConnector ofPort = port.getAugmentation(FlowCapableNodeConnector.class);
421         LOG.debug("PortAdd: PortId { "+portId.getValue()+"} PortName {"+ofPort.getName()+"}");
422         String ifName = this.mapNcToInterfaceName.get(portId);
423         setInterfaceOperStatus(ifName, OperStatus.Up);
424     }
425
426     void processPortUpdate(NodeConnector oldPort, NodeConnector update) {
427         //TODO: Currently nothing to do here.
428         LOG.trace("ifMap: {}, dpnMap: {}", mapNcToInterfaceName, dbDpnEndpoints);
429     }
430
431     void processPortDelete(NodeConnector port) {
432         NodeConnectorId portId = port.getId();
433         FlowCapableNodeConnector ofPort = port.getAugmentation(FlowCapableNodeConnector.class);
434         LOG.debug("PortDelete: PortId { "+portId.getValue()+"} PortName {"+ofPort.getName()+"}");
435         String ifName = this.mapNcToInterfaceName.get(portId);
436         setInterfaceOperStatus(ifName, OperStatus.Down);
437     }
438
439     private void setInterfaceOperStatus(String ifName, OperStatus opStatus) {
440         if (ifName != null) {
441             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id =
442                             buildStateInterfaceId(ifName);
443             Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> stateIf =
444                             read(LogicalDatastoreType.OPERATIONAL, id);
445             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface stateIface;
446             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder =
447                             new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder();
448             if (stateIf.isPresent()) {
449                 stateIface = ifaceBuilder.setOperStatus(opStatus).build();
450                 LOG.trace("Setting OperStatus for {} to {} in OPERATIONAL DS", ifName, opStatus);
451                 asyncUpdate(LogicalDatastoreType.OPERATIONAL, id, stateIface, DEFAULT_CALLBACK);
452             }
453         }
454     }
455
456     private Interface getInterfaceByIfName(String ifName) {
457         InstanceIdentifier<Interface> id = buildId(ifName);
458         Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
459         if(port.isPresent()) {
460             return port.get();
461         }
462         return null;
463     }
464
465     Long getPortForInterface(String ifName) {
466         Interface iface = getInterfaceByIfName(ifName);
467         return getPortNumForInterface(iface);
468     }
469
470     long getDpnForInterface(String ifName) {
471         Interface iface = getInterfaceByIfName(ifName);
472         try {
473             NodeConnector port = getNodeConnectorFromDataStore(iface);
474             //TODO: This should be an MDSAL Util method
475             return Long.parseLong(getDpnFromNodeConnectorId(port.getId()));
476         } catch (NullPointerException e) {
477             LOG.error("OFPort for Interface {} not found", ifName);
478         }
479         return 0L;
480     }
481
482     String getEndpointIpForDpn(long dpnId) {
483         //TODO: This should be MDSAL Util function
484         NodeId dpnNodeId = buildDpnNodeId(dpnId);
485         return dbDpnEndpoints.get(dpnNodeId);
486     }
487
488     List<MatchInfo> getInterfaceIngressRule(String ifName){
489         Interface iface = getInterfaceByIfName(ifName);
490         List<MatchInfo> matches = new ArrayList<MatchInfo>();
491         Class<? extends InterfaceType> ifType = iface.getType();
492         long dpn = this.getDpnForInterface(ifName);
493         long portNo = this.getPortNumForInterface(iface).longValue();
494         matches.add(new MatchInfo(MatchFieldType.in_port, new long[] {dpn, portNo}));
495         if(ifType.isInstance(L2vlan.class)) {
496             IfL2vlan vlanIface = iface.getAugmentation(IfL2vlan.class);
497             matches.add(new MatchInfo(MatchFieldType.vlan_vid, 
498                             new long[] {vlanIface.getVlanId().longValue()}));
499             LOG.trace("L2Vlan: {}",vlanIface);
500         } else if (ifType.isInstance(L3tunnel.class)) {
501             //TODO: Handle different tunnel types
502             IfL3tunnel ifL3Tunnel = iface.getAugmentation(IfL3tunnel.class);
503             Class<? extends TunnelTypeBase> tunnType = ifL3Tunnel.getTunnelType();
504             LOG.trace("L3Tunnel: {}",ifL3Tunnel);
505         } else if (ifType.isInstance(StackedVlan.class)) {
506             IfStackedVlan ifStackedVlan = iface.getAugmentation(IfStackedVlan.class);
507             LOG.trace("StackedVlan: {}",ifStackedVlan);
508         } else if (ifType.isInstance(Mpls.class)) {
509             IfMpls ifMpls = iface.getAugmentation(IfMpls.class);
510             LOG.trace("Mpls: {}",ifMpls);
511         }
512         return matches;
513     }
514
515     public List<InstructionInfo> getInterfaceEgressActions(String ifName) {
516         Interface iface = getInterfaceByIfName(ifName);
517
518         List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
519         List<ActionInfo> actionInfos = new ArrayList<ActionInfo>();
520         Class<? extends Class> ifType = iface.getType().getClass();
521         long dpn = this.getDpnForInterface(ifName);
522         long portNo = this.getPortNumForInterface(iface).longValue();
523         instructions.add(new InstructionInfo(InstructionType.apply_actions,
524                         actionInfos));
525         /*TODO: Refer getInterfaceIngressRules on how to get interface details
526                 for different types
527         */
528
529
530         return instructions;
531     }
532  
533     private String getDpnFromNodeConnectorId(NodeConnectorId portId) {
534         /*
535          * NodeConnectorId is of form 'openflow:dpnid:portnum'
536          */
537         String[] split = portId.getValue().split(":");
538         return split[1];
539     }
540
541     private NodeId buildDpnNodeId(long dpnId) {
542         // TODO Auto-generated method stub
543         return new NodeId("openflow:" + dpnId);
544     }
545
546     private NodeId getNodeIdFromNodeConnectorId(NodeConnectorId ncId) {
547         return new NodeId(ncId.getValue().substring(0,ncId.getValue().lastIndexOf(":")));
548     }
549
550     private Long getPortNumForInterface(Interface iface) {
551         try {
552             NodeConnector port = getNodeConnectorFromDataStore(iface);
553             FlowCapableNodeConnector ofPort = port.getAugmentation(FlowCapableNodeConnector.class);
554             return ofPort.getPortNumber().getUint32();
555         } catch (Exception e) {
556             LOG.error("OFPort for Interface {} not found", iface.getName());
557         }
558         return null;
559     }
560
561 }