Collect mega flow mask stats. ovs-dpctl show command can be used to
display them.

Signed-off-by: Andy Zhou <az...@nicira.com>

---
v1-v2:
        * remove get_dp_megaflow_stats(), extend get_dp_stats() instead
        * use __always_unused instead of GCC extensions
        * fix comments
        * fix the logic of counting n_mask_hit

---
 datapath/datapath.c         |   37 ++++++++++++++++++++++++++++++-------
 datapath/datapath.h         |    4 ++++
 datapath/flow_table.c       |   16 +++++++++++++++-
 datapath/flow_table.h       |    4 +++-
 include/linux/openvswitch.h |   15 ++++++++++++---
 5 files changed, 64 insertions(+), 12 deletions(-)

diff --git a/datapath/datapath.c b/datapath/datapath.c
index 9e6df12..9f4fe95 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -223,6 +223,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct 
sk_buff *skb)
        struct dp_stats_percpu *stats;
        struct sw_flow_key key;
        u64 *stats_counter;
+       u32 n_mask_hit;
        int error;
 
        stats = this_cpu_ptr(dp->stats_percpu);
@@ -235,7 +236,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct 
sk_buff *skb)
        }
 
        /* Look up flow. */
-       flow = ovs_flow_tbl_lookup(&dp->table, &key);
+       flow = ovs_flow_tbl_lookup(&dp->table, &key, &n_mask_hit);
        if (unlikely(!flow)) {
                struct dp_upcall_info upcall;
 
@@ -260,6 +261,7 @@ out:
        /* Update datapath statistics. */
        u64_stats_update_begin(&stats->sync);
        (*stats_counter)++;
+       stats->n_mask_hit += n_mask_hit;
        u64_stats_update_end(&stats->sync);
 }
 
@@ -566,13 +568,17 @@ static struct genl_ops dp_packet_genl_ops[] = {
        }
 };
 
-static void get_dp_stats(struct datapath *dp, struct ovs_dp_stats *stats)
+static void get_dp_stats(struct datapath *dp, struct ovs_dp_stats *stats,
+                        struct ovs_dp_megaflow_stats *mega_stats)
 {
        int i;
 
        stats->n_flows = ovs_flow_tbl_count(&dp->table);
+       mega_stats->n_masks = ovs_flow_tbl_num_masks(&dp->table);
 
        stats->n_hit = stats->n_missed = stats->n_lost = 0;
+       mega_stats->n_mask_hit = 0;
+
        for_each_possible_cpu(i) {
                const struct dp_stats_percpu *percpu_stats;
                struct dp_stats_percpu local_stats;
@@ -588,6 +594,7 @@ static void get_dp_stats(struct datapath *dp, struct 
ovs_dp_stats *stats)
                stats->n_hit += local_stats.n_hit;
                stats->n_missed += local_stats.n_missed;
                stats->n_lost += local_stats.n_lost;
+               mega_stats->n_mask_hit += local_stats.n_mask_hit;
        }
 }
 
@@ -746,6 +753,14 @@ static struct sk_buff *ovs_flow_cmd_build_info(struct 
sw_flow *flow,
        return skb;
 }
 
+static struct sw_flow *ovs_flow_tbl_lookup__(struct flow_table *tbl,
+                                             const struct sw_flow_key *key)
+{
+       u32 __always_unused n_mask_hit;
+
+       return ovs_flow_tbl_lookup(tbl, key, &n_mask_hit);
+}
+
 static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
 {
        struct nlattr **a = info->attrs;
@@ -796,7 +811,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
                goto err_unlock_ovs;
 
        /* Check if this is a duplicate flow */
-       flow = ovs_flow_tbl_lookup(&dp->table, &key);
+       flow = ovs_flow_tbl_lookup__(&dp->table, &key);
        if (!flow) {
                /* Bail out if we're not allowed to create a new flow. */
                error = -ENOENT;
@@ -908,7 +923,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct 
genl_info *info)
                goto unlock;
        }
 
-       flow = ovs_flow_tbl_lookup(&dp->table, &key);
+       flow = ovs_flow_tbl_lookup__(&dp->table, &key);
        if (!flow || !ovs_flow_cmp_unmasked_key(flow, &match)) {
                err = -ENOENT;
                goto unlock;
@@ -956,7 +971,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct 
genl_info *info)
        if (err)
                goto unlock;
 
-       flow = ovs_flow_tbl_lookup(&dp->table, &key);
+       flow = ovs_flow_tbl_lookup__(&dp->table, &key);
        if (!flow || !ovs_flow_cmp_unmasked_key(flow, &match)) {
                err = -ENOENT;
                goto unlock;
@@ -1070,6 +1085,7 @@ static size_t ovs_dp_cmd_msg_size(void)
 
        msgsize += nla_total_size(IFNAMSIZ);
        msgsize += nla_total_size(sizeof(struct ovs_dp_stats));
+       msgsize += nla_total_size(sizeof(struct ovs_dp_megaflow_stats));
 
        return msgsize;
 }
@@ -1079,6 +1095,7 @@ static int ovs_dp_cmd_fill_info(struct datapath *dp, 
struct sk_buff *skb,
 {
        struct ovs_header *ovs_header;
        struct ovs_dp_stats dp_stats;
+       struct ovs_dp_megaflow_stats dp_megaflow_stats;
        int err;
 
        ovs_header = genlmsg_put(skb, portid, seq, &dp_datapath_genl_family,
@@ -1094,8 +1111,14 @@ static int ovs_dp_cmd_fill_info(struct datapath *dp, 
struct sk_buff *skb,
        if (err)
                goto nla_put_failure;
 
-       get_dp_stats(dp, &dp_stats);
-       if (nla_put(skb, OVS_DP_ATTR_STATS, sizeof(struct ovs_dp_stats), 
&dp_stats))
+       get_dp_stats(dp, &dp_stats, &dp_megaflow_stats);
+       if (nla_put(skb, OVS_DP_ATTR_STATS, sizeof(struct ovs_dp_stats),
+                       &dp_stats))
+               goto nla_put_failure;
+
+       if (nla_put(skb, OVS_DP_ATTR_MEGAFLOW_STATS,
+                       sizeof(struct ovs_dp_megaflow_stats),
+                       &dp_megaflow_stats))
                goto nla_put_failure;
 
        return genlmsg_end(skb, ovs_header);
diff --git a/datapath/datapath.h b/datapath/datapath.h
index 64920de..879a830 100644
--- a/datapath/datapath.h
+++ b/datapath/datapath.h
@@ -48,11 +48,15 @@
  * @n_lost: Number of received packets that had no matching flow in the flow
  * table that could not be sent to userspace (normally due to an overflow in
  * one of the datapath's queues).
+ * @n_mask_hit: Number of masks looked up for flow match.
+ *   @n_mask_hit / (@n_hit + @n_missed)  will be the average masks looked
+ *   up per packet.
  */
 struct dp_stats_percpu {
        u64 n_hit;
        u64 n_missed;
        u64 n_lost;
+       u64 n_mask_hit;
        struct u64_stats_sync sync;
 };
 
diff --git a/datapath/flow_table.c b/datapath/flow_table.c
index 98eb809..b014d92 100644
--- a/datapath/flow_table.c
+++ b/datapath/flow_table.c
@@ -431,13 +431,16 @@ static struct sw_flow *masked_flow_lookup(struct 
table_instance *ti,
 }
 
 struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
-                                   const struct sw_flow_key *key)
+                                   const struct sw_flow_key *key,
+                                   u32 *n_mask_hit)
 {
        struct table_instance *ti = rcu_dereference(tbl->ti);
        struct sw_flow_mask *mask;
        struct sw_flow *flow;
 
+       *n_mask_hit = 0;
        list_for_each_entry_rcu(mask, &tbl->mask_list, list) {
+               (*n_mask_hit)++;
                flow = masked_flow_lookup(ti, key, mask);
                if (flow)  /* Found */
                        return flow;
@@ -445,6 +448,17 @@ struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
        return NULL;
 }
 
+int ovs_flow_tbl_num_masks(const struct flow_table *table)
+{
+       struct sw_flow_mask *mask;
+       int num = 0;
+
+       list_for_each_entry(mask, &table->mask_list, list)
+               num++;
+
+       return num;
+}
+
 static struct table_instance *table_instance_expand(struct table_instance *ti)
 {
        return table_instance_rehash(ti, ti->n_buckets * 2);
diff --git a/datapath/flow_table.h b/datapath/flow_table.h
index 4db5f78..fbe45d5 100644
--- a/datapath/flow_table.h
+++ b/datapath/flow_table.h
@@ -66,10 +66,12 @@ int ovs_flow_tbl_flush(struct flow_table *flow_table);
 int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
                        struct sw_flow_mask *mask);
 void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow);
+int  ovs_flow_tbl_num_masks(const struct flow_table *table);
 struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *table,
                                       u32 *bucket, u32 *idx);
 struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *,
-                                   const struct sw_flow_key *);
+                                   const struct sw_flow_key *,
+                                   u32 *n_mask_hit);
 
 bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
                               struct sw_flow_match *match);
diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
index 09c26b5..f7b2640 100644
--- a/include/linux/openvswitch.h
+++ b/include/linux/openvswitch.h
@@ -83,15 +83,18 @@ enum ovs_datapath_cmd {
  * not be sent.
  * @OVS_DP_ATTR_STATS: Statistics about packets that have passed through the
  * datapath.  Always present in notifications.
+ * @OVS_DP_ATTR_MEGAFLOW_STATS: Statistics about mega flow masks usage for the
+ * datapath. Always present in notifications.
  *
  * These attributes follow the &struct ovs_header within the Generic Netlink
  * payload for %OVS_DP_* commands.
  */
 enum ovs_datapath_attr {
        OVS_DP_ATTR_UNSPEC,
-       OVS_DP_ATTR_NAME,       /* name of dp_ifindex netdev */
-       OVS_DP_ATTR_UPCALL_PID, /* Netlink PID to receive upcalls */
-       OVS_DP_ATTR_STATS,      /* struct ovs_dp_stats */
+       OVS_DP_ATTR_NAME,               /* name of dp_ifindex netdev */
+       OVS_DP_ATTR_UPCALL_PID,         /* Netlink PID to receive upcalls */
+       OVS_DP_ATTR_STATS,              /* struct ovs_dp_stats */
+       OVS_DP_ATTR_MEGAFLOW_STATS,     /* struct ovs_dp_megaflow_stats */
        __OVS_DP_ATTR_MAX
 };
 
@@ -104,6 +107,12 @@ struct ovs_dp_stats {
        __u64 n_flows;           /* Number of flows present */
 };
 
+struct ovs_dp_megaflow_stats {
+       __u64 n_masks;           /* Number of masks for the datapath */
+       __u64 n_mask_hit;        /* Number of masks used for flow lookups. */
+       __u64 pad[2];            /* Pad for future expension */
+};
+
 struct ovs_vport_stats {
        __u64   rx_packets;             /* total packets received       */
        __u64   tx_packets;             /* total packets transmitted    */
-- 
1.7.9.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to