2 * Copyright IBM Corporation, 2013. All rights reserved.
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
8 package org.opendaylight.controller.md.statistics.manager;
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;
30 final class FlowStatsTracker extends AbstractStatsTracker<FlowAndStatisticsMapList, FlowStatsEntry> {
31 private static final Logger logger = LoggerFactory.getLogger(FlowStatsTracker.class);
32 private int unaccountedFlowsCounter = 1;
34 FlowStatsTracker(InstanceIdentifier<Node> nodeIdentifier, DataProviderService dps, long lifetimeNanos) {
35 super(nodeIdentifier, dps, lifetimeNanos);
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);
49 protected FlowStatsEntry updateSingleStat(DataModificationTransaction trans, FlowAndStatisticsMapList map) {
50 short tableId = map.getTableId();
52 FlowBuilder flowBuilder = new FlowBuilder();
54 FlowStatisticsDataBuilder flowStatisticsData = new FlowStatisticsDataBuilder();
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);
78 Flow flowRule = flow.build();
80 FlowAndStatisticsMapListBuilder stats = new FlowAndStatisticsMapListBuilder();
81 stats.setByteCount(map.getByteCount());
82 stats.setPacketCount(map.getPacketCount());
83 stats.setDuration(map.getDuration());
85 GenericStatistics flowStats = stats.build();
87 //Augment the data to the flow node
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);
110 flowStatisticsData.setFlowStatistics(flowStatistics.build());
112 logger.debug("Flow : {}",flowRule.toString());
113 logger.debug("Statistics to augment : {}",flowStatistics.build().toString());
115 InstanceIdentifier<Table> tableRef = getNodeIdentifierBuilder()
116 .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
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);
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;
143 table = (Table)trans.readOperationalData(tableRef);
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;
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());
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;