Merge "Bug fixes for netconf southbound plugin."
[controller.git] / opendaylight / md-sal / statistics-manager / src / main / java / org / opendaylight / controller / md / statistics / manager / FlowStatsTracker.java
1 /*
2  * Copyright IBM Corporation, 2013.  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.controller.md.statistics.manager;
9
10 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
11 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsDataBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatisticsBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericStatistics;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 final class FlowStatsTracker extends AbstractStatsTracker<FlowAndStatisticsMapList, FlowStatsEntry> {
31     private static final Logger logger = LoggerFactory.getLogger(FlowStatsTracker.class);
32     private int unaccountedFlowsCounter = 1;
33
34     FlowStatsTracker(InstanceIdentifier<Node> nodeIdentifier, DataProviderService dps, long lifetimeNanos) {
35         super(nodeIdentifier, dps, lifetimeNanos);
36     }
37
38     @Override
39     protected void cleanupSingleStat(DataModificationTransaction trans, FlowStatsEntry item) {
40         InstanceIdentifier<?> flowRef = getNodeIdentifierBuilder()
41                             .augmentation(FlowCapableNode.class)
42                             .child(Table.class, new TableKey(item.getTableId()))
43                             .child(Flow.class,item.getFlow().getKey())
44                             .augmentation(FlowStatisticsData.class).toInstance();
45         trans.removeOperationalData(flowRef);
46     }
47
48     @Override
49     protected FlowStatsEntry updateSingleStat(DataModificationTransaction trans, FlowAndStatisticsMapList map) {
50         short tableId = map.getTableId();
51
52         FlowBuilder flowBuilder = new FlowBuilder();
53
54         FlowStatisticsDataBuilder flowStatisticsData = new FlowStatisticsDataBuilder();
55
56         FlowBuilder flow = new FlowBuilder();
57         flow.setContainerName(map.getContainerName());
58         flow.setBufferId(map.getBufferId());
59         flow.setCookie(map.getCookie());
60         flow.setCookieMask(map.getCookieMask());
61         flow.setFlags(map.getFlags());
62         flow.setFlowName(map.getFlowName());
63         flow.setHardTimeout(map.getHardTimeout());
64         if(map.getFlowId() != null)
65             flow.setId(new FlowId(map.getFlowId().getValue()));
66         flow.setIdleTimeout(map.getIdleTimeout());
67         flow.setInstallHw(map.isInstallHw());
68         flow.setInstructions(map.getInstructions());
69         if(map.getFlowId()!= null)
70             flow.setKey(new FlowKey(new FlowId(map.getKey().getFlowId().getValue())));
71         flow.setMatch(map.getMatch());
72         flow.setOutGroup(map.getOutGroup());
73         flow.setOutPort(map.getOutPort());
74         flow.setPriority(map.getPriority());
75         flow.setStrict(map.isStrict());
76         flow.setTableId(tableId);
77
78         Flow flowRule = flow.build();
79
80         FlowAndStatisticsMapListBuilder stats = new FlowAndStatisticsMapListBuilder();
81         stats.setByteCount(map.getByteCount());
82         stats.setPacketCount(map.getPacketCount());
83         stats.setDuration(map.getDuration());
84
85         GenericStatistics flowStats = stats.build();
86
87         //Augment the data to the flow node
88
89         FlowStatisticsBuilder flowStatistics = new FlowStatisticsBuilder();
90         flowStatistics.setByteCount(flowStats.getByteCount());
91         flowStatistics.setPacketCount(flowStats.getPacketCount());
92         flowStatistics.setDuration(flowStats.getDuration());
93         flowStatistics.setContainerName(map.getContainerName());
94         flowStatistics.setBufferId(map.getBufferId());
95         flowStatistics.setCookie(map.getCookie());
96         flowStatistics.setCookieMask(map.getCookieMask());
97         flowStatistics.setFlags(map.getFlags());
98         flowStatistics.setFlowName(map.getFlowName());
99         flowStatistics.setHardTimeout(map.getHardTimeout());
100         flowStatistics.setIdleTimeout(map.getIdleTimeout());
101         flowStatistics.setInstallHw(map.isInstallHw());
102         flowStatistics.setInstructions(map.getInstructions());
103         flowStatistics.setMatch(map.getMatch());
104         flowStatistics.setOutGroup(map.getOutGroup());
105         flowStatistics.setOutPort(map.getOutPort());
106         flowStatistics.setPriority(map.getPriority());
107         flowStatistics.setStrict(map.isStrict());
108         flowStatistics.setTableId(tableId);
109
110         flowStatisticsData.setFlowStatistics(flowStatistics.build());
111
112         logger.debug("Flow : {}",flowRule.toString());
113         logger.debug("Statistics to augment : {}",flowStatistics.build().toString());
114
115         InstanceIdentifier<Table> tableRef = getNodeIdentifierBuilder()
116                 .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
117
118         //TODO: Not a good way to do it, need to figure out better way.
119         //TODO: major issue in any alternate approach is that flow key is incrementally assigned
120         //to the flows stored in data store.
121         // Augment same statistics to all the matching masked flow
122         Table table= (Table)trans.readConfigurationData(tableRef);
123         if(table != null){
124             for(Flow existingFlow : table.getFlow()){
125                 logger.debug("Existing flow in data store : {}",existingFlow.toString());
126                 if(FlowComparator.flowEquals(flowRule,existingFlow)){
127                     InstanceIdentifier<Flow> flowRef = getNodeIdentifierBuilder()
128                             .augmentation(FlowCapableNode.class)
129                             .child(Table.class, new TableKey(tableId))
130                             .child(Flow.class,existingFlow.getKey()).toInstance();
131                     flowBuilder.setKey(existingFlow.getKey());
132                     flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
133                     logger.debug("Found matching flow in the datastore, augmenting statistics");
134                     // Update entry with timestamp of latest response
135                     flow.setKey(existingFlow.getKey());
136                     FlowStatsEntry flowStatsEntry = new FlowStatsEntry(tableId,flow.build());
137                     trans.putOperationalData(flowRef, flowBuilder.build());
138                     return flowStatsEntry;
139                 }
140             }
141         }
142
143         table = (Table)trans.readOperationalData(tableRef);
144         if(table != null){
145             for(Flow existingFlow : table.getFlow()){
146                 FlowStatisticsData augmentedflowStatisticsData = existingFlow.getAugmentation(FlowStatisticsData.class);
147                 if(augmentedflowStatisticsData != null){
148                     FlowBuilder existingOperationalFlow = new FlowBuilder();
149                     existingOperationalFlow.fieldsFrom(augmentedflowStatisticsData.getFlowStatistics());
150                     logger.debug("Existing unaccounted flow in operational data store : {}",existingFlow.toString());
151                     if(FlowComparator.flowEquals(flowRule,existingOperationalFlow.build())){
152                         InstanceIdentifier<Flow> flowRef = getNodeIdentifierBuilder()
153                                 .augmentation(FlowCapableNode.class)
154                                 .child(Table.class, new TableKey(tableId))
155                                 .child(Flow.class,existingFlow.getKey()).toInstance();
156                         flowBuilder.setKey(existingFlow.getKey());
157                         flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
158                         logger.debug("Found matching unaccounted flow in the operational datastore, augmenting statistics");
159                         // Update entry with timestamp of latest response
160                         flow.setKey(existingFlow.getKey());
161                         FlowStatsEntry flowStatsEntry = new FlowStatsEntry(tableId,flow.build());
162                         trans.putOperationalData(flowRef, flowBuilder.build());
163                         return flowStatsEntry;
164                     }
165                 }
166             }
167         }
168
169         String flowKey = "#UF$TABLE*"+Short.toString(tableId)+"*"+Integer.toString(this.unaccountedFlowsCounter);
170         this.unaccountedFlowsCounter++;
171         FlowKey newFlowKey = new FlowKey(new FlowId(flowKey));
172         InstanceIdentifier<Flow> flowRef = getNodeIdentifierBuilder().augmentation(FlowCapableNode.class)
173                     .child(Table.class, new TableKey(tableId))
174                     .child(Flow.class,newFlowKey).toInstance();
175         flowBuilder.setKey(newFlowKey);
176         flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
177         logger.debug("Flow {} is not present in config data store, augmenting statistics as an unaccounted flow",
178                     flowBuilder.build());
179
180         // Update entry with timestamp of latest response
181         flow.setKey(newFlowKey);
182         FlowStatsEntry flowStatsEntry = new FlowStatsEntry(tableId,flow.build());
183         trans.putOperationalData(flowRef, flowBuilder.build());
184         return flowStatsEntry;
185     }
186 }