[ovs-dev] [PATCH/RFC 7/7] dpif-netlink: add offloaded meter stats dump in dpif_netlink_meter_get_stats
Simon Horman
simon.horman at corigine.com
Wed Nov 10 16:28:58 UTC 2021
From: Tianyu Yuan <tianyu.yuan at corigine.com>
Since previous ovs meter only supported dumping meter stats in non-offload
datapath, the dpif_netlink_meter_transact_offloaded is introduced in
dpif_netlink_meter_get_stats, in order to ckech meter stats in offloaded
datapath through sending and receiving corresponding netlink message.
Using "ovs-ofctl meter-stats br0 [meter] -O openflow13" can check the stats
on OVS-Bridge br0. Shown stats(packet_in_count and byte_in_count) are
counted by summing states of offloaded and non-offloaded datapath.
Signed-off-by: Tianyu Yuan <tianyu.yuan at corigine.com>
Signed-off-by: Simon Horman <simon.horman at corigine.com>
---
lib/dpif-netlink.c | 136 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 133 insertions(+), 3 deletions(-)
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index aff78abcc..0765ceda3 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -32,6 +32,7 @@
#include <sys/epoll.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <linux/gen_stats.h>
#include "bitmap.h"
#include "dpif-netlink-rtnl.h"
@@ -4036,12 +4037,125 @@ dpif_netlink_meter_transact(struct ofpbuf *request, struct ofpbuf **replyp,
return 0;
}
+
+static const struct nl_policy tca_root_policy_[] = {
+ [TCA_ACT_TAB] = { .type = NL_A_NESTED, .optional = false },
+ [TCA_ROOT_COUNT] = { .type = NL_A_U32, .optional = true },
+};
+
+static const struct nl_policy act_policy_[] = {
+ [TCA_ACT_KIND] = { .type = NL_A_STRING, .optional = false, },
+ [TCA_ACT_COOKIE] = { .type = NL_A_UNSPEC, .optional = true, },
+ [TCA_ACT_OPTIONS] = { .type = NL_A_NESTED, .optional = true, },
+ [TCA_ACT_STATS] = { .type = NL_A_NESTED, .optional = true, },
+};
+
+static const struct nl_policy stats_policy[] = {
+ [TCA_STATS_BASIC] = { .type = NL_A_UNSPEC,
+ .min_len = sizeof(struct gnet_stats_basic),
+ .optional = false, },
+};
+
static const struct nl_policy police_policy[] = {
[TCA_POLICE_TBF] = { .type = NL_A_UNSPEC,
.min_len = sizeof(struct tc_police),
.optional = false, },
};
+static int
+dpif_netlink_meter_transact_offloaded(ofproto_meter_id meter_id,
+ struct ofpbuf request,
+ struct ofpbuf **reply)
+{
+ uint32_t index = METER_ID_TO_POLICY_INDEX(meter_id.uint32);
+ size_t total_offset, basic_offset;
+ struct tcamsg *tcamsg;
+ int prio = 0;
+
+ tcamsg = tc_act_make_request(RTM_GETACTION, NLM_F_REQUEST, &request);
+ if (!tcamsg) {
+ return ENODEV;
+ }
+ dpif_netlink_police_start_nested(&request, &prio, &total_offset,
+ &basic_offset);
+ nl_msg_put_u32(&request, TCA_ACT_INDEX, index);
+ dpif_netlink_police_end_nested(&request, &total_offset, &basic_offset);
+
+ return tc_transact(&request, reply);
+}
+
+static int
+dpif_netlink_meter_get_stats_offloaded(ofproto_meter_id meter_id,
+ struct ovs_flow_stats *stats)
+{
+ static struct nl_policy actions_orders_policy[ACT_MAX_NUM + 1] = {};
+ struct nlattr *action_root_attrs_temp[ARRAY_SIZE(tca_root_policy_)];
+ struct nlattr *actions_orders[ARRAY_SIZE(actions_orders_policy)];
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
+ struct nlattr *action_police_attrs[ARRAY_SIZE(act_policy_)];
+ const int max_size = ARRAY_SIZE(actions_orders_policy);
+ struct nlattr *stats_attrs[ARRAY_SIZE(stats_policy)];
+ const struct gnet_stats_basic *bs;
+ struct nlattr *act_stats;
+ struct ofpbuf request;
+ struct ofpbuf *reply;
+ int i, err;
+
+ err = dpif_netlink_meter_transact_offloaded(meter_id, request, &reply);
+ if (err) {
+ VLOG_ERR_RL(&rl, "failed to send get-action netlink msg : %d", err);
+ goto err_out;
+ }
+
+ /*parse reply from ofpbuf to *nlattr[] */
+ if (!nl_policy_parse(reply, NLMSG_HDRLEN + sizeof(struct tcamsg),
+ tca_root_policy_, action_root_attrs_temp,
+ ARRAY_SIZE(action_root_attrs_temp))) {
+ VLOG_ERR_RL(&rl, "failed to parse reply message");
+ err = EINVAL;
+ goto err_out;
+ }
+
+ for (i = 0; i < max_size; i++) {
+ actions_orders_policy[i].type = NL_A_NESTED;
+ actions_orders_policy[i].optional = true;
+ }
+
+ if (!nl_parse_nested(action_root_attrs_temp[TCA_ACT_TAB],
+ actions_orders_policy,
+ actions_orders, ACT_MAX_NUM + 1)) {
+ VLOG_ERR_RL(&rl, "failed to parse TCA_ACT_TAB");
+ err = EPROTO;
+ goto err_out;
+ }
+
+ if (!nl_parse_nested(actions_orders[1], act_policy_, action_police_attrs,
+ ARRAY_SIZE(act_policy_)) ) {
+ VLOG_ERR_RL(&rl, "failed to parse action when getting meter stats");
+ err = EPROTO;
+ goto err_out;
+ }
+
+ act_stats = action_police_attrs[TCA_ACT_STATS];
+
+ if (!nl_parse_nested(act_stats, stats_policy, stats_attrs,
+ ARRAY_SIZE(stats_policy))) {
+ VLOG_ERR_RL(&rl, "failed to parse action stats policy");
+ err = EPROTO;
+ goto err_out;
+ }
+
+ bs = nl_attr_get_unspec(stats_attrs[TCA_STATS_BASIC], sizeof *bs);
+ if (bs->packets) {
+ put_32aligned_u64(&stats->n_packets, bs->packets);
+ put_32aligned_u64(&stats->n_bytes, bs->bytes);
+ }
+
+err_out:
+ ofpbuf_delete(reply);
+ return err;
+}
+
static void
dpif_netlink_meter_get_features(const struct dpif *dpif_,
struct ofputil_meter_features *features)
@@ -4478,8 +4592,13 @@ dpif_netlink_meter_get_stats(const struct dpif *dpif_,
enum ovs_meter_cmd command)
{
struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
+ struct ovs_flow_stats stats_t;
+ struct ovs_flow_stats *stats_offload = &stats_t;
struct ofpbuf buf, *msg;
uint64_t stub[1024 / 8];
+ int error;
+
+ memset(&stats_t, 0, sizeof(struct ovs_flow_stats));
static const struct nl_policy ovs_meter_stats_policy[] = {
[OVS_METER_ATTR_ID] = { .type = NL_A_U32, .optional = true},
@@ -4493,9 +4612,9 @@ dpif_netlink_meter_get_stats(const struct dpif *dpif_,
nl_msg_put_u32(&buf, OVS_METER_ATTR_ID, meter_id.uint32);
- int error = dpif_netlink_meter_transact(&buf, &msg,
- ovs_meter_stats_policy, a,
- ARRAY_SIZE(ovs_meter_stats_policy));
+ error = dpif_netlink_meter_transact(&buf, &msg,
+ ovs_meter_stats_policy, a,
+ ARRAY_SIZE(ovs_meter_stats_policy));
if (error) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
VLOG_INFO_RL(&rl, "dpif_netlink_meter_transact %s failed",
@@ -4503,6 +4622,10 @@ dpif_netlink_meter_get_stats(const struct dpif *dpif_,
return error;
}
+ if (netdev_is_flow_api_enabled()) {
+ dpif_netlink_meter_get_stats_offloaded(meter_id, stats_offload);
+ }
+
if (stats
&& a[OVS_METER_ATTR_ID]
&& a[OVS_METER_ATTR_STATS]
@@ -4516,6 +4639,13 @@ dpif_netlink_meter_get_stats(const struct dpif *dpif_,
stats->packet_in_count = get_32aligned_u64(&stat->n_packets);
stats->byte_in_count = get_32aligned_u64(&stat->n_bytes);
+ if (netdev_is_flow_api_enabled()) {
+ stats->packet_in_count +=
+ get_32aligned_u64(&stats_offload->n_packets);
+ stats->byte_in_count +=
+ get_32aligned_u64(&stats_offload->n_bytes);
+ }
+
if (a[OVS_METER_ATTR_BANDS]) {
size_t n_bands = 0;
NL_NESTED_FOR_EACH (nla, left, a[OVS_METER_ATTR_BANDS]) {
--
2.20.1
More information about the dev
mailing list