2 * Copyright (c) 2015 Cisco Systems, Inc. and others. 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
9 package org.opendaylight.openflowplugin.impl.statistics;
11 import static org.mockito.Mockito.verify;
12 import static org.mockito.Mockito.when;
14 import com.google.common.base.Optional;
15 import com.google.common.collect.Lists;
16 import com.google.common.util.concurrent.CheckedFuture;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import java.math.BigInteger;
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.concurrent.ExecutionException;
23 import java.util.concurrent.TimeUnit;
24 import java.util.concurrent.TimeoutException;
25 import org.junit.Assert;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 import org.mockito.ArgumentCaptor;
30 import org.mockito.InOrder;
31 import org.mockito.Matchers;
32 import org.mockito.Mock;
33 import org.mockito.Mockito;
34 import org.mockito.runners.MockitoJUnitRunner;
35 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
36 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
37 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
38 import org.opendaylight.openflowplugin.api.OFConstants;
39 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
40 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
41 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
42 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
43 import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
44 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
45 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
46 import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
47 import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
48 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
49 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.StatisticsGatherer;
50 import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
51 import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory;
52 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdateBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatistics;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatistics;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatistics;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModFlags;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupId;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupType;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterFlags;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterId;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.grouping.BucketsListBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.MultipartReplyBody;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCaseBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupCaseBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupDescCaseBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterCaseBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterConfigCaseBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCaseBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCaseBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableCaseBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.MultipartReplyFlowBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.multipart.reply.flow.FlowStatsBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.MultipartReplyGroupBuilder;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.multipart.reply.group.GroupStatsBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.multipart.reply.group.group.stats.BucketStats;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.multipart.reply.group.group.stats.BucketStatsBuilder;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc._case.MultipartReplyGroupDescBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc._case.multipart.reply.group.desc.GroupDescBuilder;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter._case.MultipartReplyMeterBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter._case.multipart.reply.meter.MeterStatsBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter._case.multipart.reply.meter.meter.stats.MeterBandStatsBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter.config._case.MultipartReplyMeterConfigBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter.config._case.multipart.reply.meter.config.MeterConfigBuilder;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter.config._case.multipart.reply.meter.config.meter.config.Bands;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStatsBuilder;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.multipart.reply.port.stats.PortStatsBuilder;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.MultipartReplyQueueBuilder;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.multipart.reply.queue.QueueStatsBuilder;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.MultipartReplyTableBuilder;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.multipart.reply.table.TableStatsBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatistics;
132 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
133 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
134 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
137 @RunWith(MockitoJUnitRunner.class)
138 public class StatisticsGatheringUtilsTest {
140 static final String DUMMY_NODE_ID_VALUE = "1";
141 static final NodeId DUMMY_NODE_ID = new NodeId(DUMMY_NODE_ID_VALUE);
143 private final KeyedInstanceIdentifier<Node, NodeKey> dummyNodePath = InstanceIdentifier.create(Nodes.class)
144 .child(Node.class, new NodeKey(DUMMY_NODE_ID));
146 private DeviceContext deviceContext;
148 private DeviceState deviceState;
150 private DeviceFlowRegistry deviceFlowRegistry;
152 private DeviceGroupRegistry deviceGroupRegistry;
154 private DeviceMeterRegistry deviceMeterRegistry;
156 private FlowDescriptor flowDescriptor;
158 private FlowId flowId;
160 private GetFeaturesOutput features;
162 private ReadOnlyTransaction readTx;
164 private ConnectionContext connectionAdapter;
166 private StatisticsGatherer<MultipartReply> statisticsService;
168 private DeviceInfo deviceInfo;
170 private MultipartWriterProvider provider;
173 public void setUp() throws Exception {
174 when(deviceContext.getDeviceState()).thenReturn(deviceState);
175 when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
176 when(deviceContext.getDeviceFlowRegistry()).thenReturn(deviceFlowRegistry);
177 when(deviceContext.getDeviceGroupRegistry()).thenReturn(deviceGroupRegistry);
178 when(deviceContext.getDeviceMeterRegistry()).thenReturn(deviceMeterRegistry);
179 when(deviceFlowRegistry.retrieveIdForFlow(Matchers.any(FlowRegistryKey.class))).thenReturn(flowDescriptor);
180 when(deviceContext.getReadTransaction()).thenReturn(readTx);
181 when(deviceContext.getReadTransaction()).thenReturn(readTx);
182 when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionAdapter);
183 when(connectionAdapter.getNodeId()).thenReturn(DUMMY_NODE_ID);
184 when(connectionAdapter.getFeatures()).thenReturn(features);
185 when(features.getDatapathId()).thenReturn(BigInteger.ONE);
186 when(features.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
187 when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
188 when(deviceInfo.getDatapathId()).thenReturn(BigInteger.ONE);
189 when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(dummyNodePath);
190 when(deviceInfo.getNodeId()).thenReturn(DUMMY_NODE_ID);
191 provider = MultipartWriterProviderFactory.createDefaultProvider(deviceContext);
195 public void testWriteFlowStatistics() throws Exception {
196 final ArgumentCaptor<LogicalDatastoreType> dataStoreType = ArgumentCaptor.forClass(LogicalDatastoreType.class);
197 final ArgumentCaptor<InstanceIdentifier> flowPath = ArgumentCaptor.forClass(InstanceIdentifier.class);
198 final ArgumentCaptor<Flow> flow = ArgumentCaptor.forClass(Flow.class);
200 provider.lookup(MultipartType.OFPMPFLOW).get().write(prepareFlowStatisticsData().iterator().next(), false);
202 Mockito.verify(deviceContext).writeToTransaction(
203 dataStoreType.capture(), flowPath.capture(), flow.capture());
204 Assert.assertEquals(LogicalDatastoreType.OPERATIONAL, dataStoreType.getValue());
205 final InstanceIdentifier<FlowCapableNode> flowCapableNodePath = flowPath.getValue();
206 Assert.assertEquals(DUMMY_NODE_ID, flowCapableNodePath.firstKeyOf(Node.class, NodeKey.class).getId());
207 Assert.assertEquals(42, flow.getValue().getTableId().intValue());
210 private Iterable<FlowsStatisticsUpdate> prepareFlowStatisticsData() {
211 final FlowAndStatisticsMapListBuilder flowAndStatsMapListBld = new FlowAndStatisticsMapListBuilder();
212 flowAndStatsMapListBld.setTableId((short) 42);
213 flowAndStatsMapListBld.setMatch(new MatchBuilder().build());
215 final FlowsStatisticsUpdateBuilder flowStatsUpdateBld1 = new FlowsStatisticsUpdateBuilder();
216 flowStatsUpdateBld1.setFlowAndStatisticsMapList(Lists.newArrayList(flowAndStatsMapListBld.build()));
218 return Lists.newArrayList(flowStatsUpdateBld1.build());
223 public void testGatherStatistics_group() throws Exception {
224 final MultipartType type = MultipartType.OFPMPGROUP;
225 final long groupIdValue = 19L;
227 final GroupStatsBuilder groupStatsBld = new GroupStatsBuilder()
228 .setBucketStats(Lists.newArrayList(createBucketStat(21L, 42L)))
229 .setByteCount(BigInteger.valueOf(84L))
230 .setPacketCount(BigInteger.valueOf(63L))
232 .setDurationNsec(12L)
234 .setGroupId(new GroupId(groupIdValue));
235 final MultipartReplyGroupBuilder mpReplyGroupBld = new MultipartReplyGroupBuilder();
236 mpReplyGroupBld.setGroupStats(Lists.newArrayList(groupStatsBld.build()));
237 final MultipartReplyGroupCaseBuilder mpReplyGroupCaseBld = new MultipartReplyGroupCaseBuilder();
238 mpReplyGroupCaseBld.setMultipartReplyGroup(mpReplyGroupBld.build());
240 final MultipartReply groupStatsUpdated = assembleMPReplyMessage(type, mpReplyGroupCaseBld.build());
241 final List<MultipartReply> statsData = Collections.singletonList(groupStatsUpdated);
243 fireAndCheck(type, statsData);
245 final InstanceIdentifier<GroupStatistics> groupPath = dummyNodePath.augmentation(FlowCapableNode.class)
246 .child(Group.class, new GroupKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId(groupIdValue)))
247 .augmentation(NodeGroupStatistics.class)
248 .child(GroupStatistics.class);
249 verify(deviceContext).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
250 Matchers.eq(groupPath), Matchers.any(GroupStatistics.class));
254 public void testGatherStatistics_groupDesc() throws Exception {
255 final MultipartType type = MultipartType.OFPMPGROUPDESC;
256 final long groupIdValue = 27L;
258 final BucketsListBuilder bucketsListBld = new BucketsListBuilder()
259 .setWatchPort(new PortNumber(5L));
260 final GroupDescBuilder groupStatsBld = new GroupDescBuilder()
261 .setBucketsList(Lists.newArrayList(bucketsListBld.build()))
262 .setGroupId(new GroupId(groupIdValue))
263 .setType(GroupType.OFPGTALL);
264 final MultipartReplyGroupDescBuilder mpReplyGroupBld = new MultipartReplyGroupDescBuilder();
265 mpReplyGroupBld.setGroupDesc(Lists.newArrayList(groupStatsBld.build()));
266 final MultipartReplyGroupDescCaseBuilder mpReplyGroupCaseBld = new MultipartReplyGroupDescCaseBuilder();
267 mpReplyGroupCaseBld.setMultipartReplyGroupDesc(mpReplyGroupBld.build());
269 final MultipartReply groupStatsUpdated = assembleMPReplyMessage(type, mpReplyGroupCaseBld.build());
270 final List<MultipartReply> statsData = Collections.singletonList(groupStatsUpdated);
272 fireAndCheck(type, statsData);
274 final org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId storedGroupId = new org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId(groupIdValue);
275 final KeyedInstanceIdentifier<Group, GroupKey> groupPath = dummyNodePath.augmentation(FlowCapableNode.class).child(Group.class, new GroupKey(storedGroupId));
277 verify(deviceContext, Mockito.never()).addDeleteToTxChain(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.<InstanceIdentifier<?>> any());
278 verify(deviceGroupRegistry).removeMarked();
279 verify(deviceGroupRegistry).store(storedGroupId);
280 verify(deviceContext).writeToTransaction(
281 Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(groupPath), Matchers.any(Group.class));
285 public void testGatherStatistics_meter() throws Exception {
286 final MultipartType type = MultipartType.OFPMPMETER;
287 final long meterIdValue = 19L;
289 final MeterBandStatsBuilder meterBandStatsBld = new MeterBandStatsBuilder()
290 .setByteBandCount(BigInteger.valueOf(91L))
291 .setPacketBandCount(BigInteger.valueOf(92L));
292 final MeterStatsBuilder meterStatsBld = new MeterStatsBuilder()
293 .setMeterId(new MeterId(meterIdValue))
294 .setByteInCount(BigInteger.valueOf(111L))
295 .setDurationSec(112L)
296 .setDurationNsec(113L)
298 .setPacketInCount(BigInteger.valueOf(115L))
299 .setMeterBandStats(Lists.newArrayList(meterBandStatsBld.build()));
300 final MultipartReplyMeterBuilder mpReplyMeterBld = new MultipartReplyMeterBuilder();
301 mpReplyMeterBld.setMeterStats(Lists.newArrayList(meterStatsBld.build()));
302 final MultipartReplyMeterCaseBuilder mpReplyMeterCaseBld = new MultipartReplyMeterCaseBuilder();
303 mpReplyMeterCaseBld.setMultipartReplyMeter(mpReplyMeterBld.build());
305 final MultipartReply meterStatsUpdated = assembleMPReplyMessage(type, mpReplyMeterCaseBld.build());
306 final List<MultipartReply> statsData = Collections.singletonList(meterStatsUpdated);
308 fireAndCheck(type, statsData);
310 final InstanceIdentifier<MeterStatistics> meterPath = dummyNodePath.augmentation(FlowCapableNode.class)
311 .child(Meter.class, new MeterKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId(meterIdValue)))
312 .augmentation(NodeMeterStatistics.class)
313 .child(MeterStatistics.class);
314 verify(deviceContext).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
315 Matchers.eq(meterPath), Matchers.any(MeterStatistics.class));
319 public void testGatherStatistics_nodeConnector() throws Exception {
320 final MultipartType type = MultipartType.OFPMPPORTSTATS;
322 final PortStatsBuilder portStatsBld = new PortStatsBuilder()
324 final MultipartReplyPortStatsBuilder mpReplyMeterBld = new MultipartReplyPortStatsBuilder();
325 mpReplyMeterBld.setPortStats(Lists.newArrayList(portStatsBld.build()));
326 final MultipartReplyPortStatsCaseBuilder mpReplyMeterCaseBld = new MultipartReplyPortStatsCaseBuilder();
327 mpReplyMeterCaseBld.setMultipartReplyPortStats(mpReplyMeterBld.build());
329 final MultipartReply meterStatsUpdated = assembleMPReplyMessage(type, mpReplyMeterCaseBld.build());
330 final List<MultipartReply> statsData = Collections.singletonList(meterStatsUpdated);
332 fireAndCheck(type, statsData);
334 final InstanceIdentifier<FlowCapableNodeConnectorStatistics> portPath = dummyNodePath
335 .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:" + DUMMY_NODE_ID_VALUE + ":11")))
336 .augmentation(FlowCapableNodeConnectorStatisticsData.class)
337 .child(FlowCapableNodeConnectorStatistics.class);
338 verify(deviceContext).writeToTransaction(
339 Matchers.eq(LogicalDatastoreType.OPERATIONAL),
340 Matchers.eq(portPath),
341 Matchers.any(FlowCapableNodeConnectorStatistics.class));
345 public void testGatherStatistics_table() throws Exception {
346 final MultipartType type = MultipartType.OFPMPTABLE;
348 final TableStatsBuilder tableStatsBld = new TableStatsBuilder()
350 .setLookupCount(BigInteger.valueOf(34L))
351 .setMatchedCount(BigInteger.valueOf(35L))
352 .setTableId((short) 0);
353 final MultipartReplyTableBuilder mpReplyTableBld = new MultipartReplyTableBuilder();
354 mpReplyTableBld.setTableStats(Lists.newArrayList(tableStatsBld.build()));
355 final MultipartReplyTableCaseBuilder mpReplyTableCaseBld = new MultipartReplyTableCaseBuilder();
356 mpReplyTableCaseBld.setMultipartReplyTable(mpReplyTableBld.build());
358 final MultipartReply meterStatsUpdated = assembleMPReplyMessage(type, mpReplyTableCaseBld.build());
359 final List<MultipartReply> statsData = Collections.singletonList(meterStatsUpdated);
361 fireAndCheck(type, statsData);
363 final InstanceIdentifier<FlowTableStatistics> tablePath = dummyNodePath
364 .augmentation(FlowCapableNode.class)
365 .child(Table.class, new TableKey((short) 0))
366 .augmentation(FlowTableStatisticsData.class)
367 .child(FlowTableStatistics.class);
368 verify(deviceContext).writeToTransaction(
369 Matchers.eq(LogicalDatastoreType.OPERATIONAL),
370 Matchers.eq(tablePath),
371 Matchers.any(FlowTableStatistics.class));
375 public void testGatherStatistics_queue() throws Exception {
376 final MultipartType type = MultipartType.OFPMPQUEUE;
378 final long queueIdValue = 4L;
379 final QueueStatsBuilder queueStatsBld = new QueueStatsBuilder()
381 .setTxBytes(BigInteger.valueOf(44L))
382 .setTxErrors(BigInteger.valueOf(45L))
383 .setTxPackets(BigInteger.valueOf(46L))
385 .setDurationNsec(48L)
386 .setQueueId(queueIdValue);
388 final MultipartReplyQueueBuilder mpReplyQueueBld = new MultipartReplyQueueBuilder();
389 mpReplyQueueBld.setQueueStats(Lists.newArrayList(queueStatsBld.build()));
390 final MultipartReplyQueueCaseBuilder mpReplyQueueCaseBld = new MultipartReplyQueueCaseBuilder();
391 mpReplyQueueCaseBld.setMultipartReplyQueue(mpReplyQueueBld.build());
393 final MultipartReply meterStatsUpdated = assembleMPReplyMessage(type, mpReplyQueueCaseBld.build());
394 final List<MultipartReply> statsData = Collections.singletonList(meterStatsUpdated);
396 fireAndCheck(type, statsData);
398 final KeyedInstanceIdentifier<Queue, QueueKey> queuePath = dummyNodePath
399 .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:" + DUMMY_NODE_ID_VALUE + ":11")))
400 .augmentation(FlowCapableNodeConnector.class)
401 .child(Queue.class, new QueueKey(new QueueId(queueIdValue)));
402 verify(deviceContext).writeToTransaction(
403 Matchers.eq(LogicalDatastoreType.OPERATIONAL),
404 Matchers.eq(queuePath),
405 Matchers.any(Queue.class));
409 public void testGatherStatistics_flow() throws Exception {
410 final short tableId = 0;
411 final MultipartType type = MultipartType.OFPMPFLOW;
413 final InstanceIdentifier<FlowCapableNode> nodePath = deviceInfo.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
414 final TableBuilder tableDataBld = new TableBuilder();
415 tableDataBld.setId(tableId);
416 final FlowCapableNodeBuilder flowNodeBuilder = new FlowCapableNodeBuilder();
417 flowNodeBuilder.setTable(Collections.singletonList(tableDataBld.build()));
418 final Optional<FlowCapableNode> flowNodeOpt = Optional.of(flowNodeBuilder.build());
419 final CheckedFuture<Optional<FlowCapableNode>, ReadFailedException> flowNodeFuture = Futures.immediateCheckedFuture(flowNodeOpt);
420 when(readTx.read(LogicalDatastoreType.OPERATIONAL, nodePath)).thenReturn(flowNodeFuture);
421 when(flowDescriptor.getFlowId()).thenReturn(flowId);
423 final org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.MatchBuilder matchBld =
424 new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.MatchBuilder()
425 .setMatchEntry(Collections.<MatchEntry>emptyList());
426 final FlowStatsBuilder flowStatsBld = new FlowStatsBuilder()
427 .setByteCount(BigInteger.valueOf(55L))
428 .setPacketCount(BigInteger.valueOf(56L))
430 .setDurationNsec(58L)
431 .setTableId((short) 0)
432 .setMatch(matchBld.build())
433 .setFlags(new FlowModFlags(true, false, false, false, true));
435 final MultipartReplyFlowBuilder mpReplyFlowBld = new MultipartReplyFlowBuilder();
436 mpReplyFlowBld.setFlowStats(Lists.newArrayList(flowStatsBld.build()));
437 final MultipartReplyFlowCaseBuilder mpReplyFlowCaseBld = new MultipartReplyFlowCaseBuilder();
438 mpReplyFlowCaseBld.setMultipartReplyFlow(mpReplyFlowBld.build());
440 final MultipartReply flowStatsUpdated = assembleMPReplyMessage(type, mpReplyFlowCaseBld.build());
441 final List<MultipartReply> statsData = Collections.singletonList(flowStatsUpdated);
442 fireAndCheck(type, statsData);
444 final FlowBuilder flowBld = new FlowBuilder()
445 .setTableId((short) 0)
446 .setMatch(new MatchBuilder().build());
447 final KeyedInstanceIdentifier<Table, TableKey> tablePath = dummyNodePath.augmentation(FlowCapableNode.class)
448 .child(Table.class, new TableKey((short) 0));
449 final KeyedInstanceIdentifier<Flow, FlowKey> flowPath = tablePath.child(Flow.class, new FlowKey(flowId));
451 verify(deviceContext, Mockito.never()).addDeleteToTxChain(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.<InstanceIdentifier<?>>any());
453 final InOrder inOrder = Mockito.inOrder(deviceContext);
454 inOrder.verify(deviceContext).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(tablePath), Matchers.any(Table.class));
458 public void testGatherStatistics_meterConfig() throws Exception {
459 final MultipartType type = MultipartType.OFPMPMETERCONFIG;
460 final Long meterIdValue = 55L;
462 final MeterConfigBuilder meterConfigBld = new MeterConfigBuilder()
463 .setMeterId(new MeterId(meterIdValue))
464 .setFlags(new MeterFlags(false, true, false, true))
465 .setBands(Collections.<Bands>emptyList());
467 final MultipartReplyMeterConfigBuilder mpReplyMeterConfigBld = new MultipartReplyMeterConfigBuilder();
468 mpReplyMeterConfigBld.setMeterConfig(Lists.newArrayList(meterConfigBld.build()));
469 final MultipartReplyMeterConfigCaseBuilder mpReplyMeterConfigCaseBld = new MultipartReplyMeterConfigCaseBuilder();
470 mpReplyMeterConfigCaseBld.setMultipartReplyMeterConfig(mpReplyMeterConfigBld.build());
472 final MultipartReply meterConfigUpdated = assembleMPReplyMessage(type, mpReplyMeterConfigCaseBld.build());
473 final List<MultipartReply> statsData = Collections.singletonList(meterConfigUpdated);
475 fireAndCheck(type, statsData);
477 final org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId meterId =
478 new org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId(meterIdValue);
479 final KeyedInstanceIdentifier<Meter, MeterKey> meterPath = dummyNodePath.augmentation(FlowCapableNode.class)
480 .child(Meter.class, new MeterKey(meterId));
481 verify(deviceContext, Mockito.never()).addDeleteToTxChain(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.<InstanceIdentifier<?>>any());
482 verify(deviceMeterRegistry).store(meterId);
483 verify(deviceContext).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(meterPath), Matchers.any(Meter.class));
486 private void fireAndCheck(final MultipartType type, final List<MultipartReply> statsData) throws InterruptedException, ExecutionException, TimeoutException {
487 when(statisticsService.getStatisticsOfType(Matchers.any(EventIdentifier.class), Matchers.eq(type)))
488 .thenReturn(Futures.immediateFuture(RpcResultBuilder.success(statsData).build()));
490 final ListenableFuture<Boolean> gatherStatisticsResult = StatisticsGatheringUtils.gatherStatistics(
497 ConvertorManagerFactory.createDefaultManager(),
500 Assert.assertTrue(gatherStatisticsResult.get(1, TimeUnit.SECONDS));
501 verify(deviceContext).submitTransaction();
504 private static MultipartReplyMessage assembleMPReplyMessage(final MultipartType type, final MultipartReplyBody mpReplyGroupCaseBld) {
505 return new MultipartReplyMessageBuilder()
506 .setMultipartReplyBody(mpReplyGroupCaseBld)
508 .setFlags(new MultipartRequestFlags(false))
513 private static BucketStats createBucketStat(final long byteCount, final long packetCount) {
514 return new BucketStatsBuilder().setByteCount(BigInteger.valueOf(byteCount)).setPacketCount(BigInteger.valueOf(packetCount)).build();
518 public void testDeleteAllKnownFlows() throws Exception {
519 final short tableId = 0;
520 final InstanceIdentifier<FlowCapableNode> nodePath = deviceInfo.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
521 final TableBuilder tableDataBld = new TableBuilder();
522 tableDataBld.setId(tableId);
523 final FlowCapableNodeBuilder flowNodeBuilder = new FlowCapableNodeBuilder();
524 flowNodeBuilder.setTable(Collections.singletonList(tableDataBld.build()));
525 final Optional<FlowCapableNode> flowNodeOpt = Optional.of(flowNodeBuilder.build());
526 final CheckedFuture<Optional<FlowCapableNode>, ReadFailedException> flowNodeFuture = Futures.immediateCheckedFuture(flowNodeOpt);
527 when(readTx.read(LogicalDatastoreType.OPERATIONAL, nodePath)).thenReturn(flowNodeFuture);
528 final KeyedInstanceIdentifier<Table, TableKey> tablePath = deviceInfo.getNodeInstanceIdentifier()
529 .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId));
531 StatisticsGatheringUtils.deleteAllKnownFlows(deviceContext, deviceInfo.getNodeInstanceIdentifier()
532 .augmentation(FlowCapableNode.class), false);
534 verify(deviceContext).writeToTransaction(
535 LogicalDatastoreType.OPERATIONAL,
537 tableDataBld.setFlow(Collections.<Flow>emptyList()).build());