From: Tomas Slusny Date: Wed, 11 May 2016 17:03:01 +0000 (+0200) Subject: Bug 5692 - Direct statistics RPC X-Git-Tag: release/boron~249 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=af171bff73edeb84d8b2260da9d60ba6bb4337cb;p=openflowplugin.git Bug 5692 - Direct statistics RPC - Added new RPCs for direct gathering of statistics with optional flag of storing the statistics to DS/operational Change-Id: I9d94595f9fb4f5e93f22958c64dd6cf3d4c19bcc Signed-off-by: Tomas Slusny --- diff --git a/model/model-flow-statistics/src/main/yang/opendaylight-direct-statistics.yang b/model/model-flow-statistics/src/main/yang/opendaylight-direct-statistics.yang new file mode 100644 index 0000000000..e4037a4f85 --- /dev/null +++ b/model/model-flow-statistics/src/main/yang/opendaylight-direct-statistics.yang @@ -0,0 +1,123 @@ +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; + } + } +} diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java index 35125b5421..b2c70f7053 100644 --- a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java +++ b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java @@ -138,6 +138,7 @@ public interface DeviceContext extends AutoCloseable, * @return sync. future for Slave and MD-SAL completition for Master */ ListenableFuture shuttingDownDataStoreTransactions(); + /** * Method provides current devices connection context. * diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/TxFacade.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/TxFacade.java index 6a982b1e68..e8a8ccb904 100644 --- a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/TxFacade.java +++ b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/TxFacade.java @@ -24,6 +24,13 @@ public interface TxFacade { void writeToTransaction(final LogicalDatastoreType store, final InstanceIdentifier 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. + */ + void writeToTransactionWithParentsSlow(final LogicalDatastoreType store, final InstanceIdentifier path, + final T data) throws Exception; + /** * Method creates delete operation for provided path in underlying transaction chain. */ diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java index d8e924a953..1d82ea0f2f 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java @@ -333,7 +333,12 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi @Override public void writeToTransaction(final LogicalDatastoreType store, final InstanceIdentifier path, final T data) throws Exception { - transactionChainManager.writeToTransaction(store, path, data); + transactionChainManager.writeToTransaction(store, path, data, false); + } + + @Override + public void writeToTransactionWithParentsSlow(LogicalDatastoreType store, InstanceIdentifier path, T data) throws Exception { + transactionChainManager.writeToTransaction(store, path, data, true); } @Override diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/TransactionChainManager.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/TransactionChainManager.java index 34b766f880..d85dab8f59 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/TransactionChainManager.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/TransactionChainManager.java @@ -215,11 +215,13 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable } void writeToTransaction(final LogicalDatastoreType store, - final InstanceIdentifier path, final T data) throws Exception { + final InstanceIdentifier 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."); diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/FlowsInTableService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/FlowsInTableService.java index 1d812694de..f063b2ef51 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/FlowsInTableService.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/FlowsInTableService.java @@ -40,7 +40,12 @@ public final class FlowsInTableService extends AbstractCompatibleStatService the input type parameter + * @param the output type parameter + */ +public abstract class AbstractDirectStatisticsService extends AbstractMultipartService { + + private final Function>, RpcResult> resultTransformFunction = + new Function>, RpcResult>() { + @Nullable + @Override + public RpcResult apply(@Nullable RpcResult> input) { + Preconditions.checkNotNull(input); + final O reply = buildReply(input.getResult(), input.isSuccessful()); + return RpcResultBuilder.success(reply).build(); + } + }; + + private final AsyncFunction, RpcResult> resultStoreFunction = + new AsyncFunction, RpcResult>() { + @Nullable + @Override + public ListenableFuture> apply(@Nullable RpcResult 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> handleAndReply(final I input) { + final ListenableFuture>> rpcReply = handleServiceCall(input); + ListenableFuture> 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 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; +} diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/FlowDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/FlowDirectStatisticsService.java new file mode 100644 index 0000000000..72066b0395 --- /dev/null +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/FlowDirectStatisticsService.java @@ -0,0 +1,167 @@ +/* + * 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 { + 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 input, boolean success) { + final List statsList = new ArrayList<>(); + + if (success) { + for (final MultipartReply mpReply : input) { + final MultipartReplyFlowCase caseBody = (MultipartReplyFlowCase) mpReply.getMultipartReplyBody(); + final MultipartReplyFlow replyBody = caseBody.getMultipartReplyFlow(); + + final List 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 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 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); + } +} diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/GroupDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/GroupDirectStatisticsService.java new file mode 100644 index 0000000000..b7c650a03a --- /dev/null +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/GroupDirectStatisticsService.java @@ -0,0 +1,102 @@ +/* + * 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 { + 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 input, boolean success) { + final List 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 nodePath = getDeviceContext() + .getDeviceState().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class); + + for (final GroupStats groupStatistics : output.getGroupStats()) { + final InstanceIdentifier 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); + } + } +} diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/MeterDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/MeterDirectStatisticsService.java new file mode 100644 index 0000000000..da6475ec5c --- /dev/null +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/MeterDirectStatisticsService.java @@ -0,0 +1,102 @@ +/* + * 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 { + 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 input, boolean success) { + final List 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 nodePath = getDeviceContext() + .getDeviceState().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class); + + for (final MeterStats meterStatistics : output.getMeterStats()) { + final InstanceIdentifier 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); + } + } +} diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/NodeConnectorDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/NodeConnectorDirectStatisticsService.java new file mode 100644 index 0000000000..6f6f496cbe --- /dev/null +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/NodeConnectorDirectStatisticsService.java @@ -0,0 +1,145 @@ +/* + * 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 { + /** + * 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 input, boolean success) { + final List 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 nodePath = getDeviceContext().getDeviceState().getNodeInstanceIdentifier(); + + for (final NodeConnectorStatisticsAndPortNumberMap nodeConnectorStatistics : output.getNodeConnectorStatisticsAndPortNumberMap()) { + final InstanceIdentifier 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); + } + } +} diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/OpendaylightDirectStatisticsServiceImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/OpendaylightDirectStatisticsServiceImpl.java new file mode 100644 index 0000000000..b96ae21ec1 --- /dev/null +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/OpendaylightDirectStatisticsServiceImpl.java @@ -0,0 +1,107 @@ +/* + * 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> getGroupStatistics(GetGroupStatisticsInput input) { + final Optional service = provider.lookup(GroupDirectStatisticsService.class); + + if (!service.isPresent()) { + return missingImplementation(GroupDirectStatisticsService.class); + } + + return service.get().handleAndReply(input); + } + + @Override + public Future> getQueueStatistics(GetQueueStatisticsInput input) { + final Optional service = provider.lookup(QueueDirectStatisticsService.class); + + if (!service.isPresent()) { + return missingImplementation(QueueDirectStatisticsService.class); + } + + return service.get().handleAndReply(input); + } + + @Override + public Future> getFlowStatistics(GetFlowStatisticsInput input) { + final Optional service = provider.lookup(FlowDirectStatisticsService.class); + + if (!service.isPresent()) { + return missingImplementation(FlowDirectStatisticsService.class); + } + + return service.get().handleAndReply(input); + } + + @Override + public Future> getMeterStatistics(GetMeterStatisticsInput input) { + final Optional service = provider.lookup(MeterDirectStatisticsService.class); + + if (!service.isPresent()) { + return missingImplementation(MeterDirectStatisticsService.class); + } + + return service.get().handleAndReply(input); + } + + @Override + public Future> getNodeConnectorStatistics(GetNodeConnectorStatisticsInput input) { + final Optional service = provider.lookup(NodeConnectorDirectStatisticsService.class); + + if (!service.isPresent()) { + return missingImplementation(NodeConnectorDirectStatisticsService.class); + } + + return service.get().handleAndReply(input); + } + + private Future> missingImplementation(Class service) { + return RpcResultBuilder.failed().withError( + RpcError.ErrorType.APPLICATION, + String.format("No implementation found for direct statistics service %s.", service.getCanonicalName())) + .buildFuture(); + } +} diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/OpendaylightDirectStatisticsServiceProvider.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/OpendaylightDirectStatisticsServiceProvider.java new file mode 100644 index 0000000000..daecefb2fa --- /dev/null +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/OpendaylightDirectStatisticsServiceProvider.java @@ -0,0 +1,45 @@ +/* + * 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, AbstractDirectStatisticsService> services = new HashMap<>(); + + /** + * Register direct statistics service. + * + * @param type the service type + * @param service the service instance + */ + public void register(Class type, AbstractDirectStatisticsService service) { + if (services.containsKey(type)) return; + + services.put(type, service); + } + + /** + * Lookup direct statistics service. + * + * @param the type parameter + * @param type the service type + * @return the service instance + */ + public Optional lookup(Class type) { + if (!services.containsKey(type)) return Optional.empty(); + + return Optional.of(type.cast(services.get(type))); + } +} diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/QueueDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/QueueDirectStatisticsService.java new file mode 100644 index 0000000000..88f97dcbab --- /dev/null +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/QueueDirectStatisticsService.java @@ -0,0 +1,146 @@ +/* + * 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 { + /** + * 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 input, boolean success) { + final List 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 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 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 diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MdSalRegistrationUtils.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MdSalRegistrationUtils.java index 708410e69c..05806e9b9a 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MdSalRegistrationUtils.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MdSalRegistrationUtils.java @@ -37,6 +37,14 @@ import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightMete 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; @@ -102,6 +110,15 @@ public class MdSalRegistrationUtils { 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), @@ -152,6 +169,7 @@ public class MdSalRegistrationUtils { rpcContext.unregisterRpcServiceImplementation(SalFlatBatchService.class); // TODO: experimenter symmetric and multipart message services rpcContext.unregisterRpcServiceImplementation(SalExperimenterMessageService.class); + rpcContext.unregisterRpcServiceImplementation(OpendaylightDirectStatisticsService.class); } /** diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/TransactionChainManagerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/TransactionChainManagerTest.java index 2c7d0c263a..cd3a89bc38 100644 --- a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/TransactionChainManagerTest.java +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/TransactionChainManagerTest.java @@ -104,10 +104,10 @@ public class TransactionChainManagerTest { @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); } /** @@ -118,11 +118,11 @@ public class TransactionChainManagerTest { 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(); } @@ -133,11 +133,11 @@ public class TransactionChainManagerTest { @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(); } @@ -149,11 +149,11 @@ public class TransactionChainManagerTest { Mockito.when(writeTx.submit()).thenReturn(Futures.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(); } @@ -165,11 +165,11 @@ public class TransactionChainManagerTest { @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(); } @@ -212,12 +212,12 @@ public class TransactionChainManagerTest { public void testDeactivateTransactionChainManagerFailed() throws Exception { Mockito.when(writeTx.submit()).thenReturn(Futures.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(); } @@ -225,12 +225,12 @@ public class TransactionChainManagerTest { @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(); } diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractDirectStatisticsServiceTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractDirectStatisticsServiceTest.java new file mode 100644 index 0000000000..7263b980c7 --- /dev/null +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractDirectStatisticsServiceTest.java @@ -0,0 +1,122 @@ +/* + * 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 nodeInstanceIdentifier; + + protected static NodeRef createNodeRef(String nodeIdValue) { + InstanceIdentifier 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 diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/FlowDirectStatisticsServiceTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/FlowDirectStatisticsServiceTest.java new file mode 100644 index 0000000000..11b2b63c47 --- /dev/null +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/FlowDirectStatisticsServiceTest.java @@ -0,0 +1,107 @@ +/* + * 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 = Arrays.asList(flowStat); + final List 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 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 diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/GroupDirectStatisticsServiceTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/GroupDirectStatisticsServiceTest.java new file mode 100644 index 0000000000..e948929855 --- /dev/null +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/GroupDirectStatisticsServiceTest.java @@ -0,0 +1,94 @@ +/* + * 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 = Arrays.asList(groupStat); + final List 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 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 diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/MeterDirectStatisticsServiceTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/MeterDirectStatisticsServiceTest.java new file mode 100644 index 0000000000..7c837035be --- /dev/null +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/MeterDirectStatisticsServiceTest.java @@ -0,0 +1,94 @@ +/* + * 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 = Arrays.asList(meterStat); + final List 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 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 diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/NodeConnectorDirectStatisticsServiceTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/NodeConnectorDirectStatisticsServiceTest.java new file mode 100644 index 0000000000..9296347130 --- /dev/null +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/NodeConnectorDirectStatisticsServiceTest.java @@ -0,0 +1,102 @@ +/* + * 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 nodeConnectorStats = Arrays.asList(nodeConnectorStat); + final List 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 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 diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/OpendaylightDirectStatisticsServiceImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/OpendaylightDirectStatisticsServiceImplTest.java new file mode 100644 index 0000000000..c3a2c26a17 --- /dev/null +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/OpendaylightDirectStatisticsServiceImplTest.java @@ -0,0 +1,179 @@ +/* + * 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 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 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 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 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 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 diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/QueueDirectStatisticsServiceTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/QueueDirectStatisticsServiceTest.java new file mode 100644 index 0000000000..3df2f25f70 --- /dev/null +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/QueueDirectStatisticsServiceTest.java @@ -0,0 +1,99 @@ +/* + * 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 = Arrays.asList(queueStat); + final List 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 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 diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/MdSalRegistrationUtilsTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/MdSalRegistrationUtilsTest.java index 12842a3403..cf0149cd79 100644 --- a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/MdSalRegistrationUtilsTest.java +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/MdSalRegistrationUtilsTest.java @@ -32,10 +32,10 @@ import org.opendaylight.yangtools.yang.binding.RpcService; 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() {