2 * Copyright (c) 2017 HPE, 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
8 package org.opendaylight.netvirt.statistics;
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.UUID;
14 import java.util.concurrent.CompletableFuture;
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.Future;
17 import java.util.concurrent.TimeUnit;
18 import java.util.concurrent.TimeoutException;
19 import javax.annotation.PostConstruct;
20 import javax.annotation.PreDestroy;
21 import javax.inject.Inject;
22 import javax.inject.Singleton;
23 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
24 import org.opendaylight.infrautils.counters.api.OccurenceCounter;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsInputBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsInputBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.OpendaylightDirectStatisticsService;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.config.rev170326.StatisticsConfig;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.opendaylight.yangtools.yang.common.RpcResult;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
48 public class CounterRetriever {
49 protected static final Logger LOG = LoggerFactory.getLogger(CounterRetriever.class);
50 private final OpendaylightDirectStatisticsService odlDirectStatsService;
51 private final long nodeResultTimeout;
52 private final Counters counters = new Counters();
55 public CounterRetriever(final RpcProviderRegistry rpcProviderRegistry,
56 final StatisticsConfig statisticsConfig, final OpendaylightDirectStatisticsService odlDirectStatsService) {
57 this.odlDirectStatsService = odlDirectStatsService;
58 this.nodeResultTimeout = statisticsConfig.getNodeCounterResultTimeout();
62 public void destroy() {
63 LOG.info("{} close", getClass().getSimpleName());
68 LOG.info("{} start", getClass().getSimpleName());
71 public CounterResultDataStructure getNodeConnectorCountersDirect(NodeId nodeId, NodeConnectorId nodeConnectorId) {
72 GetNodeConnectorStatisticsInput gncsi = getNodeConnectorStatisticsInputBuilder(nodeId, nodeConnectorId);
74 Future<RpcResult<GetNodeConnectorStatisticsOutput>> rpcResultFuture =
75 odlDirectStatsService.getNodeConnectorStatistics(gncsi);
76 RpcResult<GetNodeConnectorStatisticsOutput> rpcResult = null;
78 rpcResult = rpcResultFuture.get();
79 } catch (InterruptedException | ExecutionException e) {
80 counters.failedGettingNodeConnectorCounters.inc();
81 LOG.warn("Unable to retrieve node connector counters for port {}", nodeConnectorId);
85 if (rpcResult != null && rpcResult.isSuccessful() && rpcResult.getResult() != null) {
86 GetNodeConnectorStatisticsOutput nodeConnectorStatsOutput = rpcResult.getResult();
87 return createNodeConnectorResultMapDirect(nodeConnectorStatsOutput, nodeConnectorId);
89 counters.failedGettingRpcResultForNodeConnectorCounters.inc();
90 LOG.warn("Unable to retrieve node connector counters for port {}", nodeConnectorId);
95 public CounterResultDataStructure getNodeCountersDirect(Node node) {
96 List<CounterResultDataStructure> countersResults = new ArrayList<>();
97 List<CompletableFuture<NodeConnectorStatisticsSupplierOutput>> futureList = new ArrayList<>();
98 for (NodeConnector nodeConnector : node.getNodeConnector()) {
99 GetNodeConnectorStatisticsInput gncsi =
100 getNodeConnectorStatisticsInputBuilder(node.getId(), nodeConnector.getId());
101 futureList.add(CompletableFuture.supplyAsync(
102 new NodeConnectorStatisticsSupplier(odlDirectStatsService, gncsi, nodeConnector.getId())));
105 CompletableFuture<Void> allOf = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0]));
106 allOf.get(nodeResultTimeout, TimeUnit.SECONDS);
107 for (int i = 0; i < futureList.size(); i++) {
108 CompletableFuture<NodeConnectorStatisticsSupplierOutput> completableCurrentResult = futureList.get(i);
109 if (completableCurrentResult == null) {
110 LOG.warn("Unable to retrieve node counters");
111 counters.failedGettingNodeCounters.inc();
114 RpcResult<GetNodeConnectorStatisticsOutput> currentResult =
115 completableCurrentResult.get().getNodeConnectorStatisticsOutput();
116 if (currentResult != null && currentResult.isSuccessful() && currentResult.getResult() != null) {
117 GetNodeConnectorStatisticsOutput nodeConnectorStatsOutput = currentResult.getResult();
118 countersResults.add(createNodeConnectorResultMapDirect(nodeConnectorStatsOutput,
119 completableCurrentResult.get().getNodeConnectrId()));
121 counters.failedGettingNodeCounters.inc();
122 LOG.warn("Unable to retrieve node counters");
126 } catch (InterruptedException | ExecutionException | TimeoutException e) {
127 counters.failedGettingNodeCounters.inc();
128 LOG.warn("Unable to retrieve node counters");
132 return mergeCountersResults(countersResults);
135 private CounterResultDataStructure mergeCountersResults(List<CounterResultDataStructure> countersResults) {
136 CounterResultDataStructure crds = new CounterResultDataStructure();
137 for (CounterResultDataStructure currentCrds : countersResults) {
138 for (String resultId : currentCrds.getResults().keySet()) {
139 crds.addCounterResult(resultId, currentCrds.getResults().get(resultId));
145 private GetNodeConnectorStatisticsInput getNodeConnectorStatisticsInputBuilder(NodeId nodeId,
146 NodeConnectorId nodeConnectorId) {
147 NodeRef nodeRef = new NodeRef(
148 InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(nodeId)).toInstance());
149 GetNodeConnectorStatisticsInputBuilder nodeConnectorBuilder =
150 new GetNodeConnectorStatisticsInputBuilder().setNode(nodeRef).setNodeConnectorId(nodeConnectorId);
151 GetNodeConnectorStatisticsInput gncsi = nodeConnectorBuilder.build();
155 private CounterResultDataStructure createNodeConnectorResultMapDirect(
156 GetNodeConnectorStatisticsOutput nodeConnectorStatsOutput, NodeConnectorId nodeConnectorId) {
157 List<NodeConnectorStatisticsAndPortNumberMap> nodeConnectorUpdates =
158 nodeConnectorStatsOutput.getNodeConnectorStatisticsAndPortNumberMap();
159 if (nodeConnectorUpdates == null || nodeConnectorUpdates.isEmpty()) {
160 counters.failedGettingResultMapForNodeConnectorCounters.inc();
161 LOG.warn("Unable to retrieve statistics info for node connector");
165 CounterResultDataStructure crds = new CounterResultDataStructure();
166 for (NodeConnectorStatisticsAndPortNumberMap nodeConnectorUpdate : nodeConnectorUpdates) {
167 if (nodeConnectorUpdate.getNodeConnectorId() == null) {
170 String resultId = nodeConnectorId.getValue();
171 crds.addCounterResult(resultId);
172 if (nodeConnectorUpdate.getBytes() != null) {
173 crds.addCounterToGroup(resultId, CountersUtils.BYTES_GROUP_NAME,
174 CountersUtils.BYTES_RECEIVED_COUNTER_NAME, nodeConnectorUpdate.getBytes().getReceived());
175 crds.addCounterToGroup(resultId, CountersUtils.BYTES_GROUP_NAME,
176 CountersUtils.BYTES_TRANSMITTED_COUNTER_NAME, nodeConnectorUpdate.getBytes().getTransmitted());
178 if (nodeConnectorUpdate.getPackets() != null) {
179 crds.addCounterToGroup(resultId, CountersUtils.PACKETS_GROUP_NAME,
180 CountersUtils.PACKETS_RECEIVED_COUNTER_NAME, nodeConnectorUpdate.getPackets().getReceived());
181 crds.addCounterToGroup(resultId, CountersUtils.PACKETS_GROUP_NAME,
182 CountersUtils.PACKETS_TRANSMITTED_COUNTER_NAME,
183 nodeConnectorUpdate.getPackets().getTransmitted());
185 if (nodeConnectorUpdate.getDuration() != null) {
186 crds.addCounterToGroup(resultId, CountersUtils.DURATION_GROUP_NAME,
187 CountersUtils.DURATION_SECOND_COUNTER_NAME,
188 big(nodeConnectorUpdate.getDuration().getSecond().getValue()));
189 crds.addCounterToGroup(resultId, CountersUtils.DURATION_GROUP_NAME,
190 CountersUtils.DURATION_NANO_SECOND_COUNTER_NAME,
191 big(nodeConnectorUpdate.getDuration().getNanosecond().getValue()));
198 public CounterResultDataStructure getSwitchFlowCountersDirect(BigInteger dpId, Match match, short tableId) {
199 NodeRef nodeRef = new NodeRef(InstanceIdentifier.builder(Nodes.class)
200 .child(Node.class, new NodeKey(new NodeId(CountersUtils.getNodeId(dpId)))).toInstance());
201 GetFlowStatisticsInputBuilder gfsib = new GetFlowStatisticsInputBuilder();
202 gfsib.setNode(nodeRef);
203 gfsib.setMatch(match);
204 gfsib.setStoreStats(false);
206 Future<RpcResult<GetFlowStatisticsOutput>> rpcResultFuture =
207 odlDirectStatsService.getFlowStatistics(gfsib.build());
208 RpcResult<GetFlowStatisticsOutput> rpcResult = null;
210 rpcResult = rpcResultFuture.get();
211 } catch (InterruptedException | ExecutionException e) {
212 counters.failedGettingFlowCounters.inc();
213 LOG.warn("Unable to retrieve flow counters for match {}", match);
217 if (rpcResult != null && rpcResult.isSuccessful() && rpcResult.getResult() != null) {
218 GetFlowStatisticsOutput flowStatsOutput = rpcResult.getResult();
219 return createSwitchFlowResultMapDirect(flowStatsOutput);
221 counters.failedGettingFlowCounters.inc();
222 LOG.warn("Unable to retrieve flow counters for match {}", match);
227 private CounterResultDataStructure createSwitchFlowResultMapDirect(GetFlowStatisticsOutput flowStatsOutput) {
228 List<FlowAndStatisticsMapList> flowUpdates = flowStatsOutput.getFlowAndStatisticsMapList();
229 if (flowUpdates == null || flowUpdates.isEmpty()) {
230 LOG.warn("Unable to retrieve flows statistics info");
234 CounterResultDataStructure crds = new CounterResultDataStructure();
235 for (FlowAndStatisticsMapList flowUpdate : flowUpdates) {
236 String resultId = flowUpdate.getTableId().toString() + CountersUtils.OF_DELIMITER + UUID.randomUUID();
237 crds.addCounterResult(resultId);
238 if (flowUpdate.getByteCount() != null) {
239 crds.addCounterToGroup(resultId, CountersUtils.BYTES_GROUP_NAME, CountersUtils.BYTE_COUNTER_NAME,
240 flowUpdate.getByteCount().getValue());
242 if (flowUpdate.getPacketCount() != null) {
243 crds.addCounterToGroup(resultId, CountersUtils.PACKETS_GROUP_NAME, CountersUtils.PACKET_COUNTER_NAME,
244 flowUpdate.getPacketCount().getValue());
246 if (flowUpdate.getDuration() != null) {
247 crds.addCounterToGroup(resultId, CountersUtils.DURATION_GROUP_NAME,
248 CountersUtils.DURATION_SECOND_COUNTER_NAME,
249 big(flowUpdate.getDuration().getSecond().getValue()));
250 crds.addCounterToGroup(resultId, CountersUtils.DURATION_GROUP_NAME,
251 CountersUtils.DURATION_NANO_SECOND_COUNTER_NAME,
252 big(flowUpdate.getDuration().getNanosecond().getValue()));
258 private BigInteger big(Long longValue) {
259 return BigInteger.valueOf(longValue);
262 private static class Counters {
263 OccurenceCounter failedGettingNodeConnectorCounters = new OccurenceCounter(
264 getClass().getEnclosingClass().getSimpleName(), "failed_getting_node_connector_counters", "");
266 OccurenceCounter failedGettingRpcResultForNodeConnectorCounters = new OccurenceCounter(
267 getClass().getEnclosingClass().getSimpleName(),
268 "failed_getting_rpc_result_for_node_connector_counters", "");
270 OccurenceCounter failedGettingNodeCounters = new OccurenceCounter(
271 getClass().getEnclosingClass().getSimpleName(), "failed_getting_node_counters", "");
273 OccurenceCounter failedGettingResultMapForNodeConnectorCounters = new OccurenceCounter(
274 getClass().getEnclosingClass().getSimpleName(),
275 "failed_getting_result_map_for_node_connector_counters", "");
277 OccurenceCounter failedGettingFlowCounters = new OccurenceCounter(
278 getClass().getEnclosingClass().getSimpleName(), "failed_getting_flow_counters", "");