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.infrautils.counters.api.OccurenceCounter;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsInputBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutput;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsInput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsInputBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.OpendaylightDirectStatisticsService;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.config.rev170326.StatisticsConfig;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.opendaylight.yangtools.yang.common.RpcResult;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
47 public class CounterRetriever {
48 protected static final Logger LOG = LoggerFactory.getLogger(CounterRetriever.class);
49 private final OpendaylightDirectStatisticsService odlDirectStatsService;
50 private final long nodeResultTimeout;
51 private final Counters counters = new Counters();
54 public CounterRetriever(final StatisticsConfig statisticsConfig,
55 final OpendaylightDirectStatisticsService odlDirectStatsService) {
56 this.odlDirectStatsService = odlDirectStatsService;
57 nodeResultTimeout = statisticsConfig.getNodeCounterResultTimeout();
61 public void destroy() {
62 LOG.info("{} close", getClass().getSimpleName());
67 LOG.info("{} start", getClass().getSimpleName());
70 public CounterResultDataStructure getNodeConnectorCountersDirect(NodeId nodeId, NodeConnectorId nodeConnectorId) {
71 GetNodeConnectorStatisticsInput gncsi = getNodeConnectorStatisticsInputBuilder(nodeId, nodeConnectorId);
73 Future<RpcResult<GetNodeConnectorStatisticsOutput>> rpcResultFuture =
74 odlDirectStatsService.getNodeConnectorStatistics(gncsi);
75 RpcResult<GetNodeConnectorStatisticsOutput> rpcResult = null;
77 rpcResult = rpcResultFuture.get();
78 } catch (InterruptedException | ExecutionException e) {
79 counters.failedGettingNodeConnectorCounters.inc();
80 LOG.warn("Unable to retrieve node connector counters for port {}", nodeConnectorId);
84 if (rpcResult != null && rpcResult.isSuccessful() && rpcResult.getResult() != null) {
85 GetNodeConnectorStatisticsOutput nodeConnectorStatsOutput = rpcResult.getResult();
86 return createNodeConnectorResultMapDirect(nodeConnectorStatsOutput, nodeConnectorId);
88 counters.failedGettingRpcResultForNodeConnectorCounters.inc();
89 LOG.warn("Unable to retrieve node connector counters for port {}", nodeConnectorId);
94 public CounterResultDataStructure getNodeCountersDirect(Node node) {
95 List<CounterResultDataStructure> countersResults = new ArrayList<>();
96 List<CompletableFuture<NodeConnectorStatisticsSupplierOutput>> futureList = new ArrayList<>();
97 for (NodeConnector nodeConnector : node.getNodeConnector()) {
98 GetNodeConnectorStatisticsInput gncsi =
99 getNodeConnectorStatisticsInputBuilder(node.getId(), nodeConnector.getId());
100 futureList.add(CompletableFuture.supplyAsync(
101 new NodeConnectorStatisticsSupplier(odlDirectStatsService, gncsi, nodeConnector.getId())));
104 CompletableFuture<Void> allOf = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0]));
105 allOf.get(nodeResultTimeout, TimeUnit.SECONDS);
106 for (int i = 0; i < futureList.size(); i++) {
107 CompletableFuture<NodeConnectorStatisticsSupplierOutput> completableCurrentResult = futureList.get(i);
108 if (completableCurrentResult == null) {
109 LOG.warn("Unable to retrieve node counters");
110 counters.failedGettingNodeCounters.inc();
113 RpcResult<GetNodeConnectorStatisticsOutput> currentResult =
114 completableCurrentResult.get().getNodeConnectorStatisticsOutput();
115 if (currentResult != null && currentResult.isSuccessful() && currentResult.getResult() != null) {
116 GetNodeConnectorStatisticsOutput nodeConnectorStatsOutput = currentResult.getResult();
117 countersResults.add(createNodeConnectorResultMapDirect(nodeConnectorStatsOutput,
118 completableCurrentResult.get().getNodeConnectrId()));
120 counters.failedGettingNodeCounters.inc();
121 LOG.warn("Unable to retrieve node counters");
125 } catch (InterruptedException | ExecutionException | TimeoutException e) {
126 counters.failedGettingNodeCounters.inc();
127 LOG.warn("Unable to retrieve node counters");
131 return mergeCountersResults(countersResults);
134 private CounterResultDataStructure mergeCountersResults(List<CounterResultDataStructure> countersResults) {
135 CounterResultDataStructure crds = new CounterResultDataStructure();
136 for (CounterResultDataStructure currentCrds : countersResults) {
137 for (String resultId : currentCrds.getResults().keySet()) {
138 crds.addCounterResult(resultId, currentCrds.getResults().get(resultId));
144 private GetNodeConnectorStatisticsInput getNodeConnectorStatisticsInputBuilder(NodeId nodeId,
145 NodeConnectorId nodeConnectorId) {
146 NodeRef nodeRef = new NodeRef(
147 InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(nodeId)).toInstance());
148 GetNodeConnectorStatisticsInputBuilder nodeConnectorBuilder =
149 new GetNodeConnectorStatisticsInputBuilder().setNode(nodeRef).setNodeConnectorId(nodeConnectorId);
150 GetNodeConnectorStatisticsInput gncsi = nodeConnectorBuilder.build();
154 private CounterResultDataStructure createNodeConnectorResultMapDirect(
155 GetNodeConnectorStatisticsOutput nodeConnectorStatsOutput, NodeConnectorId nodeConnectorId) {
156 List<NodeConnectorStatisticsAndPortNumberMap> nodeConnectorUpdates =
157 nodeConnectorStatsOutput.getNodeConnectorStatisticsAndPortNumberMap();
158 if (nodeConnectorUpdates == null || nodeConnectorUpdates.isEmpty()) {
159 counters.failedGettingResultMapForNodeConnectorCounters.inc();
160 LOG.warn("Unable to retrieve statistics info for node connector");
164 CounterResultDataStructure crds = new CounterResultDataStructure();
165 for (NodeConnectorStatisticsAndPortNumberMap nodeConnectorUpdate : nodeConnectorUpdates) {
166 if (nodeConnectorUpdate.getNodeConnectorId() == null) {
169 String resultId = nodeConnectorId.getValue();
170 crds.addCounterResult(resultId);
171 if (nodeConnectorUpdate.getBytes() != null) {
172 crds.addCounterToGroup(resultId, CountersUtils.BYTES_GROUP_NAME,
173 CountersUtils.BYTES_RECEIVED_COUNTER_NAME, nodeConnectorUpdate.getBytes().getReceived());
174 crds.addCounterToGroup(resultId, CountersUtils.BYTES_GROUP_NAME,
175 CountersUtils.BYTES_TRANSMITTED_COUNTER_NAME, nodeConnectorUpdate.getBytes().getTransmitted());
177 if (nodeConnectorUpdate.getPackets() != null) {
178 crds.addCounterToGroup(resultId, CountersUtils.PACKETS_GROUP_NAME,
179 CountersUtils.PACKETS_RECEIVED_COUNTER_NAME, nodeConnectorUpdate.getPackets().getReceived());
180 crds.addCounterToGroup(resultId, CountersUtils.PACKETS_GROUP_NAME,
181 CountersUtils.PACKETS_TRANSMITTED_COUNTER_NAME,
182 nodeConnectorUpdate.getPackets().getTransmitted());
184 if (nodeConnectorUpdate.getDuration() != null) {
185 crds.addCounterToGroup(resultId, CountersUtils.DURATION_GROUP_NAME,
186 CountersUtils.DURATION_SECOND_COUNTER_NAME,
187 big(nodeConnectorUpdate.getDuration().getSecond().getValue()));
188 crds.addCounterToGroup(resultId, CountersUtils.DURATION_GROUP_NAME,
189 CountersUtils.DURATION_NANO_SECOND_COUNTER_NAME,
190 big(nodeConnectorUpdate.getDuration().getNanosecond().getValue()));
197 public CounterResultDataStructure getSwitchFlowCountersDirect(BigInteger dpId, Match match) {
198 NodeRef nodeRef = new NodeRef(InstanceIdentifier.builder(Nodes.class)
199 .child(Node.class, new NodeKey(new NodeId(CountersUtils.getNodeId(dpId)))).toInstance());
200 GetFlowStatisticsInputBuilder gfsib = new GetFlowStatisticsInputBuilder();
201 gfsib.setNode(nodeRef);
202 gfsib.setMatch(match);
203 gfsib.setStoreStats(false);
205 Future<RpcResult<GetFlowStatisticsOutput>> rpcResultFuture =
206 odlDirectStatsService.getFlowStatistics(gfsib.build());
207 RpcResult<GetFlowStatisticsOutput> rpcResult = null;
209 rpcResult = rpcResultFuture.get();
210 } catch (InterruptedException | ExecutionException e) {
211 counters.failedGettingFlowCounters.inc();
212 LOG.warn("Unable to retrieve flow counters for match {}", match);
216 if (rpcResult != null && rpcResult.isSuccessful() && rpcResult.getResult() != null) {
217 GetFlowStatisticsOutput flowStatsOutput = rpcResult.getResult();
218 return createSwitchFlowResultMapDirect(flowStatsOutput);
220 counters.failedGettingFlowCounters.inc();
221 LOG.warn("Unable to retrieve flow counters for match {}", match);
226 private CounterResultDataStructure createSwitchFlowResultMapDirect(GetFlowStatisticsOutput flowStatsOutput) {
227 List<FlowAndStatisticsMapList> flowUpdates = flowStatsOutput.getFlowAndStatisticsMapList();
228 if (flowUpdates == null || flowUpdates.isEmpty()) {
229 LOG.warn("Unable to retrieve flows statistics info");
233 CounterResultDataStructure crds = new CounterResultDataStructure();
234 for (FlowAndStatisticsMapList flowUpdate : flowUpdates) {
235 String resultId = flowUpdate.getTableId().toString() + CountersUtils.OF_DELIMITER + UUID.randomUUID();
236 crds.addCounterResult(resultId);
237 if (flowUpdate.getByteCount() != null) {
238 crds.addCounterToGroup(resultId, CountersUtils.BYTES_GROUP_NAME, CountersUtils.BYTE_COUNTER_NAME,
239 flowUpdate.getByteCount().getValue());
241 if (flowUpdate.getPacketCount() != null) {
242 crds.addCounterToGroup(resultId, CountersUtils.PACKETS_GROUP_NAME, CountersUtils.PACKET_COUNTER_NAME,
243 flowUpdate.getPacketCount().getValue());
245 if (flowUpdate.getDuration() != null) {
246 crds.addCounterToGroup(resultId, CountersUtils.DURATION_GROUP_NAME,
247 CountersUtils.DURATION_SECOND_COUNTER_NAME,
248 big(flowUpdate.getDuration().getSecond().getValue()));
249 crds.addCounterToGroup(resultId, CountersUtils.DURATION_GROUP_NAME,
250 CountersUtils.DURATION_NANO_SECOND_COUNTER_NAME,
251 big(flowUpdate.getDuration().getNanosecond().getValue()));
257 private BigInteger big(Long longValue) {
258 return BigInteger.valueOf(longValue);
261 private static class Counters {
262 OccurenceCounter failedGettingNodeConnectorCounters = new OccurenceCounter(
263 getClass().getEnclosingClass().getSimpleName(), "failed_getting_node_connector_counters", "");
265 OccurenceCounter failedGettingRpcResultForNodeConnectorCounters = new OccurenceCounter(
266 getClass().getEnclosingClass().getSimpleName(),
267 "failed_getting_rpc_result_for_node_connector_counters", "");
269 OccurenceCounter failedGettingNodeCounters = new OccurenceCounter(
270 getClass().getEnclosingClass().getSimpleName(), "failed_getting_node_counters", "");
272 OccurenceCounter failedGettingResultMapForNodeConnectorCounters = new OccurenceCounter(
273 getClass().getEnclosingClass().getSimpleName(),
274 "failed_getting_result_map_for_node_connector_counters", "");
276 OccurenceCounter failedGettingFlowCounters = new OccurenceCounter(
277 getClass().getEnclosingClass().getSimpleName(), "failed_getting_flow_counters", "");