2 * Copyright (c) 2015 NEC Corporation
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this
7 * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
10 package org.opendaylight.vtn.manager.internal.flow.stats;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.Timer;
16 import java.util.TimerTask;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
21 import com.google.common.base.Optional;
23 import org.opendaylight.vtn.manager.VTNException;
25 import org.opendaylight.vtn.manager.internal.TxContext;
26 import org.opendaylight.vtn.manager.internal.TxQueue;
27 import org.opendaylight.vtn.manager.internal.VTNManagerProvider;
28 import org.opendaylight.vtn.manager.internal.util.DataStoreUtils;
29 import org.opendaylight.vtn.manager.internal.util.FixedLogger;
30 import org.opendaylight.vtn.manager.internal.util.LogRecord;
31 import org.opendaylight.vtn.manager.internal.util.flow.FlowCache;
32 import org.opendaylight.vtn.manager.internal.util.flow.FlowStatsUtils;
33 import org.opendaylight.vtn.manager.internal.util.tx.AbstractTxTask;
35 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
36 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.flow.rev150313.VtnFlows;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.flow.rev150313.tenant.flow.info.VtnDataFlow;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.flow.rev150313.tenant.flow.info.VtnDataFlowKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.flow.rev150313.vtn.data.flow.fields.FlowStatsHistory;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.flow.rev150313.vtn.data.flow.fields.VtnFlowEntry;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.flow.rev150313.vtn.data.flow.fields.flow.stats.history.FlowStatsRecord;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.flow.rev150313.vtn.data.flow.fields.flow.stats.history.FlowStatsRecordBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.flow.rev150313.vtn.flows.VtnFlowTable;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericStatistics;
53 * The timer task that collects flow statistics periodically.
55 public final class StatsTimerTask extends TimerTask implements AutoCloseable {
59 private static final Logger LOG =
60 LoggerFactory.getLogger(StatsTimerTask.class);
63 * The interval in milliseconds for updating flow statistics information.
65 private static final long STATS_INTERVAL = 10000;
68 * The MD-SAL transaction queue used to update the MD-SAL datastore.
70 private final TxQueue txQueue;
73 * {@code StatsUpdator} describes the MD-SAL datastore transaction task
74 * that updates flow statistics information.
76 private static class StatsUpdator extends AbstractTxTask<Void> {
78 * A logger for trace logs.
80 private final FixedLogger traceLogger = new FixedLogger.Trace(LOG);
83 * The system time when the flow statistics are collected.
85 private Long systemTime;
88 * A list of log records.
90 private List<LogRecord> logRecords;
93 * The MAC address of the controller.
95 private Long controllerAddress;
98 * Update flow statistics in the specified VTN.
100 * @param tx A {@link ReadWriteTransaction} instance.
101 * @param table A flow table that contains all the flow entries in
103 * @throws VTNException An error occurred.
105 private void update(ReadWriteTransaction tx, VtnFlowTable table)
106 throws VTNException {
107 List<VtnDataFlow> dataFlows = table.getVtnDataFlow();
108 if (dataFlows != null) {
109 String tname = table.getTenantName();
110 for (VtnDataFlow vdf: dataFlows) {
111 update(tx, tname, vdf);
117 * Update statistics information for the given flow entry.
119 * @param tx A {@link ReadWriteTransaction} instance.
120 * @param tname The name of the VTN.
121 * @param vdf A {@link VtnDataFlow} instance.
122 * @throws VTNException An error occurred.
124 private void update(ReadWriteTransaction tx, String tname,
125 VtnDataFlow vdf) throws VTNException {
126 VtnDataFlowKey key = vdf.getKey();
127 BigInteger id = key.getFlowId().getValue();
128 Long mac = vdf.getControllerAddress();
129 if (!controllerAddress.equals(mac)) {
130 String maddr = (mac == null)
132 : Long.toHexString(mac.longValue());
133 traceLog("Skip flow entry: %s: Not owner: %s", id, maddr);
137 FlowId fid = vdf.getSalFlowId();
139 traceLog("Skip flow entry: %s: No MD-SAL flow ID.", id);
143 // Read flow statistics collected by the MD-SAL statistics manager.
144 FlowCache fc = new FlowCache(vdf);
145 VtnFlowEntry vfent = fc.getIngressFlow();
146 GenericStatistics fstats =
147 FlowStatsUtils.read(tx, vfent.getNode(), fid);
148 String err = FlowStatsUtils.check(fstats);
150 traceLog("Skip flow entry: %s: %s", id, err);
154 // Update the hisotry of flow statistics if needed.
155 FlowStatsRecord fsr = new FlowStatsRecordBuilder(fstats).
156 setTime(systemTime).setPeriodic(true).build();
157 FlowStatsHistory history =
158 FlowStatsUtils.update(vdf.getFlowStatsHistory(), fsr);
159 if (history == null) {
160 traceLog("Skip flow entry: %s: Too rapid.", id);
162 traceLog("Flow statistics has been updated: %s, %s",
164 InstanceIdentifier<FlowStatsHistory> path =
165 FlowStatsUtils.getIdentifier(tname, key);
166 LogicalDatastoreType oper = LogicalDatastoreType.OPERATIONAL;
167 tx.put(oper, path, history, false);
172 * Record a trace log message.
174 * @param format A format string used to construct log message.
175 * @param args An object array used to construct log message.
177 private void traceLog(String format, Object ... args) {
178 if (traceLogger.isEnabled()) {
179 logRecords.add(new LogRecord(traceLogger, format, args));
189 public Void execute(TxContext ctx) throws VTNException {
190 systemTime = System.currentTimeMillis();
191 logRecords = new ArrayList<>();
192 if (controllerAddress == null) {
193 controllerAddress = ctx.getProvider().getVTNConfig().
194 getControllerMacAddress().getAddress();
197 // Read the root container of flow tables.
198 InstanceIdentifier<VtnFlows> path =
199 InstanceIdentifier.create(VtnFlows.class);
200 LogicalDatastoreType oper = LogicalDatastoreType.OPERATIONAL;
201 ReadWriteTransaction tx = ctx.getReadWriteTransaction();
202 Optional<VtnFlows> opt = DataStoreUtils.read(tx, oper, path);
203 if (opt.isPresent()) {
204 List<VtnFlowTable> tables = opt.get().getVtnFlowTable();
205 if (tables != null) {
206 for (VtnFlowTable table: tables) {
207 // Update flow statistics for this VTN.
219 * Invoked when the task has been completed successfully.
221 * @param provider VTN Manager provider service.
222 * @param result The result of this task.
225 public void onSuccess(VTNManagerProvider provider, Void result) {
226 for (LogRecord r: logRecords) {
230 LOG.debug("Flow statistics have been updated successfully.");
234 * Invoked when the task has failed.
236 * @param provider VTN Manager provider service.
237 * @param t A {@link Throwable} thrown by the task.
240 public void onFailure(VTNManagerProvider provider, Throwable t) {
241 LOG.error("Failed to update flow statistics.", t);
246 * Construct a new instance.
248 * @param timer A timer thread.
249 * @param txq A {@link TxQueue} instance used to update the MD-SAL
252 public StatsTimerTask(Timer timer, TxQueue txq) {
254 timer.scheduleAtFixedRate(this, STATS_INTERVAL, STATS_INTERVAL);
260 * Run the timer task to update flow statistics.
264 txQueue.post(new StatsUpdator());
270 * Close this timer task.
273 public void close() {