From patchwork Fri Mar 9 18:23:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 35887 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id B60B3AAB5; Fri, 9 Mar 2018 19:24:39 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id 3A6CB6D85 for ; Fri, 9 Mar 2018 19:24:36 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 09 Mar 2018 10:24:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,446,1515484800"; d="scan'208";a="181382231" Received: from silpixa00381635.ir.intel.com (HELO silpixa00381635.ger.corp.intel.com) ([10.237.222.149]) by orsmga004.jf.intel.com with ESMTP; 09 Mar 2018 10:24:34 -0800 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com Date: Fri, 9 Mar 2018 18:23:57 +0000 Message-Id: <20180309182426.135278-9-jasvinder.singh@intel.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20180309182426.135278-1-jasvinder.singh@intel.com> References: <20180309182426.135278-1-jasvinder.singh@intel.com> Subject: [dpdk-dev] [PATCH 08/37] pipeline: add statistics read action X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add implementation of stats read action Signed-off-by: Cristian Dumitrescu --- lib/librte_pipeline/rte_pipeline_version.map | 1 + lib/librte_pipeline/rte_table_action.c | 112 ++++++++++++++++++++++++++- lib/librte_pipeline/rte_table_action.h | 78 +++++++++++++++++++ 3 files changed, 190 insertions(+), 1 deletion(-) diff --git a/lib/librte_pipeline/rte_pipeline_version.map b/lib/librte_pipeline/rte_pipeline_version.map index 9388585..8241efc 100644 --- a/lib/librte_pipeline/rte_pipeline_version.map +++ b/lib/librte_pipeline/rte_pipeline_version.map @@ -61,6 +61,7 @@ EXPERIMENTAL { rte_table_action_profile_free; rte_table_action_profile_freeze; rte_table_action_table_params_get; + rte_table_action_stats_read; rte_table_action_ttl_read; } DPDK_16.04; diff --git a/lib/librte_pipeline/rte_table_action.c b/lib/librte_pipeline/rte_table_action.c index 157af49..06d54df 100644 --- a/lib/librte_pipeline/rte_table_action.c +++ b/lib/librte_pipeline/rte_table_action.c @@ -916,6 +916,41 @@ pkt_ipv6_work_ttl(struct ipv6_hdr *ip, } /** + * RTE_TABLE_ACTION_STATS + */ +static int +stats_cfg_check(struct rte_table_action_stats_config *stats) +{ + if ((stats->n_packets_enabled == 0) && (stats->n_bytes_enabled == 0)) + return -EINVAL; + + return 0; +} + +struct stats_data { + uint64_t n_packets; + uint64_t n_bytes; +} __attribute__((__packed__)); + +static int +stats_apply(struct stats_data *data, + struct rte_table_action_stats_params *p) +{ + data->n_packets = p->n_packets; + data->n_bytes = p->n_bytes; + + return 0; +} + +static __rte_always_inline void +pkt_work_stats(struct stats_data *data, + uint16_t total_length) +{ + data->n_packets++; + data->n_bytes += total_length; +} + +/** * Action profile */ static int @@ -928,13 +963,13 @@ action_valid(enum rte_table_action_type action) case RTE_TABLE_ACTION_ENCAP: case RTE_TABLE_ACTION_NAT: case RTE_TABLE_ACTION_TTL: + case RTE_TABLE_ACTION_STATS: return 1; default: return 0; } } - #define RTE_TABLE_ACTION_MAX 64 struct ap_config { @@ -945,6 +980,7 @@ struct ap_config { struct rte_table_action_encap_config encap; struct rte_table_action_nat_config nat; struct rte_table_action_ttl_config ttl; + struct rte_table_action_stats_config stats; }; static size_t @@ -961,6 +997,8 @@ action_cfg_size(enum rte_table_action_type action) return sizeof(struct rte_table_action_nat_config); case RTE_TABLE_ACTION_TTL: return sizeof(struct rte_table_action_ttl_config); + case RTE_TABLE_ACTION_STATS: + return sizeof(struct rte_table_action_stats_config); default: return 0; } @@ -986,6 +1024,9 @@ action_cfg_get(struct ap_config *ap_config, case RTE_TABLE_ACTION_TTL: return &ap_config->ttl; + case RTE_TABLE_ACTION_STATS: + return &ap_config->stats; + default: return NULL; } @@ -1033,6 +1074,9 @@ action_data_size(enum rte_table_action_type action, case RTE_TABLE_ACTION_TTL: return sizeof(struct ttl_data); + case RTE_TABLE_ACTION_STATS: + return sizeof(struct stats_data); + default: return 0; } @@ -1123,6 +1167,10 @@ rte_table_action_profile_action_register(struct rte_table_action_profile *profil status = ttl_cfg_check(action_config); break; + case RTE_TABLE_ACTION_STATS: + status = stats_cfg_check(action_config); + break; + default: status = 0; break; @@ -1260,6 +1308,10 @@ rte_table_action_apply(struct rte_table_action *action, return ttl_apply(action_data, action_params); + case RTE_TABLE_ACTION_STATS: + return stats_apply(action_data, + action_params); + default: return -EINVAL; } @@ -1454,6 +1506,41 @@ rte_table_action_ttl_read(struct rte_table_action *action, return 0; } +int +rte_table_action_stats_read(struct rte_table_action *action, + void *data, + struct rte_table_action_stats_counters *stats, + int clear) +{ + struct stats_data *stats_data; + + /* Check input arguments */ + if ((action == NULL) || + ((action->cfg.action_mask & + (1LLU << RTE_TABLE_ACTION_STATS)) == 0) || + (data == NULL)) + return -EINVAL; + + stats_data = action_data_get(data, action, + RTE_TABLE_ACTION_STATS); + + /* Read */ + if (stats) { + stats->n_packets = stats_data->n_packets; + stats->n_bytes = stats_data->n_bytes; + stats->n_packets_valid = 1; + stats->n_bytes_valid = 1; + } + + /* Clear */ + if (clear) { + stats_data->n_packets = 0; + stats_data->n_bytes = 0; + } + + return 0; +} + static __rte_always_inline uint64_t pkt_work(struct rte_mbuf *mbuf, struct rte_pipeline_table_entry *table_entry, @@ -1537,6 +1624,13 @@ pkt_work(struct rte_mbuf *mbuf, drop_mask |= pkt_ipv6_work_ttl(ip, data); } + if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) { + void *data = + action_data_get(table_entry, action, RTE_TABLE_ACTION_STATS); + + pkt_work_stats(data, total_length); + } + return drop_mask; } @@ -1766,6 +1860,22 @@ pkt4_work(struct rte_mbuf **mbufs, } } + if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) { + void *data0 = + action_data_get(table_entry0, action, RTE_TABLE_ACTION_STATS); + void *data1 = + action_data_get(table_entry1, action, RTE_TABLE_ACTION_STATS); + void *data2 = + action_data_get(table_entry2, action, RTE_TABLE_ACTION_STATS); + void *data3 = + action_data_get(table_entry3, action, RTE_TABLE_ACTION_STATS); + + pkt_work_stats(data0, total_length0); + pkt_work_stats(data1, total_length1); + pkt_work_stats(data2, total_length2); + pkt_work_stats(data3, total_length3); + } + return drop_mask0 | (drop_mask1 << 1) | (drop_mask2 << 2) | diff --git a/lib/librte_pipeline/rte_table_action.h b/lib/librte_pipeline/rte_table_action.h index 57ac4f9..53b9866 100644 --- a/lib/librte_pipeline/rte_table_action.h +++ b/lib/librte_pipeline/rte_table_action.h @@ -83,6 +83,9 @@ enum rte_table_action_type { /** Time to Live (TTL) update. */ RTE_TABLE_ACTION_TTL, + + /** Statistics. */ + RTE_TABLE_ACTION_STATS, }; /** Common action configuration (per table action profile). */ @@ -489,6 +492,56 @@ struct rte_table_action_ttl_counters { }; /** + * RTE_TABLE_ACTION_STATS + */ +/** Stats action configuration (per table action profile). */ +struct rte_table_action_stats_config { + /** When non-zero, the *n_packets* stats counter is enabled, otherwise + * disabled. + * + * @see struct rte_table_action_stats_counters + */ + int n_packets_enabled; + + /** When non-zero, the *n_bytes* stats counter is enabled, otherwise + * disabled. + * + * @see struct rte_table_action_stats_counters + */ + int n_bytes_enabled; +}; + +/** Stats action parameters (per table rule). */ +struct rte_table_action_stats_params { + /** Initial value for the *n_packets* stats counter. Typically set to 0. + * + * @see struct rte_table_action_stats_counters + */ + uint64_t n_packets; + + /** Initial value for the *n_bytes* stats counter. Typically set to 0. + * + * @see struct rte_table_action_stats_counters + */ + uint64_t n_bytes; +}; + +/** Stats action counters (per table rule). */ +struct rte_table_action_stats_counters { + /** Number of packets. Valid only when *n_packets_valid* is non-zero. */ + uint64_t n_packets; + + /** Number of bytes. Valid only when *n_bytes_valid* is non-zero. */ + uint64_t n_bytes; + + /** When non-zero, the *n_packets* field is valid, otherwise invalid. */ + int n_packets_valid; + + /** When non-zero, the *n_bytes* field is valid, otherwise invalid. */ + int n_bytes_valid; +}; + +/** * Table action profile. */ struct rte_table_action_profile; @@ -737,6 +790,31 @@ rte_table_action_ttl_read(struct rte_table_action *action, struct rte_table_action_ttl_counters *stats, int clear); +/** + * Table action stats read. + * + * @param[in] action + * Handle to table action object (needs to be valid). + * @param[in] data + * Data byte array (typically table rule data) with stats action previously + * applied on it. + * @param[inout] stats + * When non-NULL, it points to the area where the stats counters read from + * *data* are saved. + * @param[in] clear + * When non-zero, the stats counters are cleared (i.e. set to zero), otherwise + * the counters are not modified. When the read operation is enabled (*stats* + * is non-NULL), the clear operation is performed after the read operation is + * completed. + * @return + * Zero on success, non-zero error code otherwise. + */ +int __rte_experimental +rte_table_action_stats_read(struct rte_table_action *action, + void *data, + struct rte_table_action_stats_counters *stats, + int clear); + #ifdef __cplusplus } #endif