--- /dev/null
+module opendaylight-direct-statistics {
+ namespace "urn:opendaylight:direct:statistics";
+ prefix directstat;
+
+ import yang-ext { prefix ext; revision-date "2013-07-09"; }
+ import ietf-inet-types { prefix inet; revision-date "2010-09-24"; }
+ import opendaylight-inventory { prefix inv; revision-date "2013-08-19"; }
+ import opendaylight-statistics-types { prefix stat-types; revision-date "2013-09-25"; }
+
+ import opendaylight-flow-types { prefix flow-types; revision-date "2013-10-26"; }
+ import opendaylight-group-types { prefix group-types; revision-date "2013-10-18"; }
+ import opendaylight-meter-types { prefix meter-types; revision-date "2013-09-18"; }
+ import opendaylight-queue-types { prefix queue-types; revision-date "2013-09-25"; }
+ import opendaylight-table-types { prefix table-types; revision-date "2013-10-26"; }
+
+ import opendaylight-flow-statistics { prefix flowstat; revision-date "2013-08-19"; }
+ import opendaylight-port-statistics { prefix portstat; revision-date "2013-12-14"; }
+ import opendaylight-queue-statistics { prefix queuestat; revision-date "2013-12-16"; }
+
+ description "Openflow direct statistics polling.";
+
+ revision "2016-05-11" {
+ description "Initial revision of direct statistics service";
+ }
+
+ grouping store-stats-grouping {
+ description "Store collected statistics to DS/operational";
+
+ leaf store-stats {
+ type boolean;
+ default false;
+ }
+ }
+
+ grouping stats-input-common-grouping {
+ description "Shared input parameters for all rpc statistics (routing context and datastore flag)";
+
+ uses inv:node-context-ref;
+ uses store-stats-grouping;
+ }
+
+ rpc get-flow-statistics {
+ description "Get statistics for given flow";
+
+ input {
+ uses stats-input-common-grouping;
+ uses flow-types:flow;
+ }
+
+ output {
+ uses flowstat:flow-and-statistics-map-list;
+ }
+ }
+
+ rpc get-group-statistics {
+ description "Get statistics for given group";
+
+ input {
+ uses stats-input-common-grouping;
+
+ leaf group-id {
+ type group-types:group-id;
+ }
+ }
+
+ output {
+ uses group-types:group-statistics-reply;
+ }
+ }
+
+ rpc get-meter-statistics {
+ description "Get statistics for given meter";
+
+ input {
+ uses stats-input-common-grouping;
+
+ leaf meter-id {
+ type meter-types:meter-id;
+ }
+ }
+
+ output {
+ uses meter-types:meter-statistics-reply;
+ }
+ }
+
+ rpc get-node-connector-statistics {
+ description "Get statistics for given node connector from the node";
+
+ input {
+ uses stats-input-common-grouping;
+
+ leaf node-connector-id {
+ description "Optional, if omitted, returns statistics for all ports";
+ type inv:node-connector-id;
+ }
+ }
+
+ output {
+ uses portstat:node-connector-statistics-and-port-number-map;
+ }
+ }
+
+ rpc get-queue-statistics {
+ description "Get statistics for given queues from given port of the node";
+
+ input {
+ uses stats-input-common-grouping;
+
+ leaf node-connector-id {
+ type inv:node-connector-id;
+ }
+
+ leaf queue-id {
+ type queue-types:queue-id;
+ }
+ }
+
+ output {
+ uses queuestat:queue-id-and-statistics-map;
+ }
+ }
+}
* @return sync. future for Slave and MD-SAL completition for Master
*/
ListenableFuture<Void> shuttingDownDataStoreTransactions();
+
/**
* Method provides current devices connection context.
*
<T extends DataObject> void writeToTransaction(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
final T data) throws Exception;
+ /**
+ * Method creates put operation using provided data in underlying transaction chain and flag to create missing parents
+ * WARNING: This method is slow because of additional reading cost. Use it only if you really need to create parents.
+ */
+ <T extends DataObject> void writeToTransactionWithParentsSlow(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
+ final T data) throws Exception;
+
/**
* Method creates delete operation for provided path in underlying transaction chain.
*/
@Override
public <T extends DataObject> void writeToTransaction(final LogicalDatastoreType store,
final InstanceIdentifier<T> path, final T data) throws Exception {
- transactionChainManager.writeToTransaction(store, path, data);
+ transactionChainManager.writeToTransaction(store, path, data, false);
+ }
+
+ @Override
+ public <T extends DataObject> void writeToTransactionWithParentsSlow(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) throws Exception {
+ transactionChainManager.writeToTransaction(store, path, data, true);
}
@Override
}
<T extends DataObject> void writeToTransaction(final LogicalDatastoreType store,
- final InstanceIdentifier<T> path, final T data) throws Exception {
+ final InstanceIdentifier<T> path,
+ final T data,
+ final boolean createParents) throws Exception {
final WriteTransaction writeTx = getTransactionSafely();
if (writeTx != null) {
LOG.trace("writeToTransaction called with path {} ", path);
- writeTx.put(store, path, data);
+ writeTx.put(store, path, data, createParents);
} else {
LOG.debug("WriteTx is null for node {}. Write data for {} was not realized.", nodeII, path);
throw new Exception("Cannot write into transaction.");
protected OfHeader buildRequest(final Xid xid, final GetFlowStatisticsFromFlowTableInput input) {
final MultipartRequestFlowCaseBuilder multipartRequestFlowCaseBuilder = new MultipartRequestFlowCaseBuilder();
final MultipartRequestFlowBuilder mprFlowRequestBuilder = new MultipartRequestFlowBuilder();
- mprFlowRequestBuilder.setTableId(input.getTableId());
+
+ if (input.getTableId() != null) {
+ mprFlowRequestBuilder.setTableId(input.getTableId());
+ } else {
+ mprFlowRequestBuilder.setTableId(OFConstants.OFPTT_ALL);
+ }
if (input.getOutPort() != null) {
mprFlowRequestBuilder.setOutPort(input.getOutPort().longValue());
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
+import org.opendaylight.openflowplugin.impl.services.AbstractMultipartService;
+import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.StoreStatsGrouping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+import javax.annotation.Nullable;
+import java.util.List;
+import java.util.concurrent.Future;
+
+/**
+ * The abstract direct statistics service.
+ * This abstract service provides wrappers and tools for all other derived statistics services.
+ *
+ * @param <I> the input type parameter
+ * @param <O> the output type parameter
+ */
+public abstract class AbstractDirectStatisticsService<I extends StoreStatsGrouping, O> extends AbstractMultipartService<I> {
+
+ private final Function<RpcResult<List<MultipartReply>>, RpcResult<O>> resultTransformFunction =
+ new Function<RpcResult<List<MultipartReply>>, RpcResult<O>>() {
+ @Nullable
+ @Override
+ public RpcResult<O> apply(@Nullable RpcResult<List<MultipartReply>> input) {
+ Preconditions.checkNotNull(input);
+ final O reply = buildReply(input.getResult(), input.isSuccessful());
+ return RpcResultBuilder.success(reply).build();
+ }
+ };
+
+ private final AsyncFunction<RpcResult<O>, RpcResult<O>> resultStoreFunction =
+ new AsyncFunction<RpcResult<O>, RpcResult<O>>() {
+ @Nullable
+ @Override
+ public ListenableFuture<RpcResult<O>> apply(@Nullable RpcResult<O> input) throws Exception {
+ Preconditions.checkNotNull(input);
+
+ if (input.isSuccessful()) {
+ storeStatistics(input.getResult());
+ getDeviceContext().submitTransaction(); // TODO: If submitTransaction will ever return future, chain it
+ }
+
+ return Futures.immediateFuture(input);
+ }
+ };
+
+ private final MultipartType multipartType;
+ private final OpenflowVersion ofVersion = OpenflowVersion.get(getVersion());
+
+ /**
+ * Instantiates a new Abstract direct statistics service.
+ *
+ * @param multipartType the multipart type
+ * @param requestContextStack the request context stack
+ * @param deviceContext the device context
+ */
+ protected AbstractDirectStatisticsService(MultipartType multipartType, RequestContextStack requestContextStack, DeviceContext deviceContext) {
+ super(requestContextStack, deviceContext);
+ this.multipartType = multipartType;
+ }
+
+ /**
+ * Handle input and reply future.
+ *
+ * @param input the input
+ * @return the future
+ */
+ public Future<RpcResult<O>> handleAndReply(final I input) {
+ final ListenableFuture<RpcResult<List<MultipartReply>>> rpcReply = handleServiceCall(input);
+ ListenableFuture<RpcResult<O>> rpcResult = Futures.transform(rpcReply, resultTransformFunction);
+
+ if (input.isStoreStats()) {
+ rpcResult = Futures.transform(rpcResult, resultStoreFunction);
+ }
+
+ return rpcResult;
+ }
+
+ @Override
+ protected OfHeader buildRequest(Xid xid, I input) throws Exception {
+ return RequestInputUtils.createMultipartHeader(multipartType, xid.getValue(), getVersion())
+ .setMultipartRequestBody(buildRequestBody(input))
+ .build();
+ }
+
+ /**
+ * Gets openflow version.
+ *
+ * @return the openflow version
+ */
+ protected OpenflowVersion getOfVersion() {
+ return ofVersion;
+ }
+
+ /**
+ * Build multipart request body.
+ *
+ * @param input the input
+ * @return the multipart request body
+ */
+ protected abstract MultipartRequestBody buildRequestBody(I input);
+
+ /**
+ * Build output from multipart reply input.
+ *
+ * @param input the input
+ * @return the output
+ */
+ protected abstract O buildReply(List<MultipartReply> input, boolean success);
+
+ /**
+ * Store statistics.
+ * TODO: Remove dependency on deviceContext from derived methods
+ * TODO: Return future, so we will be able to chain it
+ *
+ * @param output the output
+ * @throws Exception the exception
+ */
+ protected abstract void storeStatistics(O output) throws Exception;
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
+import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.FlowStatsResponseConvertor;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchReactor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.MultipartReplyFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestFlowCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.flow._case.MultipartRequestFlowBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The Flow direct statistics service.
+ */
+public class FlowDirectStatisticsService extends AbstractDirectStatisticsService<GetFlowStatisticsInput, GetFlowStatisticsOutput> {
+ private final FlowStatsResponseConvertor flowStatsConvertor = new FlowStatsResponseConvertor();
+
+ /**
+ * Instantiates a new Flow direct statistics service.
+ *
+ * @param requestContextStack the request context stack
+ * @param deviceContext the device context
+ */
+ public FlowDirectStatisticsService(RequestContextStack requestContextStack, DeviceContext deviceContext) {
+ super(MultipartType.OFPMPFLOW, requestContextStack, deviceContext);
+ }
+
+ @Override
+ protected MultipartRequestBody buildRequestBody(GetFlowStatisticsInput input) {
+ final MultipartRequestFlowBuilder mprFlowRequestBuilder = new MultipartRequestFlowBuilder();
+
+ if (input.getTableId() != null) {
+ mprFlowRequestBuilder.setTableId(input.getTableId());
+ } else {
+ mprFlowRequestBuilder.setTableId(OFConstants.OFPTT_ALL);
+ }
+
+ if (input.getOutPort() != null) {
+ mprFlowRequestBuilder.setOutPort(input.getOutPort().longValue());
+ } else {
+ mprFlowRequestBuilder.setOutPort(OFConstants.OFPP_ANY);
+ }
+
+ if (input.getOutGroup() != null) {
+ mprFlowRequestBuilder.setOutGroup(input.getOutGroup());
+ } else {
+ mprFlowRequestBuilder.setOutGroup(OFConstants.OFPG_ANY);
+ }
+
+ if (input.getCookie() != null) {
+ mprFlowRequestBuilder.setCookie(input.getCookie().getValue());
+ } else {
+ mprFlowRequestBuilder.setCookie(OFConstants.DEFAULT_COOKIE);
+ }
+
+ if (input.getCookieMask() != null) {
+ mprFlowRequestBuilder.setCookieMask(input.getCookieMask().getValue());
+ } else {
+ mprFlowRequestBuilder.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
+ }
+
+ MatchReactor.getInstance().convert(input.getMatch(), getVersion(), mprFlowRequestBuilder, getDatapathId());
+
+ return new MultipartRequestFlowCaseBuilder()
+ .setMultipartRequestFlow(mprFlowRequestBuilder.build())
+ .build();
+ }
+
+ @Override
+ protected GetFlowStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+ final List<FlowAndStatisticsMapList> statsList = new ArrayList<>();
+
+ if (success) {
+ for (final MultipartReply mpReply : input) {
+ final MultipartReplyFlowCase caseBody = (MultipartReplyFlowCase) mpReply.getMultipartReplyBody();
+ final MultipartReplyFlow replyBody = caseBody.getMultipartReplyFlow();
+
+ final List<FlowAndStatisticsMapList> statsListPart = flowStatsConvertor.toSALFlowStatsList(replyBody.getFlowStats(), getDatapathId(), getOfVersion());
+
+ for (final FlowAndStatisticsMapList part : statsListPart) {
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowId flowId =
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowId(generateFlowId(part).getValue());
+
+ statsList.add(new FlowAndStatisticsMapListBuilder(part)
+ .setKey(new FlowAndStatisticsMapListKey(flowId))
+ .setFlowId(flowId)
+ .build());
+ }
+ }
+ }
+
+ return new GetFlowStatisticsOutputBuilder()
+ .setFlowAndStatisticsMapList(statsList)
+ .build();
+ }
+
+ @Override
+ protected void storeStatistics(GetFlowStatisticsOutput output) throws Exception {
+ final InstanceIdentifier<FlowCapableNode> nodePath = getDeviceContext()
+ .getDeviceState().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
+
+ for (final FlowAndStatisticsMapList flowStatistics : output.getFlowAndStatisticsMapList()) {
+ final FlowId flowId = generateFlowId(flowStatistics);
+ final FlowKey flowKey = new FlowKey(flowId);
+
+ final FlowStatisticsDataBuilder flowStatisticsDataBld = new FlowStatisticsDataBuilder()
+ .setFlowStatistics(new FlowStatisticsBuilder(flowStatistics).build());
+
+ final FlowBuilder flowBuilder = new FlowBuilder(flowStatistics)
+ .addAugmentation(FlowStatisticsData.class, flowStatisticsDataBld.build())
+ .setKey(flowKey);
+
+ final InstanceIdentifier<Flow> flowStatisticsPath = nodePath
+ .child(Table.class, new TableKey(flowStatistics.getTableId()))
+ .child(Flow.class, flowKey);
+
+ getDeviceContext().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, flowStatisticsPath, flowBuilder.build());
+ }
+ }
+
+ private FlowId generateFlowId(FlowAndStatisticsMapList flowStatistics) {
+ final FlowStatisticsDataBuilder flowStatisticsDataBld = new FlowStatisticsDataBuilder()
+ .setFlowStatistics(new FlowStatisticsBuilder(flowStatistics).build());
+
+ final FlowBuilder flowBuilder = new FlowBuilder(flowStatistics)
+ .addAugmentation(FlowStatisticsData.class, flowStatisticsDataBld.build());
+
+ final short tableId = flowStatistics.getTableId();
+ final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(flowBuilder.build());
+ return getDeviceContext().getDeviceFlowRegistry().storeIfNecessary(flowRegistryKey, tableId);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.GroupStatsResponseConvertor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.MultipartReplyGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.group._case.MultipartRequestGroupBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The Group direct statistics service.
+ */
+public class GroupDirectStatisticsService extends AbstractDirectStatisticsService<GetGroupStatisticsInput, GetGroupStatisticsOutput> {
+ private final GroupStatsResponseConvertor groupStatsConvertor = new GroupStatsResponseConvertor();
+
+ /**
+ * Instantiates a new Group direct statistics service.
+ *
+ * @param requestContextStack the request context stack
+ * @param deviceContext the device context
+ */
+ public GroupDirectStatisticsService(RequestContextStack requestContextStack, DeviceContext deviceContext) {
+ super(MultipartType.OFPMPGROUP, requestContextStack, deviceContext);
+ }
+
+ @Override
+ protected MultipartRequestBody buildRequestBody(GetGroupStatisticsInput input) {
+ final MultipartRequestGroupBuilder mprGroupBuild = new MultipartRequestGroupBuilder();
+
+ if (input.getGroupId() != null) {
+ mprGroupBuild.setGroupId(new GroupId(input.getGroupId().getValue()));
+ } else {
+ mprGroupBuild.setGroupId(new GroupId(OFConstants.OFPG_ALL));
+ }
+
+ return new MultipartRequestGroupCaseBuilder()
+ .setMultipartRequestGroup(mprGroupBuild.build())
+ .build();
+ }
+
+ @Override
+ protected GetGroupStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+ final List<GroupStats> groupStats = new ArrayList<>();
+
+ if (success) {
+ for (final MultipartReply mpReply : input) {
+ final MultipartReplyGroupCase caseBody = (MultipartReplyGroupCase) mpReply.getMultipartReplyBody();
+ final MultipartReplyGroup replyBody = caseBody.getMultipartReplyGroup();
+ groupStats.addAll(groupStatsConvertor.toSALGroupStatsList(replyBody.getGroupStats()));
+ }
+ }
+
+ return new GetGroupStatisticsOutputBuilder()
+ .setGroupStats(groupStats)
+ .build();
+ }
+
+ @Override
+ protected void storeStatistics(GetGroupStatisticsOutput output) throws Exception {
+ final InstanceIdentifier<FlowCapableNode> nodePath = getDeviceContext()
+ .getDeviceState().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
+
+ for (final GroupStats groupStatistics : output.getGroupStats()) {
+ final InstanceIdentifier<GroupStatistics> groupStatisticsPath = nodePath
+ .child(Group.class, new GroupKey(groupStatistics.getGroupId()))
+ .augmentation(NodeGroupStatistics.class)
+ .child(GroupStatistics.class);
+
+ final GroupStatistics stats = new GroupStatisticsBuilder(groupStatistics).build();
+ getDeviceContext().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, groupStatisticsPath, stats);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.MeterStatsResponseConvertor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter._case.MultipartReplyMeter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.meter._case.MultipartRequestMeterBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The Meter direct statistics service.
+ */
+public class MeterDirectStatisticsService extends AbstractDirectStatisticsService<GetMeterStatisticsInput, GetMeterStatisticsOutput> {
+ private final MeterStatsResponseConvertor meterStatsConvertor = new MeterStatsResponseConvertor();
+
+ /**
+ * Instantiates a new Meter direct statistics service.
+ *
+ * @param requestContextStack the request context stack
+ * @param deviceContext the device context
+ */
+ public MeterDirectStatisticsService(RequestContextStack requestContextStack, DeviceContext deviceContext) {
+ super(MultipartType.OFPMPMETER, requestContextStack, deviceContext);
+ }
+
+ @Override
+ protected MultipartRequestBody buildRequestBody(GetMeterStatisticsInput input) {
+ final MultipartRequestMeterBuilder mprMeterBuild = new MultipartRequestMeterBuilder();
+
+ if (input.getMeterId() != null) {
+ mprMeterBuild.setMeterId(new MeterId(input.getMeterId().getValue()));
+ } else {
+ mprMeterBuild.setMeterId(new MeterId(OFConstants.OFPM_ALL));
+ }
+
+ return new MultipartRequestMeterCaseBuilder()
+ .setMultipartRequestMeter(mprMeterBuild.build())
+ .build();
+ }
+
+ @Override
+ protected GetMeterStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+ final List<MeterStats> meterStats = new ArrayList<>();
+
+ if (success) {
+ for (final MultipartReply mpReply : input) {
+ final MultipartReplyMeterCase caseBody = (MultipartReplyMeterCase) mpReply.getMultipartReplyBody();
+ final MultipartReplyMeter replyBody = caseBody.getMultipartReplyMeter();
+ meterStats.addAll(meterStatsConvertor.toSALMeterStatsList(replyBody.getMeterStats()));
+ }
+ }
+
+ return new GetMeterStatisticsOutputBuilder()
+ .setMeterStats(meterStats)
+ .build();
+ }
+
+ @Override
+ protected void storeStatistics(GetMeterStatisticsOutput output) throws Exception {
+ final InstanceIdentifier<FlowCapableNode> nodePath = getDeviceContext()
+ .getDeviceState().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
+
+ for (final MeterStats meterStatistics : output.getMeterStats()) {
+ final InstanceIdentifier<MeterStatistics> meterPath = nodePath
+ .child(Meter.class, new MeterKey(meterStatistics.getMeterId()))
+ .augmentation(NodeMeterStatistics.class)
+ .child(MeterStatistics.class);
+
+ final MeterStatistics stats = new MeterStatisticsBuilder(meterStatistics).build();
+ getDeviceContext().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, meterPath, stats);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter32;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.DurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.BytesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.PacketsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStats;
+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.PortStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestPortStatsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.port.stats._case.MultipartRequestPortStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The Node connector direct statistics service.
+ */
+public class NodeConnectorDirectStatisticsService extends AbstractDirectStatisticsService<GetNodeConnectorStatisticsInput, GetNodeConnectorStatisticsOutput> {
+ /**
+ * Instantiates a new Node connector direct statistics service.
+ *
+ * @param requestContextStack the request context stack
+ * @param deviceContext the device context
+ */
+ public NodeConnectorDirectStatisticsService(RequestContextStack requestContextStack, DeviceContext deviceContext) {
+ super(MultipartType.OFPMPPORTSTATS, requestContextStack, deviceContext);
+ }
+
+ @Override
+ protected MultipartRequestBody buildRequestBody(GetNodeConnectorStatisticsInput input) {
+ final MultipartRequestPortStatsBuilder mprPortStatsBuilder = new MultipartRequestPortStatsBuilder();
+
+ if (input.getNodeConnectorId() != null) {
+ mprPortStatsBuilder.setPortNo(InventoryDataServiceUtil.portNumberfromNodeConnectorId(getOfVersion(), input.getNodeConnectorId()));
+ } else {
+ mprPortStatsBuilder.setPortNo(OFConstants.OFPP_ANY);
+ }
+
+ return new MultipartRequestPortStatsCaseBuilder()
+ .setMultipartRequestPortStats(mprPortStatsBuilder.build())
+ .build();
+ }
+
+ @Override
+ protected GetNodeConnectorStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+ final List<NodeConnectorStatisticsAndPortNumberMap> nodeConnectorStatisticsAndPortNumberMap = new ArrayList<>();
+
+ if (success) {
+ for (final MultipartReply mpReply : input) {
+ final MultipartReplyPortStatsCase caseBody = (MultipartReplyPortStatsCase) mpReply.getMultipartReplyBody();
+ final MultipartReplyPortStats replyBody = caseBody.getMultipartReplyPortStats();
+
+ for (final PortStats portStats : replyBody.getPortStats()) {
+ final NodeConnectorId nodeConnectorId = InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(
+ getDatapathId(), portStats.getPortNo(), getOfVersion());
+
+ final BytesBuilder bytesBuilder = new BytesBuilder()
+ .setReceived(portStats.getRxBytes())
+ .setTransmitted(portStats.getTxBytes());
+
+ final PacketsBuilder packetsBuilder = new PacketsBuilder()
+ .setReceived(portStats.getRxPackets())
+ .setTransmitted(portStats.getTxPackets());
+
+ final DurationBuilder durationBuilder = new DurationBuilder();
+
+ if (portStats.getDurationSec() != null) {
+ durationBuilder.setSecond(new Counter32(portStats.getDurationSec()));
+ }
+
+ if (portStats.getDurationNsec() != null) {
+ durationBuilder.setNanosecond(new Counter32(portStats.getDurationNsec()));
+ }
+
+ final NodeConnectorStatisticsAndPortNumberMap stats = new NodeConnectorStatisticsAndPortNumberMapBuilder()
+ .setBytes(bytesBuilder.build())
+ .setPackets(packetsBuilder.build())
+ .setNodeConnectorId(nodeConnectorId)
+ .setDuration(durationBuilder.build())
+ .setCollisionCount(portStats.getCollisions())
+ .setKey(new NodeConnectorStatisticsAndPortNumberMapKey(nodeConnectorId))
+ .setReceiveCrcError(portStats.getRxCrcErr()).setReceiveDrops(portStats.getRxDropped())
+ .setReceiveErrors(portStats.getRxErrors())
+ .setReceiveFrameError(portStats.getRxFrameErr())
+ .setReceiveOverRunError(portStats.getRxOverErr())
+ .setTransmitDrops(portStats.getTxDropped())
+ .setTransmitErrors(portStats.getTxErrors())
+ .build();
+
+ nodeConnectorStatisticsAndPortNumberMap.add(stats);
+ }
+ }
+ }
+
+ return new GetNodeConnectorStatisticsOutputBuilder()
+ .setNodeConnectorStatisticsAndPortNumberMap(nodeConnectorStatisticsAndPortNumberMap)
+ .build();
+ }
+
+ @Override
+ protected void storeStatistics(GetNodeConnectorStatisticsOutput output) throws Exception {
+ final InstanceIdentifier<Node> nodePath = getDeviceContext().getDeviceState().getNodeInstanceIdentifier();
+
+ for (final NodeConnectorStatisticsAndPortNumberMap nodeConnectorStatistics : output.getNodeConnectorStatisticsAndPortNumberMap()) {
+ final InstanceIdentifier<FlowCapableNodeConnectorStatistics> nodeConnectorPath = nodePath
+ .child(NodeConnector.class, new NodeConnectorKey(nodeConnectorStatistics.getNodeConnectorId()))
+ .augmentation(FlowCapableNodeConnectorStatisticsData.class)
+ .child(FlowCapableNodeConnectorStatistics.class);
+
+ final FlowCapableNodeConnectorStatistics stats = new FlowCapableNodeConnectorStatisticsBuilder(nodeConnectorStatistics).build();
+ getDeviceContext().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, nodeConnectorPath, stats);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.OpendaylightDirectStatisticsService;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+import java.util.Optional;
+import java.util.concurrent.Future;
+
+/**
+ * The Opendaylight direct statistics service.
+ * This service handles RPC requests, sends them to registered handlers and returns their replies.
+ */
+public class OpendaylightDirectStatisticsServiceImpl implements OpendaylightDirectStatisticsService {
+ private final OpendaylightDirectStatisticsServiceProvider provider;
+
+ /**
+ * Instantiates a new Opendaylight direct statistics service.
+ *
+ * @param provider the openflow direct statistics service provider
+ */
+ public OpendaylightDirectStatisticsServiceImpl(final OpendaylightDirectStatisticsServiceProvider provider) {
+ this.provider = provider;
+ }
+
+ @Override
+ public Future<RpcResult<GetGroupStatisticsOutput>> getGroupStatistics(GetGroupStatisticsInput input) {
+ final Optional<GroupDirectStatisticsService> service = provider.lookup(GroupDirectStatisticsService.class);
+
+ if (!service.isPresent()) {
+ return missingImplementation(GroupDirectStatisticsService.class);
+ }
+
+ return service.get().handleAndReply(input);
+ }
+
+ @Override
+ public Future<RpcResult<GetQueueStatisticsOutput>> getQueueStatistics(GetQueueStatisticsInput input) {
+ final Optional<QueueDirectStatisticsService> service = provider.lookup(QueueDirectStatisticsService.class);
+
+ if (!service.isPresent()) {
+ return missingImplementation(QueueDirectStatisticsService.class);
+ }
+
+ return service.get().handleAndReply(input);
+ }
+
+ @Override
+ public Future<RpcResult<GetFlowStatisticsOutput>> getFlowStatistics(GetFlowStatisticsInput input) {
+ final Optional<FlowDirectStatisticsService> service = provider.lookup(FlowDirectStatisticsService.class);
+
+ if (!service.isPresent()) {
+ return missingImplementation(FlowDirectStatisticsService.class);
+ }
+
+ return service.get().handleAndReply(input);
+ }
+
+ @Override
+ public Future<RpcResult<GetMeterStatisticsOutput>> getMeterStatistics(GetMeterStatisticsInput input) {
+ final Optional<MeterDirectStatisticsService> service = provider.lookup(MeterDirectStatisticsService.class);
+
+ if (!service.isPresent()) {
+ return missingImplementation(MeterDirectStatisticsService.class);
+ }
+
+ return service.get().handleAndReply(input);
+ }
+
+ @Override
+ public Future<RpcResult<GetNodeConnectorStatisticsOutput>> getNodeConnectorStatistics(GetNodeConnectorStatisticsInput input) {
+ final Optional<NodeConnectorDirectStatisticsService> service = provider.lookup(NodeConnectorDirectStatisticsService.class);
+
+ if (!service.isPresent()) {
+ return missingImplementation(NodeConnectorDirectStatisticsService.class);
+ }
+
+ return service.get().handleAndReply(input);
+ }
+
+ private <T extends DataObject> Future<RpcResult<T>> missingImplementation(Class service) {
+ return RpcResultBuilder.<T>failed().withError(
+ RpcError.ErrorType.APPLICATION,
+ String.format("No implementation found for direct statistics service %s.", service.getCanonicalName()))
+ .buildFuture();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * The Opendaylight direct statistics service provider.
+ */
+public class OpendaylightDirectStatisticsServiceProvider {
+ private Map<Class<? extends AbstractDirectStatisticsService>, AbstractDirectStatisticsService> services = new HashMap<>();
+
+ /**
+ * Register direct statistics service.
+ *
+ * @param type the service type
+ * @param service the service instance
+ */
+ public void register(Class<? extends AbstractDirectStatisticsService> type, AbstractDirectStatisticsService service) {
+ if (services.containsKey(type)) return;
+
+ services.put(type, service);
+ }
+
+ /**
+ * Lookup direct statistics service.
+ *
+ * @param <T> the type parameter
+ * @param type the service type
+ * @return the service instance
+ */
+ public <T extends AbstractDirectStatisticsService> Optional<T> lookup(Class<T> type) {
+ if (!services.containsKey(type)) return Optional.empty();
+
+ return Optional.of(type.cast(services.get(type)));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter32;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter64;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.DurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.MultipartReplyQueue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.multipart.reply.queue.QueueStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestQueueCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.queue._case.MultipartRequestQueueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.flow.capable.node.connector.queue.statistics.FlowCapableNodeConnectorQueueStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.flow.capable.node.connector.queue.statistics.FlowCapableNodeConnectorQueueStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMapBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The Queue direct statistics service.
+ */
+public class QueueDirectStatisticsService extends AbstractDirectStatisticsService<GetQueueStatisticsInput, GetQueueStatisticsOutput> {
+ /**
+ * Instantiates a new Queue direct statistics service.
+ *
+ * @param requestContextStack the request context stack
+ * @param deviceContext the device context
+ */
+ public QueueDirectStatisticsService(RequestContextStack requestContextStack, DeviceContext deviceContext) {
+ super(MultipartType.OFPMPQUEUE, requestContextStack, deviceContext);
+ }
+
+ @Override
+ protected MultipartRequestBody buildRequestBody(GetQueueStatisticsInput input) {
+ final MultipartRequestQueueBuilder mprQueueBuilder = new MultipartRequestQueueBuilder();
+
+ if (input.getQueueId() != null) {
+ mprQueueBuilder.setQueueId(input.getQueueId().getValue());
+ } else {
+ mprQueueBuilder.setQueueId(OFConstants.OFPQ_ALL);
+ }
+
+ if (input.getNodeConnectorId() != null) {
+ mprQueueBuilder.setPortNo(InventoryDataServiceUtil.portNumberfromNodeConnectorId(getOfVersion(), input.getNodeConnectorId()));
+ } else {
+ mprQueueBuilder.setPortNo(OFConstants.OFPP_ANY);
+ }
+
+ return new MultipartRequestQueueCaseBuilder()
+ .setMultipartRequestQueue(mprQueueBuilder.build())
+ .build();
+ }
+
+ @Override
+ protected GetQueueStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+ final List<QueueIdAndStatisticsMap> queueIdAndStatisticsMap = new ArrayList<>();
+
+ if (success) {
+ for (final MultipartReply mpReply : input) {
+ final MultipartReplyQueueCase caseBody = (MultipartReplyQueueCase) mpReply.getMultipartReplyBody();
+ final MultipartReplyQueue replyBody = caseBody.getMultipartReplyQueue();
+
+ for (final QueueStats queueStats : replyBody.getQueueStats()) {
+ final DurationBuilder durationBuilder = new DurationBuilder()
+ .setSecond(new Counter32(queueStats.getDurationSec()))
+ .setNanosecond(new Counter32(queueStats.getDurationNsec()));
+
+ final QueueIdAndStatisticsMapBuilder statsBuilder = new QueueIdAndStatisticsMapBuilder()
+ .setNodeConnectorId(InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(
+ getDatapathId(), queueStats.getPortNo(), getOfVersion()))
+ .setTransmissionErrors(new Counter64(queueStats.getTxErrors()))
+ .setTransmittedBytes(new Counter64(queueStats.getTxBytes()))
+ .setTransmittedPackets(new Counter64(queueStats.getTxPackets()))
+ .setQueueId(new QueueId(queueStats.getQueueId()))
+ .setDuration(durationBuilder.build());
+
+ queueIdAndStatisticsMap.add(statsBuilder.build());
+ }
+ }
+ }
+
+ return new GetQueueStatisticsOutputBuilder()
+ .setQueueIdAndStatisticsMap(queueIdAndStatisticsMap)
+ .build();
+ }
+
+ @Override
+ protected void storeStatistics(GetQueueStatisticsOutput output) throws Exception {
+ final InstanceIdentifier<Node> nodePath = getDeviceContext().getDeviceState().getNodeInstanceIdentifier();
+
+ for (final QueueIdAndStatisticsMap queueStatistics : output.getQueueIdAndStatisticsMap()) {
+ if (queueStatistics.getQueueId() != null) {
+ final QueueKey qKey = new QueueKey(queueStatistics.getQueueId());
+
+ final FlowCapableNodeConnectorQueueStatistics statChild =
+ new FlowCapableNodeConnectorQueueStatisticsBuilder(queueStatistics).build();
+
+ final FlowCapableNodeConnectorQueueStatisticsDataBuilder statBuild =
+ new FlowCapableNodeConnectorQueueStatisticsDataBuilder()
+ .setFlowCapableNodeConnectorQueueStatistics(statChild);
+
+ final InstanceIdentifier<Queue> queueStatisticsPath = nodePath
+ .child(NodeConnector.class, new NodeConnectorKey(queueStatistics.getNodeConnectorId()))
+ .augmentation(FlowCapableNodeConnector.class)
+ .child(Queue.class, qKey);
+
+ final Queue stats = new QueueBuilder()
+ .setKey(qKey)
+ .setQueueId(queueStatistics.getQueueId())
+ .addAugmentation(FlowCapableNodeConnectorQueueStatisticsData.class, statBuild.build()).build();
+
+ getDeviceContext().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, queueStatisticsPath, stats);
+ }
+ }
+ }
+}
\ No newline at end of file
import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightPortStatisticsServiceImpl;
import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightQueueStatisticsServiceImpl;
import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.OpendaylightFlowStatisticsServiceDelegateImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.FlowDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.GroupDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.MeterDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.NodeConnectorDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.OpendaylightDirectStatisticsServiceImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.OpendaylightDirectStatisticsServiceProvider;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.QueueDirectStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.OpendaylightDirectStatisticsService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.echo.service.rev150305.SalEchoService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.message.service.rev151020.SalExperimenterMessageService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.SalFlatBatchService;
rpcContext.registerRpcServiceImplementation(NodeConfigService.class, new NodeConfigServiceImpl(rpcContext, deviceContext));
rpcContext.registerRpcServiceImplementation(OpendaylightFlowStatisticsService.class, OpendaylightFlowStatisticsServiceImpl.createWithOook(rpcContext, deviceContext));
+ // Direct statistics gathering
+ final OpendaylightDirectStatisticsServiceProvider statisticsProvider = new OpendaylightDirectStatisticsServiceProvider();
+ statisticsProvider.register(FlowDirectStatisticsService.class, new FlowDirectStatisticsService(rpcContext, deviceContext));
+ statisticsProvider.register(GroupDirectStatisticsService.class, new GroupDirectStatisticsService(rpcContext, deviceContext));
+ statisticsProvider.register(MeterDirectStatisticsService.class, new MeterDirectStatisticsService(rpcContext, deviceContext));
+ statisticsProvider.register(NodeConnectorDirectStatisticsService.class, new NodeConnectorDirectStatisticsService(rpcContext, deviceContext));
+ statisticsProvider.register(QueueDirectStatisticsService.class, new QueueDirectStatisticsService(rpcContext, deviceContext));
+ rpcContext.registerRpcServiceImplementation(OpendaylightDirectStatisticsService.class, new OpendaylightDirectStatisticsServiceImpl(statisticsProvider));
+
final SalFlatBatchServiceImpl salFlatBatchService = new SalFlatBatchServiceImpl(
new SalFlowsBatchServiceImpl(salFlowService, flowCapableTransactionService),
new SalGroupsBatchServiceImpl(salGroupService, flowCapableTransactionService),
rpcContext.unregisterRpcServiceImplementation(SalFlatBatchService.class);
// TODO: experimenter symmetric and multipart message services
rpcContext.unregisterRpcServiceImplementation(SalExperimenterMessageService.class);
+ rpcContext.unregisterRpcServiceImplementation(OpendaylightDirectStatisticsService.class);
}
/**
@Test
public void testWriteToTransaction() throws Exception {
final Node data = new NodeBuilder().setId(nodeId).build();
- txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data);
+ txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data, false);
Mockito.verify(txChain).newWriteOnlyTransaction();
- Mockito.verify(writeTx).put(LogicalDatastoreType.CONFIGURATION, path, data);
+ Mockito.verify(writeTx).put(LogicalDatastoreType.CONFIGURATION, path, data, false);
}
/**
public void testSubmitTransaction() throws Exception {
final Node data = new NodeBuilder().setId(nodeId).build();
txChainManager.initialSubmitWriteTransaction();
- txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data);
+ txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data, false);
txChainManager.submitWriteTransaction();
Mockito.verify(txChain).newWriteOnlyTransaction();
- Mockito.verify(writeTx).put(LogicalDatastoreType.CONFIGURATION, path, data);
+ Mockito.verify(writeTx).put(LogicalDatastoreType.CONFIGURATION, path, data, false);
Mockito.verify(writeTx).submit();
}
@Test
public void testSubmitTransaction1() throws Exception {
final Node data = new NodeBuilder().setId(nodeId).build();
- txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data);
+ txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data, false);
txChainManager.submitWriteTransaction();
Mockito.verify(txChain).newWriteOnlyTransaction();
- Mockito.verify(writeTx).put(LogicalDatastoreType.CONFIGURATION, path, data);
+ Mockito.verify(writeTx).put(LogicalDatastoreType.CONFIGURATION, path, data, false);
Mockito.verify(writeTx, Mockito.never()).submit();
}
Mockito.when(writeTx.submit()).thenReturn(Futures.<Void, TransactionCommitFailedException>immediateFailedCheckedFuture(new TransactionCommitFailedException("mock")));
final Node data = new NodeBuilder().setId(nodeId).build();
txChainManager.initialSubmitWriteTransaction();
- txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data);
+ txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data, false);
txChainManager.submitWriteTransaction();
Mockito.verify(txChain).newWriteOnlyTransaction();
- Mockito.verify(writeTx).put(LogicalDatastoreType.CONFIGURATION, path, data);
+ Mockito.verify(writeTx).put(LogicalDatastoreType.CONFIGURATION, path, data, false);
Mockito.verify(writeTx).submit();
}
@Test
public void testEnableCounter1() throws Exception {
final Node data = new NodeBuilder().setId(nodeId).build();
- txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data);
- txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data);
+ txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data, false);
+ txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data, false);
Mockito.verify(txChain).newWriteOnlyTransaction();
- Mockito.verify(writeTx, Mockito.times(2)).put(LogicalDatastoreType.CONFIGURATION, path, data);
+ Mockito.verify(writeTx, Mockito.times(2)).put(LogicalDatastoreType.CONFIGURATION, path, data, false);
Mockito.verify(writeTx, Mockito.never()).submit();
}
public void testDeactivateTransactionChainManagerFailed() throws Exception {
Mockito.when(writeTx.submit()).thenReturn(Futures.<Void, TransactionCommitFailedException>immediateFailedCheckedFuture(new TransactionCommitFailedException("mock")));
final Node data = new NodeBuilder().setId(nodeId).build();
- txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data);
+ txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data, false);
txChainManager.deactivateTransactionManager();
Mockito.verify(txChain).newWriteOnlyTransaction();
- Mockito.verify(writeTx).put(LogicalDatastoreType.CONFIGURATION, path, data);
+ Mockito.verify(writeTx).put(LogicalDatastoreType.CONFIGURATION, path, data, false);
Mockito.verify(writeTx).submit();
Mockito.verify(txChain).close();
}
@Test
public void testShuttingDown() throws Exception{
final Node data = new NodeBuilder().setId(nodeId).build();
- txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data);
+ txChainManager.writeToTransaction(LogicalDatastoreType.CONFIGURATION, path, data, false);
txChainManager.shuttingDown();
Mockito.verify(txChain).newWriteOnlyTransaction();
- Mockito.verify(writeTx).put(LogicalDatastoreType.CONFIGURATION, path, data);
+ Mockito.verify(writeTx).put(LogicalDatastoreType.CONFIGURATION, path, data, false);
Mockito.verify(writeTx).submit();
}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
+import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
+import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+import java.math.BigInteger;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public abstract class AbstractDirectStatisticsServiceTest {
+ protected static final Long PORT_NO = 1L;
+ protected static final BigInteger DATAPATH_ID = BigInteger.TEN;
+ protected static final short OF_VERSION = OFConstants.OFP_VERSION_1_3;
+ protected static final String NODE_ID = "openflow:1";
+
+ @Mock
+ protected RequestContextStack requestContextStack;
+ @Mock
+ protected DeviceContext deviceContext;
+ @Mock
+ protected ConnectionContext connectionContext;
+ @Mock
+ protected FeaturesReply features;
+ @Mock
+ protected MessageSpy messageSpy;
+ @Mock
+ protected OutboundQueue outboundQueueProvider;
+ @Mock
+ protected MultiMsgCollector multiMsgCollector;
+ @Mock
+ protected TranslatorLibrary translatorLibrary;
+ @Mock
+ protected DeviceState deviceState;
+ @Mock
+ protected GetFeaturesOutput getFeaturesOutput;
+
+ protected NodeConnectorId nodeConnectorId;
+ protected KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier;
+
+ protected static NodeRef createNodeRef(String nodeIdValue) {
+ InstanceIdentifier<Node> nodePath = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId(nodeIdValue)));
+
+ return new NodeRef(nodePath);
+ }
+
+ @Before
+ public void init() throws Exception {
+ OpenflowPortsUtil.init();
+
+ nodeConnectorId = InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(
+ DATAPATH_ID, PORT_NO, OpenflowVersion.get(OF_VERSION));
+
+ nodeInstanceIdentifier = InstanceIdentifier
+ .create(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId(NODE_ID)));
+
+ when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
+ when(deviceContext.getMessageSpy()).thenReturn(messageSpy);
+ when(deviceContext.getMultiMsgCollector(any())).thenReturn(multiMsgCollector);
+ when(deviceContext.oook()).thenReturn(translatorLibrary);
+ when(deviceContext.getDeviceState()).thenReturn(deviceState);
+ when(deviceContext.getDeviceState()).thenReturn(deviceState);
+ when(deviceState.getNodeInstanceIdentifier()).thenReturn(nodeInstanceIdentifier);
+ when(deviceState.getNodeId()).thenReturn(new NodeId(NODE_ID));
+ when(deviceState.getVersion()).thenReturn(OF_VERSION);
+ when(deviceState.getFeatures()).thenReturn(getFeaturesOutput);
+ when(getFeaturesOutput.getVersion()).thenReturn(OF_VERSION);
+ when(getFeaturesOutput.getDatapathId()).thenReturn(DATAPATH_ID);
+ when(connectionContext.getFeatures()).thenReturn(features);
+ when(connectionContext.getOutboundQueueProvider()).thenReturn(outboundQueueProvider);
+ when(features.getVersion()).thenReturn(OF_VERSION);
+ when(features.getDatapathId()).thenReturn(DATAPATH_ID);
+ setUp();
+ }
+
+ protected abstract void setUp() throws Exception;
+
+ @Test
+ public abstract void testBuildRequestBody() throws Exception;
+
+ @Test
+ public abstract void testBuildReply() throws Exception;
+
+ @Test
+ public abstract void testStoreStatistics() throws Exception;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowAndStatisticsMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.MultipartReplyFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.multipart.reply.flow.FlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestFlowCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.flow._case.MultipartRequestFlow;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class FlowDirectStatisticsServiceTest extends AbstractDirectStatisticsServiceTest {
+ static final Short TABLE_NO = 1;
+ private FlowDirectStatisticsService service;
+
+ @Override
+ public void setUp() throws Exception {
+ service = new FlowDirectStatisticsService(requestContextStack, deviceContext);
+ final DeviceFlowRegistry registry = mock(DeviceFlowRegistry.class);
+ when(registry.storeIfNecessary(any(), eq(TABLE_NO))).thenReturn(new FlowId("1"));
+ when(deviceContext.getDeviceFlowRegistry()).thenReturn(registry);
+ }
+
+ @Override
+ public void testBuildRequestBody() throws Exception {
+ final GetFlowStatisticsInput input = mock(GetFlowStatisticsInput.class);
+
+ when(input.getNode()).thenReturn(createNodeRef(NODE_ID));
+ when(input.getTableId()).thenReturn(TABLE_NO);
+
+ final MultipartRequestFlowCase body = (MultipartRequestFlowCase) service.buildRequestBody(input);
+ final MultipartRequestFlow flow = body.getMultipartRequestFlow();
+
+ assertEquals(TABLE_NO, flow.getTableId());
+ }
+
+ @Override
+ public void testBuildReply() throws Exception {
+ final MultipartReply reply = mock(MultipartReply.class);
+ final MultipartReplyFlowCase flowCase = mock(MultipartReplyFlowCase.class);
+ final MultipartReplyFlow flow = mock(MultipartReplyFlow.class);
+ final FlowStats flowStat = mock(FlowStats.class);
+ final List<FlowStats> flowStats = Arrays.asList(flowStat);
+ final List<MultipartReply> input = Arrays.asList(reply);
+
+ when(flow.getFlowStats()).thenReturn(flowStats);
+ when(flowCase.getMultipartReplyFlow()).thenReturn(flow);
+ when(reply.getMultipartReplyBody()).thenReturn(flowCase);
+
+ when(flowStat.getTableId()).thenReturn(TABLE_NO);
+ when(flowStat.getByteCount()).thenReturn(BigInteger.ONE);
+ when(flowStat.getPacketCount()).thenReturn(BigInteger.ONE);
+ when(flowStat.getFlags()).thenReturn(mock(FlowModFlags.class));
+ when(flowStat.getMatch()).thenReturn(new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.MatchBuilder()
+ .setMatchEntry(Collections.emptyList())
+ .build());
+
+ final GetFlowStatisticsOutput output = service.buildReply(input, true);
+ assertTrue(output.getFlowAndStatisticsMapList().size() > 0);
+
+ final FlowAndStatisticsMap stats = output.getFlowAndStatisticsMapList().get(0);
+
+ assertEquals(stats.getTableId(), TABLE_NO);
+ }
+
+ @Override
+ public void testStoreStatistics() throws Exception {
+ final FlowAndStatisticsMapList stat = mock(FlowAndStatisticsMapList.class);
+ when(stat.getTableId()).thenReturn(TABLE_NO);
+ when(stat.getMatch()).thenReturn(new MatchBuilder().build());
+
+ final List<FlowAndStatisticsMapList> stats = Arrays.asList(stat);
+ final GetFlowStatisticsOutput output = mock(GetFlowStatisticsOutput.class);
+ when(output.getFlowAndStatisticsMapList()).thenReturn(stats);
+
+ service.storeStatistics(output);
+ verify(deviceContext).writeToTransactionWithParentsSlow(eq(LogicalDatastoreType.OPERATIONAL), any(), any());
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.MultipartReplyGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.multipart.reply.group.GroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.group._case.MultipartRequestGroup;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class GroupDirectStatisticsServiceTest extends AbstractDirectStatisticsServiceTest {
+ static final Long GROUP_NO = 1L;
+ private GroupDirectStatisticsService service;
+
+ @Override
+ public void setUp() throws Exception {
+ service = new GroupDirectStatisticsService(requestContextStack, deviceContext);
+ }
+
+ @Override
+ public void testBuildRequestBody() throws Exception {
+ final GetGroupStatisticsInput input = mock(GetGroupStatisticsInput.class);
+
+ when(input.getNode()).thenReturn(createNodeRef(NODE_ID));
+ when(input.getGroupId()).thenReturn(new GroupId(GROUP_NO));
+
+ final MultipartRequestGroupCase body = (MultipartRequestGroupCase) service.buildRequestBody(input);
+ final MultipartRequestGroup group = body.getMultipartRequestGroup();
+
+ assertEquals(GROUP_NO, group.getGroupId().getValue());
+ }
+
+ @Override
+ public void testBuildReply() throws Exception {
+ final MultipartReply reply = mock(MultipartReply.class);
+ final MultipartReplyGroupCase groupCase = mock(MultipartReplyGroupCase.class);
+ final MultipartReplyGroup group = mock(MultipartReplyGroup.class);
+ final GroupStats groupStat = mock(GroupStats.class);
+ final List<GroupStats> groupStats = Arrays.asList(groupStat);
+ final List<MultipartReply> input = Arrays.asList(reply);
+
+ when(group.getGroupStats()).thenReturn(groupStats);
+ when(groupCase.getMultipartReplyGroup()).thenReturn(group);
+ when(reply.getMultipartReplyBody()).thenReturn(groupCase);
+
+ when(groupStat.getGroupId()).thenReturn(new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupId(GROUP_NO));
+ when(groupStat.getByteCount()).thenReturn(BigInteger.ONE);
+ when(groupStat.getPacketCount()).thenReturn(BigInteger.ONE);
+
+ final GetGroupStatisticsOutput output = service.buildReply(input, true);
+ assertTrue(output.getGroupStats().size() > 0);
+
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats stats =
+ output.getGroupStats().get(0);
+
+ assertEquals(stats.getGroupId().getValue(), GROUP_NO);
+ }
+
+ @Override
+ public void testStoreStatistics() throws Exception {
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats stat = mock(org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats.class);
+ when(stat.getGroupId()).thenReturn(new GroupId(GROUP_NO));
+
+ final List<org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats> stats = Arrays.asList(stat);
+ final GetGroupStatisticsOutput output = mock(GetGroupStatisticsOutput.class);
+ when(output.getGroupStats()).thenReturn(stats);
+
+ service.storeStatistics(output);
+ verify(deviceContext).writeToTransactionWithParentsSlow(eq(LogicalDatastoreType.OPERATIONAL), any(), any());
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter._case.MultipartReplyMeter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter._case.multipart.reply.meter.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.meter._case.MultipartRequestMeter;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class MeterDirectStatisticsServiceTest extends AbstractDirectStatisticsServiceTest {
+ static final Long METER_NO = 1L;
+ private MeterDirectStatisticsService service;
+
+ @Override
+ public void setUp() throws Exception {
+ service = new MeterDirectStatisticsService(requestContextStack, deviceContext);
+ }
+
+ @Override
+ public void testBuildRequestBody() throws Exception {
+ final GetMeterStatisticsInput input = mock(GetMeterStatisticsInput.class);
+
+ when(input.getNode()).thenReturn(createNodeRef(NODE_ID));
+ when(input.getMeterId()).thenReturn(new MeterId(METER_NO));
+
+ final MultipartRequestMeterCase body = (MultipartRequestMeterCase) service.buildRequestBody(input);
+ final MultipartRequestMeter meter = body.getMultipartRequestMeter();
+
+ assertEquals(METER_NO, meter.getMeterId().getValue());
+ }
+
+ @Override
+ public void testBuildReply() throws Exception {
+ final MultipartReply reply = mock(MultipartReply.class);
+ final MultipartReplyMeterCase MeterCase = mock(MultipartReplyMeterCase.class);
+ final MultipartReplyMeter meter = mock(MultipartReplyMeter.class);
+ final MeterStats meterStat = mock(MeterStats.class);
+ final List<MeterStats> meterStats = Arrays.asList(meterStat);
+ final List<MultipartReply> input = Arrays.asList(reply);
+
+ when(meter.getMeterStats()).thenReturn(meterStats);
+ when(MeterCase.getMultipartReplyMeter()).thenReturn(meter);
+ when(reply.getMultipartReplyBody()).thenReturn(MeterCase);
+
+ when(meterStat.getMeterId()).thenReturn(new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterId(METER_NO));
+ when(meterStat.getByteInCount()).thenReturn(BigInteger.ONE);
+ when(meterStat.getPacketInCount()).thenReturn(BigInteger.ONE);
+
+ final GetMeterStatisticsOutput output = service.buildReply(input, true);
+ assertTrue(output.getMeterStats().size() > 0);
+
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats stats =
+ output.getMeterStats().get(0);
+
+ assertEquals(stats.getMeterId().getValue(), METER_NO);
+ }
+
+ @Override
+ public void testStoreStatistics() throws Exception {
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats stat = mock(org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats.class);
+ when(stat.getMeterId()).thenReturn(new MeterId(METER_NO));
+
+ final List<org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats> stats = Arrays.asList(stat);
+ final GetMeterStatisticsOutput output = mock(GetMeterStatisticsOutput.class);
+ when(output.getMeterStats()).thenReturn(stats);
+
+ service.storeStatistics(output);
+ verify(deviceContext).writeToTransactionWithParentsSlow(eq(LogicalDatastoreType.OPERATIONAL), any(), any());
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStats;
+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.PortStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestPortStatsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.port.stats._case.MultipartRequestPortStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class NodeConnectorDirectStatisticsServiceTest extends AbstractDirectStatisticsServiceTest {
+ private NodeConnectorDirectStatisticsService service;
+
+ @Override
+ public void setUp() throws Exception {
+ service = new NodeConnectorDirectStatisticsService(requestContextStack, deviceContext);
+ }
+
+ @Override
+ public void testBuildRequestBody() throws Exception {
+ final GetNodeConnectorStatisticsInput input = mock(GetNodeConnectorStatisticsInput.class);
+
+ when(input.getNode()).thenReturn(createNodeRef(NODE_ID));
+ when(input.getNodeConnectorId()).thenReturn(nodeConnectorId);
+
+ final MultipartRequestPortStatsCase body = (MultipartRequestPortStatsCase) service.buildRequestBody(input);
+ final MultipartRequestPortStats nodeConnector = body.getMultipartRequestPortStats();
+
+ assertEquals(PORT_NO, nodeConnector.getPortNo());
+ }
+
+ @Override
+ public void testBuildReply() throws Exception {
+ final MultipartReply reply = mock(MultipartReply.class);
+ final MultipartReplyPortStatsCase nodeConnectorCase = mock(MultipartReplyPortStatsCase.class);
+ final MultipartReplyPortStats nodeConnector = mock(MultipartReplyPortStats.class);
+ final PortStats nodeConnectorStat = mock(PortStats.class);
+ final List<PortStats> nodeConnectorStats = Arrays.asList(nodeConnectorStat);
+ final List<MultipartReply> input = Arrays.asList(reply);
+
+ when(nodeConnector.getPortStats()).thenReturn(nodeConnectorStats);
+ when(nodeConnectorCase.getMultipartReplyPortStats()).thenReturn(nodeConnector);
+ when(reply.getMultipartReplyBody()).thenReturn(nodeConnectorCase);
+
+ when(nodeConnectorStat.getPortNo()).thenReturn(PORT_NO);
+ when(nodeConnectorStat.getTxBytes()).thenReturn(BigInteger.ONE);
+ when(nodeConnectorStat.getCollisions()).thenReturn(BigInteger.ONE);
+ when(nodeConnectorStat.getRxBytes()).thenReturn(BigInteger.ONE);
+ when(nodeConnectorStat.getRxCrcErr()).thenReturn(BigInteger.ONE);
+ when(nodeConnectorStat.getRxDropped()).thenReturn(BigInteger.ONE);
+ when(nodeConnectorStat.getRxErrors()).thenReturn(BigInteger.ONE);
+ when(nodeConnectorStat.getRxFrameErr()).thenReturn(BigInteger.ONE);
+ when(nodeConnectorStat.getRxOverErr()).thenReturn(BigInteger.ONE);
+ when(nodeConnectorStat.getRxPackets()).thenReturn(BigInteger.ONE);
+ when(nodeConnectorStat.getTxDropped()).thenReturn(BigInteger.ONE);
+ when(nodeConnectorStat.getTxErrors()).thenReturn(BigInteger.ONE);
+
+ final GetNodeConnectorStatisticsOutput output = service.buildReply(input, true);
+ assertTrue(output.getNodeConnectorStatisticsAndPortNumberMap().size() > 0);
+
+ final NodeConnectorStatisticsAndPortNumberMap stats =
+ output.getNodeConnectorStatisticsAndPortNumberMap().get(0);
+
+ assertEquals(stats.getNodeConnectorId(), nodeConnectorId);
+ }
+
+ @Override
+ public void testStoreStatistics() throws Exception {
+ final NodeConnectorStatisticsAndPortNumberMap stat = mock(NodeConnectorStatisticsAndPortNumberMap.class);
+ when(stat.getNodeConnectorId()).thenReturn(nodeConnectorId);
+
+ final List<NodeConnectorStatisticsAndPortNumberMap> stats = Arrays.asList(stat);
+ final GetNodeConnectorStatisticsOutput output = mock(GetNodeConnectorStatisticsOutput.class);
+ when(output.getNodeConnectorStatisticsAndPortNumberMap()).thenReturn(stats);
+
+ service.storeStatistics(output);
+ verify(deviceContext).writeToTransactionWithParentsSlow(eq(LogicalDatastoreType.OPERATIONAL), any(), any());
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.OpendaylightDirectStatisticsService;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+@RunWith(MockitoJUnitRunner.class)
+public class OpendaylightDirectStatisticsServiceImplTest {
+ @Mock
+ FlowDirectStatisticsService flowDirectStatisticsService;
+ @Mock
+ GroupDirectStatisticsService groupDirectStatisticsService;
+ @Mock
+ MeterDirectStatisticsService meterDirectStatisticsService;
+ @Mock
+ NodeConnectorDirectStatisticsService nodeConnectorDirectStatisticsService;
+ @Mock
+ QueueDirectStatisticsService queueDirectStatisticsService;
+
+ @Mock
+ GetGroupStatisticsInput getGroupStatisticsInput;
+ @Mock
+ GetQueueStatisticsInput getQueueStatisticsInput;
+ @Mock
+ GetFlowStatisticsInput getFlowStatisticsInput;
+ @Mock
+ GetMeterStatisticsInput getMeterStatisticsInput;
+ @Mock
+ GetNodeConnectorStatisticsInput getNodeConnectorStatisticsInput;
+
+ private OpendaylightDirectStatisticsService service;
+ private OpendaylightDirectStatisticsService emptyService;
+
+ @Before
+ public void setUp() throws Exception {
+ final OpendaylightDirectStatisticsServiceProvider provider = new OpendaylightDirectStatisticsServiceProvider();
+ provider.register(FlowDirectStatisticsService.class, flowDirectStatisticsService);
+ provider.register(GroupDirectStatisticsService.class, groupDirectStatisticsService);
+ provider.register(MeterDirectStatisticsService.class, meterDirectStatisticsService);
+ provider.register(NodeConnectorDirectStatisticsService.class, nodeConnectorDirectStatisticsService);
+ provider.register(QueueDirectStatisticsService.class, queueDirectStatisticsService);
+
+ service = new OpendaylightDirectStatisticsServiceImpl(provider);
+ emptyService = new OpendaylightDirectStatisticsServiceImpl(new OpendaylightDirectStatisticsServiceProvider());
+ }
+
+ @Test
+ public void testGetGroupStatistics() throws Exception {
+ service.getGroupStatistics(getGroupStatisticsInput);
+ verify(groupDirectStatisticsService).handleAndReply(getGroupStatisticsInput);
+ }
+
+ @Test
+ public void testGetGroupStatisticsFail() throws Exception {
+ RpcResult<GetGroupStatisticsOutput> result = emptyService
+ .getGroupStatistics(getGroupStatisticsInput)
+ .get();
+
+ assertFalse(result.isSuccessful());
+
+ for (RpcError error : result.getErrors()) {
+ assertTrue(error.getMessage().contains(GroupDirectStatisticsService.class.getSimpleName()));
+ }
+
+ verify(groupDirectStatisticsService, times(0)).handleAndReply(getGroupStatisticsInput);
+ }
+
+ @Test
+ public void testGetQueueStatistics() throws Exception {
+ service.getQueueStatistics(getQueueStatisticsInput);
+ verify(queueDirectStatisticsService).handleAndReply(getQueueStatisticsInput);
+ }
+
+ @Test
+ public void testGetQueueStatisticsFail() throws Exception {
+ RpcResult<GetQueueStatisticsOutput> result = emptyService
+ .getQueueStatistics(getQueueStatisticsInput)
+ .get();
+
+ assertFalse(result.isSuccessful());
+
+ for (RpcError error : result.getErrors()) {
+ assertTrue(error.getMessage().contains(QueueDirectStatisticsService.class.getSimpleName()));
+ }
+
+ verify(queueDirectStatisticsService, times(0)).handleAndReply(getQueueStatisticsInput);
+ }
+
+ @Test
+ public void testGetFlowStatistics() throws Exception {
+ service.getFlowStatistics(getFlowStatisticsInput);
+ verify(flowDirectStatisticsService).handleAndReply(getFlowStatisticsInput);
+ }
+
+ @Test
+ public void testGetFlowStatisticsFail() throws Exception {
+ RpcResult<GetFlowStatisticsOutput> result = emptyService
+ .getFlowStatistics(getFlowStatisticsInput)
+ .get();
+
+ assertFalse(result.isSuccessful());
+
+ for (RpcError error : result.getErrors()) {
+ assertTrue(error.getMessage().contains(FlowDirectStatisticsService.class.getSimpleName()));
+ }
+
+ verify(flowDirectStatisticsService, times(0)).handleAndReply(getFlowStatisticsInput);
+ }
+
+ @Test
+ public void testGetMeterStatistics() throws Exception {
+ service.getMeterStatistics(getMeterStatisticsInput);
+ verify(meterDirectStatisticsService).handleAndReply(getMeterStatisticsInput);
+ }
+
+ @Test
+ public void testGetMeterStatisticsFail() throws Exception {
+ RpcResult<GetMeterStatisticsOutput> result = emptyService
+ .getMeterStatistics(getMeterStatisticsInput)
+ .get();
+
+ assertFalse(result.isSuccessful());
+
+ for (RpcError error : result.getErrors()) {
+ assertTrue(error.getMessage().contains(MeterDirectStatisticsService.class.getSimpleName()));
+ }
+
+ verify(meterDirectStatisticsService, times(0)).handleAndReply(getMeterStatisticsInput);
+ }
+
+ @Test
+ public void testGetNodeConnectorStatistics() throws Exception {
+ service.getNodeConnectorStatistics(getNodeConnectorStatisticsInput);
+ verify(nodeConnectorDirectStatisticsService).handleAndReply(getNodeConnectorStatisticsInput);
+ }
+
+ @Test
+ public void testGetNodeConnectorStatisticsFail() throws Exception {
+ RpcResult<GetNodeConnectorStatisticsOutput> result = emptyService
+ .getNodeConnectorStatistics(getNodeConnectorStatisticsInput)
+ .get();
+
+ assertFalse(result.isSuccessful());
+
+ for (RpcError error : result.getErrors()) {
+ assertTrue(error.getMessage().contains(NodeConnectorDirectStatisticsService.class.getSimpleName()));
+ }
+
+ verify(nodeConnectorDirectStatisticsService, times(0)).handleAndReply(getNodeConnectorStatisticsInput);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.MultipartReplyQueue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.multipart.reply.queue.QueueStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestQueueCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.queue._case.MultipartRequestQueue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class QueueDirectStatisticsServiceTest extends AbstractDirectStatisticsServiceTest {
+ static final Long QUEUE_NO = 1L;
+ private QueueDirectStatisticsService service;
+
+ @Override
+ public void setUp() throws Exception {
+ service = new QueueDirectStatisticsService(requestContextStack, deviceContext);
+ }
+
+ @Override
+ public void testBuildRequestBody() throws Exception {
+ final GetQueueStatisticsInput input = mock(GetQueueStatisticsInput.class);
+
+ when(input.getNode()).thenReturn(createNodeRef(NODE_ID));
+ when(input.getQueueId()).thenReturn(new QueueId(QUEUE_NO));
+ when(input.getNodeConnectorId()).thenReturn(new NodeConnectorId(NODE_ID + ":" + PORT_NO));
+
+ final MultipartRequestQueueCase body = (MultipartRequestQueueCase) service.buildRequestBody(input);
+ final MultipartRequestQueue queue = body.getMultipartRequestQueue();
+
+ assertEquals(PORT_NO, queue.getPortNo());
+ assertEquals(QUEUE_NO, queue.getQueueId());
+ }
+
+ @Override
+ public void testBuildReply() throws Exception {
+ final MultipartReply reply = mock(MultipartReply.class);
+ final MultipartReplyQueueCase queueCase = mock(MultipartReplyQueueCase.class);
+ final MultipartReplyQueue queue = mock(MultipartReplyQueue.class);
+ final QueueStats queueStat = mock(QueueStats.class);
+ final List<QueueStats> queueStats = Arrays.asList(queueStat);
+ final List<MultipartReply> input = Arrays.asList(reply);
+
+ when(queue.getQueueStats()).thenReturn(queueStats);
+ when(queueCase.getMultipartReplyQueue()).thenReturn(queue);
+ when(reply.getMultipartReplyBody()).thenReturn(queueCase);
+
+ when(queueStat.getPortNo()).thenReturn(PORT_NO);
+ when(queueStat.getQueueId()).thenReturn(QUEUE_NO);
+ when(queueStat.getTxBytes()).thenReturn(BigInteger.ONE);
+ when(queueStat.getTxErrors()).thenReturn(BigInteger.ONE);
+ when(queueStat.getTxPackets()).thenReturn(BigInteger.ONE);
+
+ final GetQueueStatisticsOutput output = service.buildReply(input, true);
+ assertTrue(output.getQueueIdAndStatisticsMap().size() > 0);
+
+ final QueueIdAndStatisticsMap map = output.getQueueIdAndStatisticsMap().get(0);
+ assertEquals(map.getQueueId().getValue(), QUEUE_NO);
+ assertEquals(map.getNodeConnectorId(), nodeConnectorId);
+ }
+
+ @Override
+ public void testStoreStatistics() throws Exception {
+ final QueueIdAndStatisticsMap map = mock(QueueIdAndStatisticsMap.class);
+ when(map.getQueueId()).thenReturn(new QueueId(QUEUE_NO));
+
+ final List<QueueIdAndStatisticsMap> maps = Arrays.asList(map);
+ final GetQueueStatisticsOutput output = mock(GetQueueStatisticsOutput.class);
+ when(output.getQueueIdAndStatisticsMap()).thenReturn(maps);
+
+ service.storeStatistics(output);
+ verify(deviceContext).writeToTransactionWithParentsSlow(eq(LogicalDatastoreType.OPERATIONAL), any(), any());
+ }
+}
\ No newline at end of file
public class MdSalRegistrationUtilsTest {
/**
- * Number of currently registrated services (can be changed) in {@link MdSalRegistrationUtils#registerServices
+ * Number of currently registrated services (can be changed)
* (RpcContext, DeviceContext)}
*/
- private static final int NUMBER_OF_RPC_SERVICE_REGISTRATION = 12;
+ private static final int NUMBER_OF_RPC_SERVICE_REGISTRATION = 13;
@Test
public void registerServiceTest() {