Merge "ArpHandler to ignore ip packet sent to default GW"
[controller.git] / opendaylight / md-sal / compatibility / sal-compatibility / src / main / java / org / opendaylight / controller / sal / compatibility / InventoryAndReadAdapter.xtend
1 package org.opendaylight.controller.sal.compatibility
2
3 import java.util.ArrayList
4 import java.util.Collections
5 import java.util.List
6 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
7 import org.opendaylight.controller.sal.binding.api.data.DataProviderService
8 import org.opendaylight.controller.sal.core.Edge
9 import org.opendaylight.controller.sal.core.Node
10 import org.opendaylight.controller.sal.core.NodeTable
11 import org.opendaylight.controller.sal.core.UpdateType
12 import org.opendaylight.controller.sal.flowprogrammer.Flow
13 import org.opendaylight.controller.sal.inventory.IPluginInInventoryService
14 import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService
15 import org.opendaylight.controller.sal.reader.FlowOnNode
16 import org.opendaylight.controller.sal.reader.IPluginInReadService
17 import org.opendaylight.controller.sal.reader.IPluginOutReadService
18 import org.opendaylight.controller.sal.reader.NodeConnectorStatistics
19 import org.opendaylight.controller.sal.reader.NodeDescription
20 import org.opendaylight.controller.sal.reader.NodeTableStatistics
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdate
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInputBuilder
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableInputBuilder
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsListener
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdate
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInputBuilder
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsListener
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatistics
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryService
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.Link
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatistics
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsInputBuilder
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetNodeConnectorStatisticsInputBuilder
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsListener
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService
61 import org.opendaylight.yangtools.yang.binding.DataObject
62 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
63 import org.slf4j.LoggerFactory
64
65 import static extension org.opendaylight.controller.sal.common.util.Arguments.*
66 import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
67 import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
68 import java.util.concurrent.ConcurrentHashMap
69 import java.util.Map
70
71 class InventoryAndReadAdapter implements IPluginInReadService,
72                                                                                          IPluginInInventoryService,
73                                                                                          OpendaylightInventoryListener,
74                                                                                          OpendaylightFlowStatisticsListener,
75                                                                                          OpendaylightFlowTableStatisticsListener,
76                                                                                          OpendaylightPortStatisticsListener {
77
78     private static val LOG = LoggerFactory.getLogger(InventoryAndReadAdapter);
79
80         private static val OPENFLOWV10_TABLE_ID = new Integer(0).shortValue;
81     @Property
82     DataBrokerService dataService;
83
84     @Property
85     DataProviderService dataProviderService;
86
87     @Property
88     OpendaylightFlowStatisticsService flowStatisticsService;
89
90     @Property
91     OpendaylightPortStatisticsService nodeConnectorStatisticsService;
92     
93     @Property
94     OpendaylightFlowTableStatisticsService flowTableStatisticsService;
95
96     @Property
97     IPluginOutInventoryService inventoryPublisher;
98
99     @Property
100     FlowTopologyDiscoveryService topologyDiscovery;
101     
102     @Property
103     List<IPluginOutReadService> statisticsPublisher = new ArrayList<IPluginOutReadService>();
104         
105     def setReadPublisher(IPluginOutReadService listener) {
106         statisticsPublisher.add(listener);
107     }
108     
109     def unsetReadPublisher (IPluginOutReadService listener) {
110         if( listener != null)
111                 statisticsPublisher.remove(listener);
112     }
113
114     protected def startChange() {
115         return dataProviderService.beginTransaction;
116     }
117
118     override getTransmitRate(org.opendaylight.controller.sal.core.NodeConnector connector) {
119         val nodeConnector = readFlowCapableNodeConnector(connector.toNodeConnectorRef);
120         return nodeConnector.currentSpeed
121     }
122
123     override readAllFlow(Node node, boolean cached) {
124
125         val output = new ArrayList<FlowOnNode>();
126                 val tableRef = InstanceIdentifier.builder(Nodes)
127                                                                                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
128                                                         .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance();
129                 
130                 val it = this.startChange();
131                 
132                 val table= it.readConfigurationData(tableRef) as Table;
133                 
134                 if(table != null){
135                         LOG.info("Number of flows installed in table 0 of node {} : {}",node,table.flow.size);
136                         
137                         for(flow : table.flow){
138                                 
139                                 val adsalFlow = ToSalConversionsUtils.toFlow(flow);
140                                 val statsFromDataStore = flow.getAugmentation(FlowStatisticsData);
141                                 
142                                 if(statsFromDataStore != null){
143                                         val it = new FlowOnNode(adsalFlow);
144                                         byteCount =  statsFromDataStore.flowStatistics.byteCount.value.longValue;
145                                         packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue;
146                                         durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue;
147                                         durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue;
148                                         
149                                         output.add(it);
150                                 }
151                         }
152                 }
153         
154         //TODO (main): Shell we send request to the switch? It will make async request to the switch.
155         // Once plugin receive response, it will let adaptor know through onFlowStatisticsUpdate()
156         // If we assume that md-sal statistics manager will always be running, then its not required
157         // But if not, then sending request will collect the latest data for adaptor atleast.
158         val input = new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder;
159         input.setNode(node.toNodeRef);
160         flowStatisticsService.getAllFlowsStatisticsFromAllFlowTables(input.build)
161         
162         return output;
163     }
164
165     override readAllNodeConnector(Node node, boolean cached) {
166         
167         val ret = new ArrayList<NodeConnectorStatistics>();
168                 val nodeRef = InstanceIdentifier.builder(Nodes)
169                                                                         .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
170                                                                         .toInstance();
171                 
172                 val provider = this.startChange();
173                 
174                 val dsNode= provider.readConfigurationData(nodeRef) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
175                 
176                 if(dsNode != null){
177                         
178                         for (dsNodeConnector : dsNode.nodeConnector){
179                                 val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
180                                                                         .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
181                                                                         .child(NodeConnector, dsNodeConnector.key)
182                                                                         .toInstance();
183                                 
184                                 val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as NodeConnector;
185                                 
186                                 if(nodeConnectorFromDS != null){
187                                         val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics;
188                                         
189                                         ret.add(toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics,dsNode.id,dsNodeConnector.id));
190                                 }
191                         }
192                 }
193
194                 //TODO: Refer TODO (main)
195         val input = new GetAllNodeConnectorsStatisticsInputBuilder();
196         input.setNode(node.toNodeRef);
197         nodeConnectorStatisticsService.getAllNodeConnectorsStatistics(input.build());
198         return ret;
199     }
200
201     override readAllNodeTable(Node node, boolean cached) {
202         val ret = new ArrayList<NodeTableStatistics>();
203         
204                 val dsFlowCapableNode= readFlowCapableNode(node.toNodeRef)
205                 
206                 if(dsFlowCapableNode != null){
207                         
208                         for (table : dsFlowCapableNode.table){
209                                 
210                                 val tableStats = table.getAugmentation(FlowTableStatisticsData);
211                                 
212                                 if(tableStats != null){
213                                         ret.add(toNodeTableStatistics(tableStats.flowTableStatistics,table.id,node));
214                                 }
215                         }
216                 }
217
218                 //TODO: Refer TODO (main)
219         val input = new GetFlowTablesStatisticsInputBuilder();
220         input.setNode(node.toNodeRef);
221         flowTableStatisticsService.getFlowTablesStatistics(input.build);
222         return ret;
223     }
224
225     override readDescription(Node node, boolean cached) {
226         return toNodeDescription(node.toNodeRef);
227         }
228
229     override readFlow(Node node, Flow targetFlow, boolean cached) {
230                 var FlowOnNode ret= null;
231                 
232                 val tableRef = InstanceIdentifier.builder(Nodes)
233                                                                                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
234                                                         .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance();
235                 
236                 val it = this.startChange();
237                 
238                 val table= it.readConfigurationData(tableRef) as Table;
239                 
240                 if(table != null){
241                         LOG.info("Number of flows installed in table 0 of node {} : {}",node,table.flow.size);
242                         
243                         for(mdsalFlow : table.flow){
244                                 if(FromSalConversionsUtils.flowEquals(mdsalFlow, MDFlowMapping.toMDSalflow(targetFlow))){
245                                         val statsFromDataStore = mdsalFlow.getAugmentation(FlowStatisticsData);
246                                         
247                                         if(statsFromDataStore != null){
248                                                 LOG.debug("Found matching flow in the data store flow table ");
249                                                 val it = new FlowOnNode(targetFlow);
250                                                 byteCount =  statsFromDataStore.flowStatistics.byteCount.value.longValue;
251                                                 packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue;
252                                                 durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue;
253                                                 durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue;
254                                                 
255                                                 ret = it;
256                                         }
257                                 }                       
258                         }
259                 }
260         
261         //TODO: Refer TODO (main)
262         val input = new GetFlowStatisticsFromFlowTableInputBuilder;
263         input.setNode(node.toNodeRef);
264         input.fieldsFrom(MDFlowMapping.toMDSalflow(targetFlow));
265         flowStatisticsService.getFlowStatisticsFromFlowTable(input.build)
266         
267         return ret;
268         
269     }
270
271     override readNodeConnector(org.opendaylight.controller.sal.core.NodeConnector connector, boolean cached) {
272         var NodeConnectorStatistics  nodeConnectorStatistics = null;
273         
274                 val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
275                                                                         .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(connector.node))
276                                                                         .child(NodeConnector, InventoryMapping.toNodeConnectorKey(connector))
277                                                                         .toInstance();
278                 val provider = this.startChange();
279                                 
280                 val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as NodeConnector;
281                                 
282                 if(nodeConnectorFromDS != null){
283                         val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics;
284                         if(nodeConnectorStatsFromDs != null) {
285                                 nodeConnectorStatistics = toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics,
286                                                                                                                                                 InventoryMapping.toNodeKey(connector.node).id,
287                                                                                                                                                 InventoryMapping.toNodeConnectorKey(connector).id);
288                         }
289                 }
290
291                 //TODO: Refer TODO (main)
292         val input = new GetNodeConnectorStatisticsInputBuilder();
293         input.setNode(connector.node.toNodeRef);
294         input.setNodeConnectorId(InventoryMapping.toNodeConnectorKey(connector).id);
295         nodeConnectorStatisticsService.getNodeConnectorStatistics(input.build());
296         return nodeConnectorStatistics;
297     }
298
299     override readNodeTable(NodeTable nodeTable, boolean cached) {
300         var NodeTableStatistics nodeStats = null
301         
302         val tableRef = InstanceIdentifier.builder(Nodes)
303                                                                                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(nodeTable.node))
304                                                         .augmentation(FlowCapableNode).child(Table, new TableKey(nodeTable.ID as Short)).toInstance();
305                 
306                 val it = this.startChange();
307                 
308                 val table= it.readConfigurationData(tableRef) as Table;
309                 
310                 if(table != null){
311                         val tableStats = table.getAugmentation(FlowTableStatisticsData);
312                                 
313                         if(tableStats != null){
314                                 nodeStats =  toNodeTableStatistics(tableStats.flowTableStatistics,table.id,nodeTable.node);
315                         }
316                 }
317
318                 //TODO: Refer TODO (main)
319         val input = new GetFlowTablesStatisticsInputBuilder();
320         input.setNode(nodeTable.node.toNodeRef);
321         flowTableStatisticsService.getFlowTablesStatistics(input.build);
322         
323         return nodeStats;
324     }
325
326     override onNodeConnectorRemoved(NodeConnectorRemoved update) {
327         // NOOP
328     }
329
330     override onNodeRemoved(NodeRemoved notification) {
331         val properties = Collections.<org.opendaylight.controller.sal.core.Property>emptySet();
332
333         inventoryPublisher.updateNode(notification.nodeRef.toADNode, UpdateType.REMOVED, properties);
334     }
335
336     override onNodeConnectorUpdated(NodeConnectorUpdated update) {
337         var updateType = UpdateType.CHANGED;
338         if ( this._dataService.readOperationalData(update.nodeConnectorRef.value as InstanceIdentifier<? extends DataObject>) == null ){
339             updateType = UpdateType.ADDED;
340         }
341
342         var nodeConnector = update.nodeConnectorRef.toADNodeConnector
343
344         inventoryPublisher.updateNodeConnector(nodeConnector , updateType , update.toADNodeConnectorProperties);
345     }
346
347     override onNodeUpdated(NodeUpdated notification) {
348         val InstanceIdentifier<? extends DataObject> identifier = notification.nodeRef.value  as InstanceIdentifier<? extends DataObject>;
349
350         var updateType = UpdateType.CHANGED;
351         if ( this._dataService.readOperationalData(identifier) == null ){
352             updateType = UpdateType.ADDED;
353         }
354         inventoryPublisher.updateNode(notification.nodeRef.toADNode, updateType, notification.toADNodeProperties);
355         
356                 //Notify the listeners of IPluginOutReadService
357         
358         for (statsPublisher : statisticsPublisher){
359                         val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
360                         statsPublisher.descriptionStatisticsUpdated(nodeRef.toADNode,toNodeDescription(notification.nodeRef));
361                 }
362     }
363
364     override getNodeProps() {
365         val props = new ConcurrentHashMap<Node, Map<String, org.opendaylight.controller.sal.core.Property>>()
366         
367         val nodes = readAllMDNodes()
368         for (node : nodes.node ) {
369             val fcn = node.getAugmentation(FlowCapableNode)
370             if(fcn != null) {
371                 val perNodeProps = fcn.toADNodeProperties(node.id)
372                 val perNodePropMap = new ConcurrentHashMap<String, org.opendaylight.controller.sal.core.Property>
373                 if(perNodeProps != null ) {
374                     for(perNodeProp : perNodeProps) {
375                         perNodePropMap.put(perNodeProp.name,perNodeProp)
376                     }
377                 }
378                 props.put(new Node(MD_SAL_TYPE, node.id.toADNodeId),perNodePropMap)
379             }
380         }
381         return props;
382     }
383     
384     private def readAllMDNodes() {
385         val nodesRef = InstanceIdentifier.builder(Nodes)
386             .toInstance
387         val reader = TypeSafeDataReader.forReader(dataService)
388         return reader.readOperationalData(nodesRef)
389     }
390     
391     private def readAllMDNodeConnectors(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node node) {
392         val nodeRef = InstanceIdentifier.builder(Nodes)
393             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(node.id))
394             .toInstance
395         val reader = TypeSafeDataReader.forReader(dataService)
396         return reader.readOperationalData(nodeRef).nodeConnector
397     }
398
399     override getNodeConnectorProps(Boolean refresh) {
400         // Note, because the MD-SAL has a unified data store, we can ignore the Boolean refresh, as we have no secondary 
401         // data store to refresh from
402         val props = new ConcurrentHashMap<org.opendaylight.controller.sal.core.NodeConnector, Map<String, org.opendaylight.controller.sal.core.Property>>()
403         val nodes = readAllMDNodes()
404         for (node : nodes.node) {
405             val ncs = node.readAllMDNodeConnectors
406             if(ncs != null) {
407                 for( nc : ncs ) {
408                     val fcnc = nc.getAugmentation(FlowCapableNodeConnector)
409                     if(fcnc != null) {
410                         val ncps = fcnc.toADNodeConnectorProperties
411                         val ncpsm = new ConcurrentHashMap<String, org.opendaylight.controller.sal.core.Property>
412                         if(ncps != null) {
413                             for(p : ncps) {
414                                 ncpsm.put(p.name,p)
415                             }
416                         }  
417                         props.put(nc.id.toADNodeConnector(node.id),ncpsm)
418                     }
419                 }
420             }
421         }
422         return props
423     }
424
425     private def FlowCapableNode readFlowCapableNode(NodeRef ref) {
426         val dataObject = dataService.readOperationalData(ref.value as InstanceIdentifier<? extends DataObject>);
427         val node = dataObject.checkInstanceOf(
428             org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node);
429         return node.getAugmentation(FlowCapableNode);
430     }
431
432     private def FlowCapableNodeConnector readFlowCapableNodeConnector(NodeConnectorRef ref) {
433         val dataObject = dataService.readOperationalData(ref.value as InstanceIdentifier<? extends DataObject>);
434         val node = dataObject.checkInstanceOf(
435             NodeConnector);
436         return node.getAugmentation(FlowCapableNodeConnector);
437     }
438
439     private def toNodeConnectorStatistics(
440         org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.NodeConnectorStatistics nodeConnectorStatistics, NodeId nodeId, NodeConnectorId nodeConnectorId) {
441                 
442                         val it = new NodeConnectorStatistics();
443                         
444                         receivePacketCount = nodeConnectorStatistics.packets.received.longValue;
445                         transmitPacketCount = nodeConnectorStatistics.packets.transmitted.longValue;
446                         
447                         receiveByteCount = nodeConnectorStatistics.bytes.received.longValue;
448                         transmitByteCount = nodeConnectorStatistics.bytes.transmitted.longValue;
449                         
450                         receiveDropCount = nodeConnectorStatistics.receiveDrops.longValue;
451                         transmitDropCount = nodeConnectorStatistics.transmitDrops.longValue;
452                         
453                         receiveErrorCount = nodeConnectorStatistics.receiveErrors.longValue;
454                         transmitErrorCount = nodeConnectorStatistics.transmitErrors.longValue;
455                         
456                         receiveFrameErrorCount = nodeConnectorStatistics.receiveFrameError.longValue;
457                         receiveOverRunErrorCount = nodeConnectorStatistics.receiveOverRunError.longValue;
458                         receiveCRCErrorCount = nodeConnectorStatistics.receiveCrcError.longValue;
459                         collisionCount = nodeConnectorStatistics.collisionCount.longValue;
460                         
461                         val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
462                                                                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(nodeId))
463                                                                 .child(NodeConnector,new NodeConnectorKey(nodeConnectorId)).toInstance;
464                         
465                         nodeConnector = NodeMapping.toADNodeConnector(new NodeConnectorRef(nodeConnectorRef));
466                         
467                         return it;
468     }
469
470         private def toNodeTableStatistics(
471                 FlowTableStatistics tableStats,
472                 Short tableId,Node node){
473                 var it = new NodeTableStatistics();
474                 
475                 activeCount = tableStats.activeFlows.value.intValue;
476                 lookupCount = tableStats.packetsLookedUp.value.intValue;
477                 matchedCount = tableStats.packetsMatched.value.intValue;
478                 name = tableId.toString;
479                 nodeTable = new NodeTable(NodeMapping.MD_SAL_TYPE,tableId,node);
480                 return it;
481         }
482         
483         private def toNodeDescription(NodeRef nodeRef){
484                 val capableNode = readFlowCapableNode(nodeRef);
485
486         val it = new NodeDescription()
487         manufacturer = capableNode.manufacturer
488         serialNumber = capableNode.serialNumber
489         software = capableNode.software
490         description = capableNode.description
491         
492         return it;
493         }
494     
495     
496     def Edge toADEdge(Link link) {
497         new Edge(link.source.toADNodeConnector,link.destination.toADNodeConnector)
498     }
499         
500         /*
501          * OpendaylightFlowStatisticsListener interface implementation
502          */
503         override onAggregateFlowStatisticsUpdate(AggregateFlowStatisticsUpdate notification) {
504         //Ignoring this notification as there does not seem to be a way to bubble this up to AD-SAL
505         }
506         
507         override onFlowsStatisticsUpdate(FlowsStatisticsUpdate notification) {
508                 
509                 val adsalFlowsStatistics = new ArrayList<FlowOnNode>();
510                 
511                 for(flowStats : notification.flowAndStatisticsMapList){
512                         if(flowStats.tableId == 0)
513                                 adsalFlowsStatistics.add(toFlowOnNode(flowStats));
514                 }
515                 
516                 for (statsPublisher : statisticsPublisher){
517                         val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
518                         statsPublisher.nodeFlowStatisticsUpdated(nodeRef.toADNode,adsalFlowsStatistics);
519                 }
520                 
521         }
522         /*
523          * OpendaylightFlowTableStatisticsListener interface implementation
524          */     
525         override onFlowTableStatisticsUpdate(FlowTableStatisticsUpdate notification) {
526                 var adsalFlowTableStatistics = new ArrayList<NodeTableStatistics>();
527                 
528                 for(stats : notification.flowTableAndStatisticsMap){
529                         if (stats.tableId.value == 0){
530                                 val it = new NodeTableStatistics();
531                                 activeCount = stats.activeFlows.value.intValue;
532                                 lookupCount = stats.packetsLookedUp.value.longValue;
533                                 matchedCount = stats.packetsMatched.value.longValue;
534                                 
535                                 adsalFlowTableStatistics.add(it);
536                         }
537                 }
538                 for (statsPublisher : statisticsPublisher){
539                         val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
540                         statsPublisher.nodeTableStatisticsUpdated(nodeRef.toADNode,adsalFlowTableStatistics);
541                 }
542         }
543         
544         /*
545          * OpendaylightPortStatisticsUpdate interface implementation
546          */
547         override onNodeConnectorStatisticsUpdate(NodeConnectorStatisticsUpdate notification) {
548                 
549                 val adsalPortStatistics  = new ArrayList<NodeConnectorStatistics>();
550                 
551                 for(nodeConnectorStatistics : notification.nodeConnectorStatisticsAndPortNumberMap){
552                         adsalPortStatistics.add(toNodeConnectorStatistics(nodeConnectorStatistics,notification.id,nodeConnectorStatistics.nodeConnectorId));
553                 }
554                 
555                 for (statsPublisher : statisticsPublisher){
556                         val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
557                         statsPublisher.nodeConnectorStatisticsUpdated(nodeRef.toADNode,adsalPortStatistics);
558                 }
559                 
560         }
561         
562         private static def toFlowOnNode (FlowAndStatisticsMapList flowAndStatsMap){
563                 
564                 val it = new FlowOnNode(ToSalConversionsUtils.toFlow(flowAndStatsMap));
565                 
566                 byteCount = flowAndStatsMap.byteCount.value.longValue;
567                 packetCount = flowAndStatsMap.packetCount.value.longValue;
568                 durationSeconds = flowAndStatsMap.duration.second.value.intValue;
569                 durationNanoseconds = flowAndStatsMap.duration.nanosecond.value.intValue;
570                 
571                 return it;
572         }
573
574         override  getConfiguredNotConnectedNodes() {
575         return Collections.emptySet();
576         }
577 }