From patchwork Mon Jun 8 15:00:16 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Jastrzebski X-Patchwork-Id: 5308 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 1AD31C340; Mon, 8 Jun 2015 17:05:25 +0200 (CEST) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id 24CB3C32C for ; Mon, 8 Jun 2015 17:05:22 +0200 (CEST) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP; 08 Jun 2015 08:05:22 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.13,574,1427785200"; d="scan'208";a="743027866" Received: from unknown (HELO Sent) ([10.217.248.178]) by orsmga002.jf.intel.com with SMTP; 08 Jun 2015 08:05:19 -0700 Received: by Sent (sSMTP sendmail emulation); Mon, 08 Jun 2015 17:04:56 +0116 From: Michal Jastrzebski To: dev@dpdk.org Date: Mon, 8 Jun 2015 17:00:16 +0200 Message-Id: <1433775616-6896-26-git-send-email-michalx.k.jastrzebski@intel.com> X-Mailer: git-send-email 2.1.1 In-Reply-To: <1433775616-6896-1-git-send-email-michalx.k.jastrzebski@intel.com> References: <1433775616-6896-1-git-send-email-michalx.k.jastrzebski@intel.com> Subject: [dpdk-dev] [PATCH v4 1/1] pipeline: add statistics for librte_pipeline ports and tables X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Maciej Gajdzica This patch adds statistics collection for librte_pipeline. Those statistics ale disabled by default during build time. Signed-off-by: Pawel Wodkowski Acked-by: Cristian Dumitrescu --- config/common_bsdapp | 1 + config/common_linuxapp | 1 + lib/librte_pipeline/rte_pipeline.c | 185 +++++++++++++++++++++++++++++++++--- lib/librte_pipeline/rte_pipeline.h | 98 +++++++++++++++++++ 4 files changed, 274 insertions(+), 11 deletions(-) diff --git a/config/common_bsdapp b/config/common_bsdapp index 68d5110..4c20fe0 100644 --- a/config/common_bsdapp +++ b/config/common_bsdapp @@ -395,6 +395,7 @@ RTE_TABLE_STATS_COLLECT=n # Compile librte_pipeline # CONFIG_RTE_LIBRTE_PIPELINE=y +RTE_PIPELINE_STATS_COLLECT=n # # Compile librte_kni diff --git a/config/common_linuxapp b/config/common_linuxapp index 7e9b7fa..ca93abc 100644 --- a/config/common_linuxapp +++ b/config/common_linuxapp @@ -402,6 +402,7 @@ RTE_TABLE_STATS_COLLECT=n # Compile librte_pipeline # CONFIG_RTE_LIBRTE_PIPELINE=y +RTE_PIPELINE_STATS_COLLECT=y # # Compile librte_kni diff --git a/lib/librte_pipeline/rte_pipeline.c b/lib/librte_pipeline/rte_pipeline.c index 36d92c9..69bf003 100644 --- a/lib/librte_pipeline/rte_pipeline.c +++ b/lib/librte_pipeline/rte_pipeline.c @@ -48,6 +48,17 @@ #define RTE_TABLE_INVALID UINT32_MAX +#ifdef RTE_PIPELINE_STATS_COLLECT +#define RTE_PIPELINE_STATS_ADD(counter, val) \ + ({ (counter) += (val); }) + +#define RTE_PIPELINE_STATS_ADD_M(counter, mask) \ + ({ (counter) += __builtin_popcountll(mask); }) +#else +#define RTE_PIPELINE_STATS_ADD(counter, val) +#define RTE_PIPELINE_STATS_ADD_M(counter, mask) +#endif + struct rte_port_in { /* Input parameters */ struct rte_port_in_ops ops; @@ -63,6 +74,8 @@ struct rte_port_in { /* List of enabled ports */ struct rte_port_in *next; + + uint64_t n_pkts_dropped_by_ah; }; struct rte_port_out { @@ -74,6 +87,8 @@ struct rte_port_out { /* Handle to low-level port */ void *h_port; + + uint64_t n_pkts_dropped_by_ah; }; struct rte_table { @@ -90,6 +105,12 @@ struct rte_table { /* Handle to the low-level table object */ void *h_table; + + /* Stats for this table. */ + uint64_t n_pkts_dropped_by_lkp_hit_ah; + uint64_t n_pkts_dropped_by_lkp_miss_ah; + uint64_t n_pkts_dropped_lkp_hit; + uint64_t n_pkts_dropped_lkp_miss; }; #define RTE_PIPELINE_MAX_NAME_SZ 124 @@ -1040,6 +1061,8 @@ rte_pipeline_action_handler_port_bulk(struct rte_pipeline *p, port_out->f_action_bulk(p->pkts, &pkts_mask, port_out->arg_ah); p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= pkts_mask ^ mask; + RTE_PIPELINE_STATS_ADD_M(port_out->n_pkts_dropped_by_ah, + pkts_mask ^ mask); } /* Output port TX */ @@ -1071,6 +1094,9 @@ rte_pipeline_action_handler_port(struct rte_pipeline *p, uint64_t pkts_mask) p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= (pkt_mask ^ 1LLU) << i; + RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, + pkt_mask ^ 1LLU); + /* Output port TX */ if (pkt_mask != 0) port_out->ops.f_tx(port_out->h_port, @@ -1104,6 +1130,9 @@ rte_pipeline_action_handler_port(struct rte_pipeline *p, uint64_t pkts_mask) p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= (pkt_mask ^ 1LLU) << i; + RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, + pkt_mask ^ 1LLU); + /* Output port TX */ if (pkt_mask != 0) port_out->ops.f_tx(port_out->h_port, @@ -1140,6 +1169,9 @@ rte_pipeline_action_handler_port_meta(struct rte_pipeline *p, p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= (pkt_mask ^ 1LLU) << i; + RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, + pkt_mask ^ 1ULL); + /* Output port TX */ if (pkt_mask != 0) port_out->ops.f_tx(port_out->h_port, @@ -1174,6 +1206,9 @@ rte_pipeline_action_handler_port_meta(struct rte_pipeline *p, p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= (pkt_mask ^ 1LLU) << i; + RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, + pkt_mask ^ 1ULL); + /* Output port TX */ if (pkt_mask != 0) port_out->ops.f_tx(port_out->h_port, @@ -1232,10 +1267,10 @@ rte_pipeline_run(struct rte_pipeline *p) if (port_in->f_action != NULL) { uint64_t mask = pkts_mask; - port_in->f_action(p->pkts, n_pkts, &pkts_mask, - port_in->arg_ah); - p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= - pkts_mask ^ mask; + port_in->f_action(p->pkts, n_pkts, &pkts_mask, port_in->arg_ah); + mask ^= pkts_mask; + p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= mask; + RTE_PIPELINE_STATS_ADD_M(port_in->n_pkts_dropped_by_ah, mask); } /* Table */ @@ -1261,9 +1296,10 @@ rte_pipeline_run(struct rte_pipeline *p) table->f_action_miss(p->pkts, &lookup_miss_mask, default_entry, table->arg_ah); - p->action_mask0[ - RTE_PIPELINE_ACTION_DROP] |= - lookup_miss_mask ^ mask; + mask ^= lookup_miss_mask; + p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= mask; + RTE_PIPELINE_STATS_ADD_M( + table->n_pkts_dropped_by_lkp_miss_ah, mask); } /* Table reserved actions */ @@ -1277,6 +1313,10 @@ rte_pipeline_run(struct rte_pipeline *p) uint32_t pos = default_entry->action; p->action_mask0[pos] = lookup_miss_mask; + if (pos == RTE_PIPELINE_ACTION_DROP) { + RTE_PIPELINE_STATS_ADD_M(table->n_pkts_dropped_lkp_miss, + lookup_miss_mask); + } } } @@ -1289,9 +1329,10 @@ rte_pipeline_run(struct rte_pipeline *p) table->f_action_hit(p->pkts, &lookup_hit_mask, p->entries, table->arg_ah); - p->action_mask0[ - RTE_PIPELINE_ACTION_DROP] |= - lookup_hit_mask ^ mask; + mask ^= lookup_hit_mask; + p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= mask; + RTE_PIPELINE_STATS_ADD_M( + table->n_pkts_dropped_by_lkp_hit_ah, mask); } /* Table reserved actions */ @@ -1308,6 +1349,9 @@ rte_pipeline_run(struct rte_pipeline *p) p->action_mask0[RTE_PIPELINE_ACTION_TABLE] |= p->action_mask1[ RTE_PIPELINE_ACTION_TABLE]; + + RTE_PIPELINE_STATS_ADD_M(table->n_pkts_dropped_lkp_hit, + p->action_mask1[RTE_PIPELINE_ACTION_DROP]); } /* Prepare for next iteration */ @@ -1370,9 +1414,128 @@ rte_pipeline_port_out_packet_insert(struct rte_pipeline *p, if (pkt_mask != 0) /* Output port TX */ port_out->ops.f_tx(port_out->h_port, pkt); - else + else { rte_pktmbuf_free(pkt); + RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, 1); + } + } + + return 0; +} + +int rte_pipeline_port_in_stats_read(struct rte_pipeline *p, uint32_t port_id, + struct rte_pipeline_port_in_stats *stats, int clear) +{ + struct rte_port_in *port; + int retval; + + if (p == NULL) { + RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", + __func__); + return -EINVAL; + } + + if (port_id >= p->num_ports_in) { + RTE_LOG(ERR, PIPELINE, + "%s: port IN ID %u is out of range\n", + __func__, port_id); + return -EINVAL; + } + + port = &p->ports_in[port_id]; + + if (port->ops.f_stats != NULL) { + retval = port->ops.f_stats(port->h_port, &stats->stats, clear); + if (retval) + return retval; + } else if (stats != NULL) + memset(&stats->stats, 0, sizeof(stats->stats)); + + if (stats != NULL) + stats->n_pkts_dropped_by_ah = port->n_pkts_dropped_by_ah; + + if (clear != 0) + port->n_pkts_dropped_by_ah = 0; + + return 0; +} + +int rte_pipeline_port_out_stats_read(struct rte_pipeline *p, uint32_t port_id, + struct rte_pipeline_port_out_stats *stats, int clear) +{ + struct rte_port_out *port; + int retval; + + if (p == NULL) { + RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", __func__); + return -EINVAL; + } + + if (port_id >= p->num_ports_out) { + RTE_LOG(ERR, PIPELINE, + "%s: port OUT ID %u is out of range\n", __func__, port_id); + return -EINVAL; + } + + port = &p->ports_out[port_id]; + if (port->ops.f_stats != NULL) { + retval = port->ops.f_stats(port->h_port, &stats->stats, clear); + if (retval != 0) + return retval; + } else if (stats != NULL) + memset(&stats->stats, 0, sizeof(stats->stats)); + + if (stats != NULL) + stats->n_pkts_dropped_by_ah = port->n_pkts_dropped_by_ah; + + if (clear != 0) + port->n_pkts_dropped_by_ah = 0; + + return 0; +} + +int rte_pipeline_table_stats_read(struct rte_pipeline *p, uint32_t table_id, + struct rte_pipeline_table_stats *stats, int clear) +{ + struct rte_table *table; + int retval; + + if (p == NULL) { + RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", + __func__); + return -EINVAL; + } + + if (table_id >= p->num_tables) { + RTE_LOG(ERR, PIPELINE, + "%s: table %u is out of range\n", __func__, table_id); + return -EINVAL; + } + + table = &p->tables[table_id]; + if (table->ops.f_stats != NULL) { + retval = table->ops.f_stats(table->h_table, &stats->stats, clear); + if (retval != 0) + return retval; + } else if (stats != NULL) + memset(&stats->stats, 0, sizeof(stats->stats)); + + if (stats != NULL) { + stats->n_pkts_dropped_by_lkp_hit_ah = + table->n_pkts_dropped_by_lkp_hit_ah; + stats->n_pkts_dropped_by_lkp_miss_ah = + table->n_pkts_dropped_by_lkp_miss_ah; + stats->n_pkts_dropped_lkp_hit = table->n_pkts_dropped_lkp_hit; + stats->n_pkts_dropped_lkp_miss = table->n_pkts_dropped_lkp_miss; + } + + if (clear != 0) { + table->n_pkts_dropped_by_lkp_hit_ah = 0; + table->n_pkts_dropped_by_lkp_miss_ah = 0; + table->n_pkts_dropped_lkp_hit = 0; + table->n_pkts_dropped_lkp_miss = 0; } return 0; } + diff --git a/lib/librte_pipeline/rte_pipeline.h b/lib/librte_pipeline/rte_pipeline.h index 145fc06..59e0710 100644 --- a/lib/librte_pipeline/rte_pipeline.h +++ b/lib/librte_pipeline/rte_pipeline.h @@ -112,6 +112,45 @@ struct rte_pipeline_params { uint32_t offset_port_id; }; +/** Pipeline port in stats. */ +struct rte_pipeline_port_in_stats { + /** Port in stats. */ + struct rte_port_in_stats stats; + + /** Number of packets dropped by action handler. */ + uint64_t n_pkts_dropped_by_ah; + +}; + +/** Pipeline port out stats. */ +struct rte_pipeline_port_out_stats { + /** Port out stats. */ + struct rte_port_out_stats stats; + + /** Number of packets dropped by action handler. */ + uint64_t n_pkts_dropped_by_ah; +}; + +/** Pipeline table stats. */ +struct rte_pipeline_table_stats { + /** Table stats. */ + struct rte_table_stats stats; + + /** Number of packets dropped by lookup hit action handler. */ + uint64_t n_pkts_dropped_by_lkp_hit_ah; + + /** Number of packets dropped by lookup miss action handler. */ + uint64_t n_pkts_dropped_by_lkp_miss_ah; + + /** Number of packets dropped by pipeline in behalf of this table based on + * on action specified in table entry. */ + uint64_t n_pkts_dropped_lkp_hit; + + /** Number of packets dropped by pipeline in behalf of this table based on + * on action specified in table entry. */ + uint64_t n_pkts_dropped_lkp_miss; +}; + /** * Pipeline create * @@ -426,6 +465,26 @@ int rte_pipeline_table_entry_delete(struct rte_pipeline *p, int *key_found, struct rte_pipeline_table_entry *entry); +/** + * Read pipeline table stats. + * + * This function reads table statistics identified by *table_id* of given + * pipeline *p*. + * + * @param p + * Handle to pipeline instance. + * @param table_id + * Port ID what stats will be returned. + * @param stats + * Statistics buffer. + * @param clear + * If not 0 clear stats after reading. + * @return + * 0 on success, error code otherwise + */ +int rte_pipeline_table_stats_read(struct rte_pipeline *p, uint32_t table_id, + struct rte_pipeline_table_stats *stats, int clear); + /* * Port IN * @@ -540,6 +599,26 @@ int rte_pipeline_port_in_enable(struct rte_pipeline *p, int rte_pipeline_port_in_disable(struct rte_pipeline *p, uint32_t port_id); +/** + * Read pipeline port in stats. + * + * This function reads port in statistics identified by *port_id* of given + * pipeline *p*. + * + * @param p + * Handle to pipeline instance. + * @param port_id + * Port ID what stats will be returned. + * @param stats + * Statistics buffer. + * @param clear + * If not 0 clear stats after reading. + * @return + * 0 on success, error code otherwise + */ +int rte_pipeline_port_in_stats_read(struct rte_pipeline *p, uint32_t port_id, + struct rte_pipeline_port_in_stats *stats, int clear); + /* * Port OUT * @@ -658,6 +737,25 @@ int rte_pipeline_port_out_packet_insert(struct rte_pipeline *p, uint32_t port_id, struct rte_mbuf *pkt); +/** + * Read pipeline port out stats. + * + * This function reads port out statistics identified by *port_id* of given + * pipeline *p*. + * + * @param p + * Handle to pipeline instance. + * @param port_id + * Port ID what stats will be returned. + * @param stats + * Statistics buffer. + * @param clear + * If not 0 clear stats after reading. + * @return + * 0 on success, error code otherwise + */ +int rte_pipeline_port_out_stats_read(struct rte_pipeline *p, uint32_t port_id, + struct rte_pipeline_port_out_stats *stats, int clear); #ifdef __cplusplus } #endif