From patchwork Thu Aug 4 16:58:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 114631 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 5085DA00C4; Thu, 4 Aug 2022 19:00:06 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 223BB42C3C; Thu, 4 Aug 2022 18:59:04 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mails.dpdk.org (Postfix) with ESMTP id BF94D42C07 for ; Thu, 4 Aug 2022 18:58:58 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1659632338; x=1691168338; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=aSGoQDo0ZaSICL8ssWK4ejiXpJSJjBRJMT0Tiwv2XJk=; b=juBeYpaTikAz1R9RFUETF2A75XDQ9XaQz9kgdYwxUsxpA6rXWvqzmlVN gSaRS+yTFO0vz5WqjkEIV1RzYlyjuguOdfLW4xzsUC9fV65R+2Ua52VbD 8UAYBEPEhb8jGCPxo5fvb8veTJjZxkikSXPANOtKilkVkgT9n409v4uWo RAfZku+pPD18XUDyHxr9KSPf1RljL4uXJP9gyTyaK8s9A5+lsM8KbSxuB t7HGqE6sPMn4js4ENUmEkKLYxJnfFa+H6tHIVwohiRPBgIGY15bHNgHF4 mhsT5nC1VPjLgMTlJSwK61N3mKGH30IIGY6puUxSZHd2UnOHNxLEaDt2H g==; X-IronPort-AV: E=McAfee;i="6400,9594,10429"; a="290000128" X-IronPort-AV: E=Sophos;i="5.93,216,1654585200"; d="scan'208";a="290000128" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Aug 2022 09:58:58 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.93,216,1654585200"; d="scan'208";a="636163138" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.223.157]) by orsmga001.jf.intel.com with ESMTP; 04 Aug 2022 09:58:53 -0700 From: Cristian Dumitrescu To: dev@dpdk.org Cc: jasvinder.singh@intel.com, yogesh.jangra@intel.com Subject: [PATCH 07/21] net/softnic: replace the legacy pipeline with the SWX pipeline Date: Thu, 4 Aug 2022 16:58:25 +0000 Message-Id: <20220804165839.1074817-8-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220804165839.1074817-1-cristian.dumitrescu@intel.com> References: <20220804165839.1074817-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Replace the legacy pipeline support with support for the SWX pipeline. Signed-off-by: Cristian Dumitrescu Signed-off-by: Yogesh Jangra --- drivers/net/softnic/meson.build | 1 - drivers/net/softnic/rte_eth_softnic.c | 6 - drivers/net/softnic/rte_eth_softnic_action.c | 423 --- drivers/net/softnic/rte_eth_softnic_cli.c | 16 +- .../net/softnic/rte_eth_softnic_internals.h | 502 +--- .../net/softnic/rte_eth_softnic_pipeline.c | 988 +------ drivers/net/softnic/rte_eth_softnic_thread.c | 2594 +---------------- 7 files changed, 216 insertions(+), 4314 deletions(-) delete mode 100644 drivers/net/softnic/rte_eth_softnic_action.c diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build index 91f1f3220f..f0cfc6dc17 100644 --- a/drivers/net/softnic/meson.build +++ b/drivers/net/softnic/meson.build @@ -10,7 +10,6 @@ sources = files( 'conn.c', 'parser.c', 'rte_eth_softnic.c', - 'rte_eth_softnic_action.c', 'rte_eth_softnic_cli.c', 'rte_eth_softnic_link.c', 'rte_eth_softnic_mempool.c', diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c index eb97ae7185..a940952c7a 100644 --- a/drivers/net/softnic/rte_eth_softnic.c +++ b/drivers/net/softnic/rte_eth_softnic.c @@ -160,8 +160,6 @@ pmd_dev_stop(struct rte_eth_dev *dev) /* Firmware */ softnic_pipeline_disable_all(p); softnic_pipeline_free(p); - softnic_table_action_profile_free(p); - softnic_port_in_action_profile_free(p); softnic_link_free(p); softnic_softnic_swq_free_keep_rxq_txq(p); softnic_mempool_free(p); @@ -180,8 +178,6 @@ pmd_free(struct pmd_internals *p) softnic_thread_free(p); softnic_pipeline_free(p); - softnic_table_action_profile_free(p); - softnic_port_in_action_profile_free(p); softnic_link_free(p); softnic_swq_free(p); softnic_mempool_free(p); @@ -261,8 +257,6 @@ pmd_init(struct pmd_params *params) softnic_mempool_init(p); softnic_swq_init(p); softnic_link_init(p); - softnic_port_in_action_profile_init(p); - softnic_table_action_profile_init(p); softnic_pipeline_init(p); status = softnic_thread_init(p); diff --git a/drivers/net/softnic/rte_eth_softnic_action.c b/drivers/net/softnic/rte_eth_softnic_action.c deleted file mode 100644 index 33be9552a6..0000000000 --- a/drivers/net/softnic/rte_eth_softnic_action.c +++ /dev/null @@ -1,423 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2018 Intel Corporation - */ - -#include -#include -#include - -#include -#include - -#include "rte_eth_softnic_internals.h" - -/** - * Input port - */ -int -softnic_port_in_action_profile_init(struct pmd_internals *p) -{ - TAILQ_INIT(&p->port_in_action_profile_list); - - return 0; -} - -void -softnic_port_in_action_profile_free(struct pmd_internals *p) -{ - for ( ; ; ) { - struct softnic_port_in_action_profile *profile; - - profile = TAILQ_FIRST(&p->port_in_action_profile_list); - if (profile == NULL) - break; - - TAILQ_REMOVE(&p->port_in_action_profile_list, profile, node); - free(profile); - } -} - -struct softnic_port_in_action_profile * -softnic_port_in_action_profile_find(struct pmd_internals *p, - const char *name) -{ - struct softnic_port_in_action_profile *profile; - - if (name == NULL) - return NULL; - - TAILQ_FOREACH(profile, &p->port_in_action_profile_list, node) - if (strcmp(profile->name, name) == 0) - return profile; - - return NULL; -} - -struct softnic_port_in_action_profile * -softnic_port_in_action_profile_create(struct pmd_internals *p, - const char *name, - struct softnic_port_in_action_profile_params *params) -{ - struct softnic_port_in_action_profile *profile; - struct rte_port_in_action_profile *ap; - int status; - - /* Check input params */ - if (name == NULL || - softnic_port_in_action_profile_find(p, name) || - params == NULL) - return NULL; - - if ((params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) && - params->lb.f_hash == NULL) { - switch (params->lb.key_size) { - case 8: - params->lb.f_hash = rte_table_hash_crc_key8; - break; - - case 16: - params->lb.f_hash = rte_table_hash_crc_key16; - break; - - case 24: - params->lb.f_hash = rte_table_hash_crc_key24; - break; - - case 32: - params->lb.f_hash = rte_table_hash_crc_key32; - break; - - case 40: - params->lb.f_hash = rte_table_hash_crc_key40; - break; - - case 48: - params->lb.f_hash = rte_table_hash_crc_key48; - break; - - case 56: - params->lb.f_hash = rte_table_hash_crc_key56; - break; - - case 64: - params->lb.f_hash = rte_table_hash_crc_key64; - break; - - default: - return NULL; - } - - params->lb.seed = 0; - } - - /* Resource */ - ap = rte_port_in_action_profile_create(0); - if (ap == NULL) - return NULL; - - if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_FLTR)) { - status = rte_port_in_action_profile_action_register(ap, - RTE_PORT_IN_ACTION_FLTR, - ¶ms->fltr); - - if (status) { - rte_port_in_action_profile_free(ap); - return NULL; - } - } - - if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) { - status = rte_port_in_action_profile_action_register(ap, - RTE_PORT_IN_ACTION_LB, - ¶ms->lb); - - if (status) { - rte_port_in_action_profile_free(ap); - return NULL; - } - } - - status = rte_port_in_action_profile_freeze(ap); - if (status) { - rte_port_in_action_profile_free(ap); - return NULL; - } - - /* Node allocation */ - profile = calloc(1, sizeof(struct softnic_port_in_action_profile)); - if (profile == NULL) { - rte_port_in_action_profile_free(ap); - return NULL; - } - - /* Node fill in */ - strlcpy(profile->name, name, sizeof(profile->name)); - memcpy(&profile->params, params, sizeof(*params)); - profile->ap = ap; - - /* Node add to list */ - TAILQ_INSERT_TAIL(&p->port_in_action_profile_list, profile, node); - - return profile; -} - -/** - * Table - */ -int -softnic_table_action_profile_init(struct pmd_internals *p) -{ - TAILQ_INIT(&p->table_action_profile_list); - - return 0; -} - -void -softnic_table_action_profile_free(struct pmd_internals *p) -{ - for ( ; ; ) { - struct softnic_table_action_profile *profile; - - profile = TAILQ_FIRST(&p->table_action_profile_list); - if (profile == NULL) - break; - - TAILQ_REMOVE(&p->table_action_profile_list, profile, node); - rte_table_action_profile_free(profile->ap); - free(profile); - } -} - -struct softnic_table_action_profile * -softnic_table_action_profile_find(struct pmd_internals *p, - const char *name) -{ - struct softnic_table_action_profile *profile; - - if (name == NULL) - return NULL; - - TAILQ_FOREACH(profile, &p->table_action_profile_list, node) - if (strcmp(profile->name, name) == 0) - return profile; - - return NULL; -} - -struct softnic_table_action_profile * -softnic_table_action_profile_create(struct pmd_internals *p, - const char *name, - struct softnic_table_action_profile_params *params) -{ - struct softnic_table_action_profile *profile; - struct rte_table_action_profile *ap; - int status; - - /* Check input params */ - if (name == NULL || - softnic_table_action_profile_find(p, name) || - params == NULL || - ((params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) == 0)) - return NULL; - - if ((params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) && - params->lb.f_hash == NULL) { - switch (params->lb.key_size) { - case 8: - params->lb.f_hash = rte_table_hash_crc_key8; - break; - - case 16: - params->lb.f_hash = rte_table_hash_crc_key16; - break; - - case 24: - params->lb.f_hash = rte_table_hash_crc_key24; - break; - - case 32: - params->lb.f_hash = rte_table_hash_crc_key32; - break; - - case 40: - params->lb.f_hash = rte_table_hash_crc_key40; - break; - - case 48: - params->lb.f_hash = rte_table_hash_crc_key48; - break; - - case 56: - params->lb.f_hash = rte_table_hash_crc_key56; - break; - - case 64: - params->lb.f_hash = rte_table_hash_crc_key64; - break; - - default: - return NULL; - } - - params->lb.seed = 0; - } - - /* Resource */ - ap = rte_table_action_profile_create(¶ms->common); - if (ap == NULL) - return NULL; - - if (params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { - status = rte_table_action_profile_action_register(ap, - RTE_TABLE_ACTION_FWD, - NULL); - - if (status) { - rte_table_action_profile_free(ap); - return NULL; - } - } - - if (params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) { - status = rte_table_action_profile_action_register(ap, - RTE_TABLE_ACTION_LB, - ¶ms->lb); - - if (status) { - rte_table_action_profile_free(ap); - return NULL; - } - } - - if (params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { - status = rte_table_action_profile_action_register(ap, - RTE_TABLE_ACTION_MTR, - ¶ms->mtr); - - if (status) { - rte_table_action_profile_free(ap); - return NULL; - } - } - - if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { - status = rte_table_action_profile_action_register(ap, - RTE_TABLE_ACTION_TM, - ¶ms->tm); - - if (status) { - rte_table_action_profile_free(ap); - return NULL; - } - } - - if (params->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { - status = rte_table_action_profile_action_register(ap, - RTE_TABLE_ACTION_ENCAP, - ¶ms->encap); - - if (status) { - rte_table_action_profile_free(ap); - return NULL; - } - } - - if (params->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { - status = rte_table_action_profile_action_register(ap, - RTE_TABLE_ACTION_NAT, - ¶ms->nat); - - if (status) { - rte_table_action_profile_free(ap); - return NULL; - } - } - - if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) { - status = rte_table_action_profile_action_register(ap, - RTE_TABLE_ACTION_TTL, - ¶ms->ttl); - - if (status) { - rte_table_action_profile_free(ap); - return NULL; - } - } - - if (params->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) { - status = rte_table_action_profile_action_register(ap, - RTE_TABLE_ACTION_STATS, - ¶ms->stats); - - if (status) { - rte_table_action_profile_free(ap); - return NULL; - } - } - if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) { - status = rte_table_action_profile_action_register(ap, - RTE_TABLE_ACTION_TIME, - NULL); - - if (status) { - rte_table_action_profile_free(ap); - return NULL; - } - } - - if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) { - status = rte_table_action_profile_action_register(ap, - RTE_TABLE_ACTION_TAG, - NULL); - - if (status) { - rte_table_action_profile_free(ap); - return NULL; - } - } - - if (params->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) { - status = rte_table_action_profile_action_register(ap, - RTE_TABLE_ACTION_DECAP, - NULL); - - if (status) { - rte_table_action_profile_free(ap); - return NULL; - } - } - - if (params->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) { - status = rte_table_action_profile_action_register(ap, - RTE_TABLE_ACTION_SYM_CRYPTO, - ¶ms->sym_crypto); - - if (status) { - rte_table_action_profile_free(ap); - return NULL; - } - } - - status = rte_table_action_profile_freeze(ap); - if (status) { - rte_table_action_profile_free(ap); - return NULL; - } - - /* Node allocation */ - profile = calloc(1, sizeof(struct softnic_table_action_profile)); - if (profile == NULL) { - rte_table_action_profile_free(ap); - return NULL; - } - - /* Node fill in */ - strlcpy(profile->name, name, sizeof(profile->name)); - memcpy(&profile->params, params, sizeof(*params)); - profile->ap = ap; - - /* Node add to list */ - TAILQ_INSERT_TAIL(&p->table_action_profile_list, profile, node); - - return profile; -} diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c index abe275ec83..2b00b65c6c 100644 --- a/drivers/net/softnic/rte_eth_softnic_cli.c +++ b/drivers/net/softnic/rte_eth_softnic_cli.c @@ -196,6 +196,7 @@ cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic, size_t out_size) { char *pipeline_name; + struct pipeline *p; uint32_t thread_id; int status; @@ -215,13 +216,18 @@ cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic, } pipeline_name = tokens[3]; + p = softnic_pipeline_find(softnic, pipeline_name); + if (!p) { + snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); + return; + } if (strcmp(tokens[4], "enable") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); return; } - status = softnic_thread_pipeline_enable(softnic, thread_id, pipeline_name); + status = softnic_thread_pipeline_enable(softnic, thread_id, p); if (status) { snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable"); return; @@ -239,6 +245,7 @@ cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic, size_t out_size) { char *pipeline_name; + struct pipeline *p; uint32_t thread_id; int status; @@ -258,13 +265,18 @@ cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic, } pipeline_name = tokens[3]; + p = softnic_pipeline_find(softnic, pipeline_name); + if (!p) { + snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); + return; + } if (strcmp(tokens[4], "disable") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); return; } - status = softnic_thread_pipeline_disable(softnic, thread_id, pipeline_name); + status = softnic_thread_pipeline_disable(softnic, thread_id, p); if (status) { snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline disable"); diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index df74c1fbdc..d817883a39 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -13,9 +13,8 @@ #include #include #include -#include -#include -#include +#include +#include #include #include @@ -89,207 +88,18 @@ struct softnic_link { TAILQ_HEAD(softnic_link_list, softnic_link); -/** - * Input port action - */ -struct softnic_port_in_action_profile_params { - uint64_t action_mask; - struct rte_port_in_action_fltr_config fltr; - struct rte_port_in_action_lb_config lb; -}; - -struct softnic_port_in_action_profile { - TAILQ_ENTRY(softnic_port_in_action_profile) node; - char name[NAME_SIZE]; - struct softnic_port_in_action_profile_params params; - struct rte_port_in_action_profile *ap; -}; - -TAILQ_HEAD(softnic_port_in_action_profile_list, softnic_port_in_action_profile); - -/** - * Table action - */ -struct softnic_table_action_profile_params { - uint64_t action_mask; - struct rte_table_action_common_config common; - struct rte_table_action_lb_config lb; - struct rte_table_action_mtr_config mtr; - struct rte_table_action_tm_config tm; - 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; - struct rte_table_action_sym_crypto_config sym_crypto; -}; - -struct softnic_table_action_profile { - TAILQ_ENTRY(softnic_table_action_profile) node; - char name[NAME_SIZE]; - struct softnic_table_action_profile_params params; - struct rte_table_action_profile *ap; -}; - -TAILQ_HEAD(softnic_table_action_profile_list, softnic_table_action_profile); - -struct softnic_table_meter_profile { - TAILQ_ENTRY(softnic_table_meter_profile) node; - uint32_t meter_profile_id; - struct rte_table_action_meter_profile profile; -}; - -TAILQ_HEAD(softnic_table_meter_profile_list, - softnic_table_meter_profile); - /** * Pipeline */ -struct pipeline_params { - uint32_t timer_period_ms; - uint32_t offset_port_id; -}; - -enum softnic_port_in_type { - PORT_IN_RXQ, - PORT_IN_SWQ, - PORT_IN_SOURCE, -}; - -struct softnic_port_in_params { - /* Read */ - enum softnic_port_in_type type; - char dev_name[NAME_SIZE]; - union { - struct { - uint16_t queue_id; - } rxq; - - struct { - const char *mempool_name; - const char *file_name; - uint32_t n_bytes_per_pkt; - } source; - }; - uint32_t burst_size; - - /* Action */ - char action_profile_name[NAME_SIZE]; -}; - -enum softnic_port_out_type { - PORT_OUT_TXQ, - PORT_OUT_SWQ, - PORT_OUT_SINK, -}; - -struct softnic_port_out_params { - enum softnic_port_out_type type; - char dev_name[NAME_SIZE]; - union { - struct { - uint16_t queue_id; - } txq; - - struct { - const char *file_name; - uint32_t max_n_pkts; - } sink; - }; - uint32_t burst_size; - int retry; - uint32_t n_retries; -}; - -enum softnic_table_type { - TABLE_ACL, - TABLE_ARRAY, - TABLE_HASH, - TABLE_LPM, - TABLE_STUB, -}; - -struct softnic_table_acl_params { - uint32_t n_rules; - uint32_t ip_header_offset; - int ip_version; -}; - -struct softnic_table_array_params { - uint32_t n_keys; - uint32_t key_offset; -}; - -#ifndef TABLE_RULE_MATCH_SIZE_MAX -#define TABLE_RULE_MATCH_SIZE_MAX 256 -#endif - -struct softnic_table_hash_params { - uint32_t n_keys; - uint32_t key_offset; - uint32_t key_size; - uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX]; - uint32_t n_buckets; - int extendable_bucket; -}; - -struct softnic_table_lpm_params { - uint32_t n_rules; - uint32_t key_offset; - uint32_t key_size; -}; - -struct softnic_table_params { - /* Match */ - enum softnic_table_type match_type; - union { - struct softnic_table_acl_params acl; - struct softnic_table_array_params array; - struct softnic_table_hash_params hash; - struct softnic_table_lpm_params lpm; - } match; - - /* Action */ - char action_profile_name[NAME_SIZE]; -}; - -struct softnic_port_in { - struct softnic_port_in_params params; - struct softnic_port_in_action_profile *ap; - struct rte_port_in_action *a; -}; - -struct softnic_port_out { - struct softnic_port_out_params params; -}; - -struct softnic_table { - struct softnic_table_params params; - struct softnic_table_action_profile *ap; - struct rte_table_action *a; - struct rte_table_action_dscp_table dscp_table; - struct softnic_table_meter_profile_list meter_profiles; -}; - struct pipeline { TAILQ_ENTRY(pipeline) node; char name[NAME_SIZE]; - struct rte_pipeline *p; - struct pipeline_params params; - struct softnic_port_in port_in[RTE_PIPELINE_PORT_IN_MAX]; - struct softnic_port_out port_out[RTE_PIPELINE_PORT_OUT_MAX]; - struct softnic_table table[RTE_PIPELINE_TABLE_MAX]; - uint32_t n_ports_in; - uint32_t n_ports_out; - uint32_t n_tables; - - struct rte_ring *msgq_req; - struct rte_ring *msgq_rsp; - uint32_t timer_period_ms; + struct rte_swx_pipeline *p; + struct rte_swx_ctl_pipeline *ctl; int enabled; uint32_t thread_id; - uint32_t cpu_id; }; TAILQ_HEAD(pipeline_list, pipeline); @@ -309,6 +119,15 @@ TAILQ_HEAD(pipeline_list, pipeline); #define THREAD_TIMER_PERIOD_MS 100 #endif +/* Pipeline instruction quanta: Needs to be big enough to do some meaningful + * work, but not too big to avoid starving any other pipelines mapped to the + * same thread. For a pipeline that executes 10 instructions per packet, a + * quanta of 1000 instructions equates to processing 100 packets. + */ +#ifndef PIPELINE_INSTR_QUANTA +#define PIPELINE_INSTR_QUANTA 1000 +#endif + /** * Main thread: data plane thread context */ @@ -322,37 +141,14 @@ struct softnic_thread { /** * Data plane threads: context */ -#ifndef TABLE_RULE_ACTION_SIZE_MAX -#define TABLE_RULE_ACTION_SIZE_MAX 2048 -#endif - -struct softnic_table_data { - struct rte_table_action *a; -}; - -struct pipeline_data { - struct rte_pipeline *p; - struct softnic_table_data table_data[RTE_PIPELINE_TABLE_MAX]; - uint32_t n_tables; - - struct rte_ring *msgq_req; - struct rte_ring *msgq_rsp; - uint64_t timer_period; /* Measured in CPU cycles. */ - uint64_t time_next; - - uint8_t buffer[TABLE_RULE_ACTION_SIZE_MAX]; -}; - struct softnic_thread_data { - struct rte_pipeline *p[THREAD_PIPELINES_MAX]; + struct rte_swx_pipeline *p[THREAD_PIPELINES_MAX]; uint32_t n_pipelines; - struct pipeline_data pipeline_data[THREAD_PIPELINES_MAX]; struct rte_ring *msgq_req; struct rte_ring *msgq_rsp; uint64_t timer_period; /* Measured in CPU cycles. */ uint64_t time_next; - uint64_t time_next_min; uint64_t iter; } __rte_cache_aligned; @@ -367,8 +163,6 @@ struct pmd_internals { struct softnic_mempool_list mempool_list; struct softnic_swq_list swq_list; struct softnic_link_list link_list; - struct softnic_port_in_action_profile_list port_in_action_profile_list; - struct softnic_table_action_profile_list table_action_profile_list; struct pipeline_list pipeline_list; struct softnic_thread thread[RTE_MAX_LCORE]; struct softnic_thread_data thread_data[RTE_MAX_LCORE]; @@ -447,42 +241,6 @@ softnic_link_create(struct pmd_internals *p, const char *name, struct softnic_link_params *params); -/** - * Input port action - */ -int -softnic_port_in_action_profile_init(struct pmd_internals *p); - -void -softnic_port_in_action_profile_free(struct pmd_internals *p); - -struct softnic_port_in_action_profile * -softnic_port_in_action_profile_find(struct pmd_internals *p, - const char *name); - -struct softnic_port_in_action_profile * -softnic_port_in_action_profile_create(struct pmd_internals *p, - const char *name, - struct softnic_port_in_action_profile_params *params); - -/** - * Table action - */ -int -softnic_table_action_profile_init(struct pmd_internals *p); - -void -softnic_table_action_profile_free(struct pmd_internals *p); - -struct softnic_table_action_profile * -softnic_table_action_profile_find(struct pmd_internals *p, - const char *name); - -struct softnic_table_action_profile * -softnic_table_action_profile_create(struct pmd_internals *p, - const char *name, - struct softnic_table_action_profile_params *params); - /** * Pipeline */ @@ -504,228 +262,9 @@ softnic_pipeline_find(struct pmd_internals *p, const char *name); struct pipeline * softnic_pipeline_create(struct pmd_internals *p, const char *name, - struct pipeline_params *params); - -int -softnic_pipeline_port_in_create(struct pmd_internals *p, - const char *pipeline_name, - struct softnic_port_in_params *params, - int enabled); - -int -softnic_pipeline_port_in_connect_to_table(struct pmd_internals *p, - const char *pipeline_name, - uint32_t port_id, - uint32_t table_id); - -int -softnic_pipeline_port_out_create(struct pmd_internals *p, - const char *pipeline_name, - struct softnic_port_out_params *params); - -int -softnic_pipeline_port_out_find(struct pmd_internals *softnic, - const char *pipeline_name, - const char *name, - uint32_t *port_id); - -int -softnic_pipeline_table_create(struct pmd_internals *p, - const char *pipeline_name, - struct softnic_table_params *params); - -struct softnic_table_meter_profile * -softnic_pipeline_table_meter_profile_find(struct softnic_table *table, - uint32_t meter_profile_id); - -struct softnic_table_rule_match_acl { - int ip_version; - - RTE_STD_C11 - union { - struct { - uint32_t sa; - uint32_t da; - } ipv4; - - struct { - uint8_t sa[16]; - uint8_t da[16]; - } ipv6; - }; - - uint32_t sa_depth; - uint32_t da_depth; - uint16_t sp0; - uint16_t sp1; - uint16_t dp0; - uint16_t dp1; - uint8_t proto; - uint8_t proto_mask; - uint32_t priority; -}; - -struct softnic_table_rule_match_array { - uint32_t pos; -}; - -struct softnic_table_rule_match_hash { - uint8_t key[TABLE_RULE_MATCH_SIZE_MAX]; -}; - -struct softnic_table_rule_match_lpm { - int ip_version; - - RTE_STD_C11 - union { - uint32_t ipv4; - uint8_t ipv6[16]; - }; - - uint8_t depth; -}; - -struct softnic_table_rule_match { - enum softnic_table_type match_type; - - union { - struct softnic_table_rule_match_acl acl; - struct softnic_table_rule_match_array array; - struct softnic_table_rule_match_hash hash; - struct softnic_table_rule_match_lpm lpm; - } match; -}; - -#ifndef SYM_CRYPTO_MAX_KEY_SIZE -#define SYM_CRYPTO_MAX_KEY_SIZE (256) -#endif -struct softnic_table_rule_action { - uint64_t action_mask; - struct rte_table_action_fwd_params fwd; - struct rte_table_action_lb_params lb; - struct rte_table_action_mtr_params mtr; - struct rte_table_action_tm_params tm; - struct rte_table_action_encap_params encap; - struct rte_table_action_nat_params nat; - struct rte_table_action_ttl_params ttl; - struct rte_table_action_stats_params stats; - struct rte_table_action_time_params time; - struct rte_table_action_tag_params tag; - struct rte_table_action_decap_params decap; - struct rte_table_action_sym_crypto_params sym_crypto; - uint8_t sym_crypto_key[SYM_CRYPTO_MAX_KEY_SIZE]; -}; - -int -softnic_pipeline_port_in_stats_read(struct pmd_internals *p, - const char *pipeline_name, - uint32_t port_id, - struct rte_pipeline_port_in_stats *stats, - int clear); - -int -softnic_pipeline_port_in_enable(struct pmd_internals *p, - const char *pipeline_name, - uint32_t port_id); - -int -softnic_pipeline_port_in_disable(struct pmd_internals *p, - const char *pipeline_name, - uint32_t port_id); - -int -softnic_pipeline_port_out_stats_read(struct pmd_internals *p, - const char *pipeline_name, - uint32_t port_id, - struct rte_pipeline_port_out_stats *stats, - int clear); - -int -softnic_pipeline_table_stats_read(struct pmd_internals *p, - const char *pipeline_name, - uint32_t table_id, - struct rte_pipeline_table_stats *stats, - int clear); - -int -softnic_pipeline_table_rule_add(struct pmd_internals *p, - const char *pipeline_name, - uint32_t table_id, - struct softnic_table_rule_match *match, - struct softnic_table_rule_action *action, - void **data); - -int -softnic_pipeline_table_rule_add_bulk(struct pmd_internals *p, - const char *pipeline_name, - uint32_t table_id, - struct softnic_table_rule_match *match, - struct softnic_table_rule_action *action, - void **data, - uint32_t *n_rules); - -int -softnic_pipeline_table_rule_add_default(struct pmd_internals *p, - const char *pipeline_name, - uint32_t table_id, - struct softnic_table_rule_action *action, - void **data); - -int -softnic_pipeline_table_rule_delete(struct pmd_internals *p, - const char *pipeline_name, - uint32_t table_id, - struct softnic_table_rule_match *match); - -int -softnic_pipeline_table_rule_delete_default(struct pmd_internals *p, - const char *pipeline_name, - uint32_t table_id); - -int -softnic_pipeline_table_rule_stats_read(struct pmd_internals *p, - const char *pipeline_name, - uint32_t table_id, - void *data, - struct rte_table_action_stats_counters *stats, - int clear); - -int -softnic_pipeline_table_mtr_profile_add(struct pmd_internals *p, - const char *pipeline_name, - uint32_t table_id, - uint32_t meter_profile_id, - struct rte_table_action_meter_profile *profile); - -int -softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *p, - const char *pipeline_name, - uint32_t table_id, - uint32_t meter_profile_id); - -int -softnic_pipeline_table_rule_mtr_read(struct pmd_internals *p, - const char *pipeline_name, - uint32_t table_id, - void *data, - uint32_t tc_mask, - struct rte_table_action_mtr_counters *stats, - int clear); - -int -softnic_pipeline_table_dscp_table_update(struct pmd_internals *p, - const char *pipeline_name, - uint32_t table_id, - uint64_t dscp_mask, - struct rte_table_action_dscp_table *dscp_table); - -int -softnic_pipeline_table_rule_ttl_read(struct pmd_internals *p, - const char *pipeline_name, - uint32_t table_id, - void *data, - struct rte_table_action_ttl_counters *stats, - int clear); + const char *lib_file_name, + const char *iospec_file_name, + int numa_node); /** * Thread @@ -739,12 +278,15 @@ softnic_thread_free(struct pmd_internals *p); int softnic_thread_pipeline_enable(struct pmd_internals *p, uint32_t thread_id, - const char *pipeline_name); + struct pipeline *pipeline); int softnic_thread_pipeline_disable(struct pmd_internals *p, uint32_t thread_id, - const char *pipeline_name); + struct pipeline *pipeline); + +void +softnic_thread_pipeline_disable_all(struct pmd_internals *p); /** * CLI diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c index 7a2828b785..76570b2cb3 100644 --- a/drivers/net/softnic/rte_eth_softnic_pipeline.c +++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c @@ -6,35 +6,10 @@ #include #include -#include -#include - #include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include #include "rte_eth_softnic_internals.h" -#ifndef PIPELINE_MSGQ_SIZE -#define PIPELINE_MSGQ_SIZE 64 -#endif - -#ifndef TABLE_LPM_NUMBER_TBL8 -#define TABLE_LPM_NUMBER_TBL8 256 -#endif - int softnic_pipeline_init(struct pmd_internals *p) { @@ -43,44 +18,19 @@ softnic_pipeline_init(struct pmd_internals *p) return 0; } -static void -softnic_pipeline_table_free(struct softnic_table *table) -{ - for ( ; ; ) { - struct softnic_table_meter_profile *mp; - - mp = TAILQ_FIRST(&table->meter_profiles); - if (mp == NULL) - break; - - TAILQ_REMOVE(&table->meter_profiles, mp, node); - free(mp); - } -} - void softnic_pipeline_free(struct pmd_internals *p) { for ( ; ; ) { struct pipeline *pipeline; - uint32_t table_id; pipeline = TAILQ_FIRST(&p->pipeline_list); if (pipeline == NULL) break; TAILQ_REMOVE(&p->pipeline_list, pipeline, node); - - for (table_id = 0; table_id < pipeline->n_tables; table_id++) { - struct softnic_table *table = - &pipeline->table[table_id]; - - softnic_pipeline_table_free(table); - } - - rte_ring_free(pipeline->msgq_req); - rte_ring_free(pipeline->msgq_rsp); - rte_pipeline_free(pipeline->p); + rte_swx_ctl_pipeline_free(pipeline->ctl); + rte_swx_pipeline_free(pipeline->p); free(pipeline); } } @@ -94,7 +44,7 @@ softnic_pipeline_disable_all(struct pmd_internals *p) if (pipeline->enabled) softnic_thread_pipeline_disable(p, pipeline->thread_id, - pipeline->name); + pipeline); } uint32_t @@ -126,850 +76,170 @@ softnic_pipeline_find(struct pmd_internals *p, return NULL; } -struct pipeline * -softnic_pipeline_create(struct pmd_internals *softnic, - const char *name, - struct pipeline_params *params) -{ - char resource_name[NAME_MAX]; - struct rte_pipeline_params pp; - struct pipeline *pipeline; - struct rte_pipeline *p; - struct rte_ring *msgq_req; - struct rte_ring *msgq_rsp; - - /* Check input params */ - if (name == NULL || - softnic_pipeline_find(softnic, name) || - params == NULL || - params->timer_period_ms == 0) - return NULL; - - /* Resource create */ - snprintf(resource_name, sizeof(resource_name), "%s-%s-REQ", - softnic->params.name, - name); - - msgq_req = rte_ring_create(resource_name, - PIPELINE_MSGQ_SIZE, - softnic->params.cpu_id, - RING_F_SP_ENQ | RING_F_SC_DEQ); - if (msgq_req == NULL) - return NULL; - - snprintf(resource_name, sizeof(resource_name), "%s-%s-RSP", - softnic->params.name, - name); - - msgq_rsp = rte_ring_create(resource_name, - PIPELINE_MSGQ_SIZE, - softnic->params.cpu_id, - RING_F_SP_ENQ | RING_F_SC_DEQ); - if (msgq_rsp == NULL) { - rte_ring_free(msgq_req); - return NULL; - } - - snprintf(resource_name, sizeof(resource_name), "%s_%s", - softnic->params.name, - name); - - pp.name = resource_name; - pp.socket_id = (int)softnic->params.cpu_id; - pp.offset_port_id = params->offset_port_id; - - p = rte_pipeline_create(&pp); - if (p == NULL) { - rte_ring_free(msgq_rsp); - rte_ring_free(msgq_req); - return NULL; - } - - /* Node allocation */ - pipeline = calloc(1, sizeof(struct pipeline)); - if (pipeline == NULL) { - rte_pipeline_free(p); - rte_ring_free(msgq_rsp); - rte_ring_free(msgq_req); - return NULL; - } - - /* Node fill in */ - strlcpy(pipeline->name, name, sizeof(pipeline->name)); - pipeline->p = p; - memcpy(&pipeline->params, params, sizeof(*params)); - pipeline->n_ports_in = 0; - pipeline->n_ports_out = 0; - pipeline->n_tables = 0; - pipeline->msgq_req = msgq_req; - pipeline->msgq_rsp = msgq_rsp; - pipeline->timer_period_ms = params->timer_period_ms; - pipeline->enabled = 0; - pipeline->cpu_id = softnic->params.cpu_id; - - /* Node add to list */ - TAILQ_INSERT_TAIL(&softnic->pipeline_list, pipeline, node); - - return pipeline; -} +#ifndef MAX_LINE_LENGTH +#define MAX_LINE_LENGTH 2048 +#endif -int -softnic_pipeline_port_in_create(struct pmd_internals *softnic, - const char *pipeline_name, - struct softnic_port_in_params *params, - int enabled) +/* The Soft NIC device internal resources such as mempools, rings or pipelines are globally visible, + * hence they need to have globally unique names. In order to apply the same configuration scripts + * unmodified to all the Soft NIC devices that instantiate the same program, the pipeline I/O + * configuration files are silently translated internally to prefix the name of the above resources + * with the Soft NIC device name, thus making the resource names globally unique. + */ +static int +iospec_translate(struct pmd_internals *softnic __rte_unused, + const char *file_in_name, + const char *file_out_name) { - struct rte_pipeline_port_in_params p; - - union { - struct rte_port_ethdev_reader_params ethdev; - struct rte_port_ring_reader_params ring; - struct rte_port_sched_reader_params sched; - struct rte_port_fd_reader_params fd; - struct rte_port_source_params source; - } pp; + FILE *fi = NULL, *fo = NULL; + char *line = NULL; + int status = 0; - struct pipeline *pipeline; - struct softnic_port_in *port_in; - struct softnic_port_in_action_profile *ap; - struct rte_port_in_action *action; - uint32_t port_id; - int status; - - memset(&p, 0, sizeof(p)); - memset(&pp, 0, sizeof(pp)); - - /* Check input params */ - if (pipeline_name == NULL || - params == NULL || - params->burst_size == 0 || - params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX) - return -1; - - pipeline = softnic_pipeline_find(softnic, pipeline_name); - if (pipeline == NULL) - return -1; - - ap = NULL; - if (strlen(params->action_profile_name)) { - ap = softnic_port_in_action_profile_find(softnic, - params->action_profile_name); - if (ap == NULL) - return -1; + /* File open. */ + fi = fopen(file_in_name, "r"); + fo = fopen(file_out_name, "w"); + if (!fi || !fo) { + status = -EIO; + goto free; } - switch (params->type) { - case PORT_IN_RXQ: - { - struct softnic_link *link; - - link = softnic_link_find(softnic, params->dev_name); - if (link == NULL) - return -1; - - if (params->rxq.queue_id >= link->n_rxq) - return -1; - - pp.ethdev.port_id = link->port_id; - pp.ethdev.queue_id = params->rxq.queue_id; - - p.ops = &rte_port_ethdev_reader_ops; - p.arg_create = &pp.ethdev; - break; + /* Memory allocation. */ + line = malloc(MAX_LINE_LENGTH); + if (!line) { + status = -ENOMEM; + goto free; } - case PORT_IN_SWQ: - { - struct softnic_swq *swq; - - swq = softnic_swq_find(softnic, params->dev_name); - if (swq == NULL) - return -1; - - pp.ring.ring = swq->r; - - p.ops = &rte_port_ring_reader_ops; - p.arg_create = &pp.ring; - break; - } + /* Read from the input file and write to the output file. */ + for ( ; ; ) { + char *ptr = line; + uint32_t n_tokens; + int flag = 0; - case PORT_IN_SOURCE: - { - struct softnic_mempool *mempool; + /* Read next line. */ + if (!fgets(line, MAX_LINE_LENGTH, fi)) + break; - mempool = softnic_mempool_find(softnic, params->source.mempool_name); - if (mempool == NULL) - return -1; + /* Parse the line into tokens. */ + for (n_tokens = 0; ; n_tokens++) { + char *token; - pp.source.mempool = mempool->m; - pp.source.file_name = params->source.file_name; - pp.source.n_bytes_per_pkt = params->source.n_bytes_per_pkt; + /* Read token. */ + token = strtok_r(ptr, " \f\n\r\t\v", &ptr); + if (!token) + break; - p.ops = &rte_port_source_ops; - p.arg_create = &pp.source; - break; - } + /* Handle comments. */ + if (!n_tokens && + ((token[0] == '#') || + (token[0] == ';') || + ((token[0] == '/') && (token[1] == '/')))) + break; - default: - return -1; - } + /* Process token. */ + if (flag) { + fprintf(fo, "%s_%s ", softnic->params.name, token); + flag = 0; + continue; + } - p.burst_size = params->burst_size; + if (!strcmp(token, "mempool") || + !strcmp(token, "ring")) { + flag = 1; + fprintf(fo, "%s ", token); + continue; + } - /* Resource create */ - action = NULL; - p.f_action = NULL; - p.arg_ah = NULL; - - if (ap) { - action = rte_port_in_action_create(ap->ap, - softnic->params.cpu_id); - if (action == NULL) - return -1; - - status = rte_port_in_action_params_get(action, - &p); - if (status) { - rte_port_in_action_free(action); - return -1; + /* Default action: write token. */ + fprintf(fo, "%s ", token); } - } - - status = rte_pipeline_port_in_create(pipeline->p, - &p, - &port_id); - if (status) { - rte_port_in_action_free(action); - return -1; - } - - if (enabled) - rte_pipeline_port_in_enable(pipeline->p, port_id); - - /* Pipeline */ - port_in = &pipeline->port_in[pipeline->n_ports_in]; - memcpy(&port_in->params, params, sizeof(*params)); - port_in->ap = ap; - port_in->a = action; - pipeline->n_ports_in++; - - return 0; -} - -int -softnic_pipeline_port_in_connect_to_table(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t port_id, - uint32_t table_id) -{ - struct pipeline *pipeline; - int status; - /* Check input params */ - if (pipeline_name == NULL) - return -1; + /* Handle empty or comment lines. */ + if (!n_tokens) + continue; - pipeline = softnic_pipeline_find(softnic, pipeline_name); - if (pipeline == NULL || - port_id >= pipeline->n_ports_in || - table_id >= pipeline->n_tables) - return -1; + /* Write newline. */ + fprintf(fo, "\n"); + } - /* Resource */ - status = rte_pipeline_port_in_connect_to_table(pipeline->p, - port_id, - table_id); +free: + /* Memory free. */ + free(line); + /* File close. */ + if (fi) + fclose(fi); + if (fo) + fclose(fo); return status; } -int -softnic_pipeline_port_out_create(struct pmd_internals *softnic, - const char *pipeline_name, - struct softnic_port_out_params *params) +struct pipeline * +softnic_pipeline_create(struct pmd_internals *softnic, + const char *name, + const char *lib_file_name, + const char *iospec_file_name, + int numa_node) { - struct rte_pipeline_port_out_params p; - - union { - struct rte_port_ethdev_writer_params ethdev; - struct rte_port_ring_writer_params ring; - struct rte_port_sched_writer_params sched; - struct rte_port_fd_writer_params fd; - struct rte_port_sink_params sink; - } pp; - - union { - struct rte_port_ethdev_writer_nodrop_params ethdev; - struct rte_port_ring_writer_nodrop_params ring; - struct rte_port_fd_writer_nodrop_params fd; - } pp_nodrop; - - struct pipeline *pipeline; - struct softnic_port_out *port_out; - uint32_t port_id; - int status; - - memset(&p, 0, sizeof(p)); - memset(&pp, 0, sizeof(pp)); - memset(&pp_nodrop, 0, sizeof(pp_nodrop)); + char global_name[NAME_MAX]; + FILE *iospec_file = NULL; + struct pipeline *pipeline = NULL; + struct rte_swx_pipeline *p = NULL; + struct rte_swx_ctl_pipeline *ctl = NULL; + int status = 0; /* Check input params */ - if (pipeline_name == NULL || - params == NULL || - params->burst_size == 0 || - params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX) - return -1; - - pipeline = softnic_pipeline_find(softnic, pipeline_name); - if (pipeline == NULL) - return -1; - - switch (params->type) { - case PORT_OUT_TXQ: - { - struct softnic_link *link; - - link = softnic_link_find(softnic, params->dev_name); - if (link == NULL) - return -1; - - if (params->txq.queue_id >= link->n_txq) - return -1; - - pp.ethdev.port_id = link->port_id; - pp.ethdev.queue_id = params->txq.queue_id; - pp.ethdev.tx_burst_sz = params->burst_size; - - pp_nodrop.ethdev.port_id = link->port_id; - pp_nodrop.ethdev.queue_id = params->txq.queue_id; - pp_nodrop.ethdev.tx_burst_sz = params->burst_size; - pp_nodrop.ethdev.n_retries = params->n_retries; - - if (params->retry == 0) { - p.ops = &rte_port_ethdev_writer_ops; - p.arg_create = &pp.ethdev; - } else { - p.ops = &rte_port_ethdev_writer_nodrop_ops; - p.arg_create = &pp_nodrop.ethdev; - } - break; - } - - case PORT_OUT_SWQ: - { - struct softnic_swq *swq; - - swq = softnic_swq_find(softnic, params->dev_name); - if (swq == NULL) - return -1; - - pp.ring.ring = swq->r; - pp.ring.tx_burst_sz = params->burst_size; - - pp_nodrop.ring.ring = swq->r; - pp_nodrop.ring.tx_burst_sz = params->burst_size; - pp_nodrop.ring.n_retries = params->n_retries; - - if (params->retry == 0) { - p.ops = &rte_port_ring_writer_ops; - p.arg_create = &pp.ring; - } else { - p.ops = &rte_port_ring_writer_nodrop_ops; - p.arg_create = &pp_nodrop.ring; - } - break; - } - - case PORT_OUT_SINK: - { - pp.sink.file_name = params->sink.file_name; - pp.sink.max_n_pkts = params->sink.max_n_pkts; - - p.ops = &rte_port_sink_ops; - p.arg_create = &pp.sink; - break; - } - - default: - return -1; - } - - p.f_action = NULL; - p.arg_ah = NULL; + if (!name || !name[0] || softnic_pipeline_find(softnic, name)) + goto error; /* Resource create */ - status = rte_pipeline_port_out_create(pipeline->p, - &p, - &port_id); + snprintf(global_name, sizeof(global_name), "/tmp/%s_%s.io", softnic->params.name, name); + status = iospec_translate(softnic, iospec_file_name, global_name); if (status) - return -1; - - /* Pipeline */ - port_out = &pipeline->port_out[pipeline->n_ports_out]; - memcpy(&port_out->params, params, sizeof(*params)); - pipeline->n_ports_out++; - - return 0; -} + goto error; -static const struct rte_acl_field_def table_acl_field_format_ipv4[] = { - /* Protocol */ - [0] = { - .type = RTE_ACL_FIELD_TYPE_BITMASK, - .size = sizeof(uint8_t), - .field_index = 0, - .input_index = 0, - .offset = offsetof(struct rte_ipv4_hdr, next_proto_id), - }, - - /* Source IP address (IPv4) */ - [1] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 1, - .input_index = 1, - .offset = offsetof(struct rte_ipv4_hdr, src_addr), - }, - - /* Destination IP address (IPv4) */ - [2] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 2, - .input_index = 2, - .offset = offsetof(struct rte_ipv4_hdr, dst_addr), - }, - - /* Source Port */ - [3] = { - .type = RTE_ACL_FIELD_TYPE_RANGE, - .size = sizeof(uint16_t), - .field_index = 3, - .input_index = 3, - .offset = sizeof(struct rte_ipv4_hdr) + - offsetof(struct rte_tcp_hdr, src_port), - }, - - /* Destination Port */ - [4] = { - .type = RTE_ACL_FIELD_TYPE_RANGE, - .size = sizeof(uint16_t), - .field_index = 4, - .input_index = 3, - .offset = sizeof(struct rte_ipv4_hdr) + - offsetof(struct rte_tcp_hdr, dst_port), - }, -}; - -static const struct rte_acl_field_def table_acl_field_format_ipv6[] = { - /* Protocol */ - [0] = { - .type = RTE_ACL_FIELD_TYPE_BITMASK, - .size = sizeof(uint8_t), - .field_index = 0, - .input_index = 0, - .offset = offsetof(struct rte_ipv6_hdr, proto), - }, - - /* Source IP address (IPv6) */ - [1] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 1, - .input_index = 1, - .offset = offsetof(struct rte_ipv6_hdr, src_addr[0]), - }, - - [2] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 2, - .input_index = 2, - .offset = offsetof(struct rte_ipv6_hdr, src_addr[4]), - }, - - [3] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 3, - .input_index = 3, - .offset = offsetof(struct rte_ipv6_hdr, src_addr[8]), - }, - - [4] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 4, - .input_index = 4, - .offset = offsetof(struct rte_ipv6_hdr, src_addr[12]), - }, - - /* Destination IP address (IPv6) */ - [5] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 5, - .input_index = 5, - .offset = offsetof(struct rte_ipv6_hdr, dst_addr[0]), - }, - - [6] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 6, - .input_index = 6, - .offset = offsetof(struct rte_ipv6_hdr, dst_addr[4]), - }, - - [7] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 7, - .input_index = 7, - .offset = offsetof(struct rte_ipv6_hdr, dst_addr[8]), - }, - - [8] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 8, - .input_index = 8, - .offset = offsetof(struct rte_ipv6_hdr, dst_addr[12]), - }, - - /* Source Port */ - [9] = { - .type = RTE_ACL_FIELD_TYPE_RANGE, - .size = sizeof(uint16_t), - .field_index = 9, - .input_index = 9, - .offset = sizeof(struct rte_ipv6_hdr) + - offsetof(struct rte_tcp_hdr, src_port), - }, - - /* Destination Port */ - [10] = { - .type = RTE_ACL_FIELD_TYPE_RANGE, - .size = sizeof(uint16_t), - .field_index = 10, - .input_index = 9, - .offset = sizeof(struct rte_ipv6_hdr) + - offsetof(struct rte_tcp_hdr, dst_port), - }, -}; - -int -softnic_pipeline_table_create(struct pmd_internals *softnic, - const char *pipeline_name, - struct softnic_table_params *params) -{ - char name[NAME_MAX]; - struct rte_pipeline_table_params p; - - union { - struct rte_table_acl_params acl; - struct rte_table_array_params array; - struct rte_table_hash_params hash; - struct rte_table_lpm_params lpm; - struct rte_table_lpm_ipv6_params lpm_ipv6; - } pp; - - struct pipeline *pipeline; - struct softnic_table *table; - struct softnic_table_action_profile *ap; - struct rte_table_action *action; - uint32_t table_id; - int status; + iospec_file = fopen(global_name, "r"); + if (!iospec_file) + goto error; - memset(&p, 0, sizeof(p)); - memset(&pp, 0, sizeof(pp)); - - /* Check input params */ - if (pipeline_name == NULL || - params == NULL) - return -1; - - pipeline = softnic_pipeline_find(softnic, pipeline_name); - if (pipeline == NULL || - pipeline->n_tables >= RTE_PIPELINE_TABLE_MAX) - return -1; - - ap = NULL; - if (strlen(params->action_profile_name)) { - ap = softnic_table_action_profile_find(softnic, - params->action_profile_name); - if (ap == NULL) - return -1; - } - - snprintf(name, NAME_MAX, "%s_%s_table%u", - softnic->params.name, pipeline_name, pipeline->n_tables); - - switch (params->match_type) { - case TABLE_ACL: - { - uint32_t ip_header_offset = params->match.acl.ip_header_offset - - (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM); - uint32_t i; - - if (params->match.acl.n_rules == 0) - return -1; - - pp.acl.name = name; - pp.acl.n_rules = params->match.acl.n_rules; - if (params->match.acl.ip_version) { - memcpy(&pp.acl.field_format, - &table_acl_field_format_ipv4, - sizeof(table_acl_field_format_ipv4)); - pp.acl.n_rule_fields = - RTE_DIM(table_acl_field_format_ipv4); - } else { - memcpy(&pp.acl.field_format, - &table_acl_field_format_ipv6, - sizeof(table_acl_field_format_ipv6)); - pp.acl.n_rule_fields = - RTE_DIM(table_acl_field_format_ipv6); - } - - for (i = 0; i < pp.acl.n_rule_fields; i++) - pp.acl.field_format[i].offset += ip_header_offset; - - p.ops = &rte_table_acl_ops; - p.arg_create = &pp.acl; - break; - } - - case TABLE_ARRAY: - { - if (params->match.array.n_keys == 0) - return -1; - - pp.array.n_entries = params->match.array.n_keys; - pp.array.offset = params->match.array.key_offset; - - p.ops = &rte_table_array_ops; - p.arg_create = &pp.array; - break; - } - - case TABLE_HASH: - { - struct rte_table_ops *ops; - rte_table_hash_op_hash f_hash; - - if (params->match.hash.n_keys == 0) - return -1; - - switch (params->match.hash.key_size) { - case 8: - f_hash = rte_table_hash_crc_key8; - break; - case 16: - f_hash = rte_table_hash_crc_key16; - break; - case 24: - f_hash = rte_table_hash_crc_key24; - break; - case 32: - f_hash = rte_table_hash_crc_key32; - break; - case 40: - f_hash = rte_table_hash_crc_key40; - break; - case 48: - f_hash = rte_table_hash_crc_key48; - break; - case 56: - f_hash = rte_table_hash_crc_key56; - break; - case 64: - f_hash = rte_table_hash_crc_key64; - break; - default: - return -1; - } + snprintf(global_name, sizeof(global_name), "%s_%s", softnic->params.name, name); - pp.hash.name = name; - pp.hash.key_size = params->match.hash.key_size; - pp.hash.key_offset = params->match.hash.key_offset; - pp.hash.key_mask = params->match.hash.key_mask; - pp.hash.n_keys = params->match.hash.n_keys; - pp.hash.n_buckets = params->match.hash.n_buckets; - pp.hash.f_hash = f_hash; - pp.hash.seed = 0; - - if (params->match.hash.extendable_bucket) - switch (params->match.hash.key_size) { - case 8: - ops = &rte_table_hash_key8_ext_ops; - break; - case 16: - ops = &rte_table_hash_key16_ext_ops; - break; - default: - ops = &rte_table_hash_ext_ops; - } - else - switch (params->match.hash.key_size) { - case 8: - ops = &rte_table_hash_key8_lru_ops; - break; - case 16: - ops = &rte_table_hash_key16_lru_ops; - break; - default: - ops = &rte_table_hash_lru_ops; - } - - p.ops = ops; - p.arg_create = &pp.hash; - break; - } - - case TABLE_LPM: - { - if (params->match.lpm.n_rules == 0) - return -1; - - switch (params->match.lpm.key_size) { - case 4: - { - pp.lpm.name = name; - pp.lpm.n_rules = params->match.lpm.n_rules; - pp.lpm.number_tbl8s = TABLE_LPM_NUMBER_TBL8; - pp.lpm.flags = 0; - pp.lpm.entry_unique_size = p.action_data_size + - sizeof(struct rte_pipeline_table_entry); - pp.lpm.offset = params->match.lpm.key_offset; - - p.ops = &rte_table_lpm_ops; - p.arg_create = &pp.lpm; - break; - } - - case 16: - { - pp.lpm_ipv6.name = name; - pp.lpm_ipv6.n_rules = params->match.lpm.n_rules; - pp.lpm_ipv6.number_tbl8s = TABLE_LPM_NUMBER_TBL8; - pp.lpm_ipv6.entry_unique_size = p.action_data_size + - sizeof(struct rte_pipeline_table_entry); - pp.lpm_ipv6.offset = params->match.lpm.key_offset; - - p.ops = &rte_table_lpm_ipv6_ops; - p.arg_create = &pp.lpm_ipv6; - break; - } - - default: - return -1; - } - - break; - } - - case TABLE_STUB: - { - p.ops = &rte_table_stub_ops; - p.arg_create = NULL; - break; - } - - default: - return -1; - } - - /* Resource create */ - action = NULL; - p.f_action_hit = NULL; - p.f_action_miss = NULL; - p.arg_ah = NULL; - - if (ap) { - action = rte_table_action_create(ap->ap, - softnic->params.cpu_id); - if (action == NULL) - return -1; - - status = rte_table_action_table_params_get(action, - &p); - if (status || - ((p.action_data_size + - sizeof(struct rte_pipeline_table_entry)) > - TABLE_RULE_ACTION_SIZE_MAX)) { - rte_table_action_free(action); - return -1; - } - } - - if (params->match_type == TABLE_LPM) { - if (params->match.lpm.key_size == 4) - pp.lpm.entry_unique_size = p.action_data_size + - sizeof(struct rte_pipeline_table_entry); - - if (params->match.lpm.key_size == 16) - pp.lpm_ipv6.entry_unique_size = p.action_data_size + - sizeof(struct rte_pipeline_table_entry); - } - - status = rte_pipeline_table_create(pipeline->p, - &p, - &table_id); - if (status) { - rte_table_action_free(action); - return -1; - } + status = rte_swx_pipeline_build_from_lib(&p, + global_name, + lib_file_name, + iospec_file, + numa_node); + if (status) + goto error; - /* Pipeline */ - table = &pipeline->table[pipeline->n_tables]; - memcpy(&table->params, params, sizeof(*params)); - table->ap = ap; - table->a = action; - TAILQ_INIT(&table->meter_profiles); - memset(&table->dscp_table, 0, sizeof(table->dscp_table)); - pipeline->n_tables++; + fclose(iospec_file); + iospec_file = NULL; - return 0; -} + ctl = rte_swx_ctl_pipeline_create(p); + if (!ctl) + goto error; -int -softnic_pipeline_port_out_find(struct pmd_internals *softnic, - const char *pipeline_name, - const char *name, - uint32_t *port_id) -{ - struct pipeline *pipeline; - uint32_t i; - - if (softnic == NULL || - pipeline_name == NULL || - name == NULL || - port_id == NULL) - return -1; - - pipeline = softnic_pipeline_find(softnic, pipeline_name); - if (pipeline == NULL) - return -1; - - for (i = 0; i < pipeline->n_ports_out; i++) - if (strcmp(pipeline->port_out[i].params.dev_name, name) == 0) { - *port_id = i; - return 0; - } + /* Node allocation */ + pipeline = calloc(1, sizeof(struct pipeline)); + if (!pipeline) + goto error; - return -1; -} + /* Node fill in */ + strlcpy(pipeline->name, name, sizeof(pipeline->name)); + pipeline->p = p; + pipeline->ctl = ctl; -struct softnic_table_meter_profile * -softnic_pipeline_table_meter_profile_find(struct softnic_table *table, - uint32_t meter_profile_id) -{ - struct softnic_table_meter_profile *mp; + /* Node add to list */ + TAILQ_INSERT_TAIL(&softnic->pipeline_list, pipeline, node); - TAILQ_FOREACH(mp, &table->meter_profiles, node) - if (mp->meter_profile_id == meter_profile_id) - return mp; + return pipeline; +error: + free(pipeline); + rte_swx_ctl_pipeline_free(ctl); + rte_swx_pipeline_free(p); + if (iospec_file) + fclose(iospec_file); return NULL; } diff --git a/drivers/net/softnic/rte_eth_softnic_thread.c b/drivers/net/softnic/rte_eth_softnic_thread.c index ec8bef4694..888af6caf4 100644 --- a/drivers/net/softnic/rte_eth_softnic_thread.c +++ b/drivers/net/softnic/rte_eth_softnic_thread.c @@ -10,11 +10,6 @@ #include #include -#include -#include -#include -#include -#include #include "rte_eth_softnic_internals.h" /** @@ -88,7 +83,6 @@ softnic_thread_init(struct pmd_internals *softnic) t_data->timer_period = (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000; t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period; - t_data->time_next_min = t_data->time_next; } return 0; @@ -97,6 +91,9 @@ softnic_thread_init(struct pmd_internals *softnic) static inline int thread_is_valid(struct pmd_internals *softnic, uint32_t thread_id) { + if (thread_id >= RTE_MAX_LCORE) + return 0; /* FALSE */ + if (thread_id == rte_get_main_lcore()) return 0; /* FALSE */ @@ -190,18 +187,22 @@ thread_sc_service_down(struct pmd_internals *softnic, uint32_t thread_id) t->service_id = UINT32_MAX; } -/** - * Pipeline is running when: - * (A) Pipeline is mapped to a data plane thread AND - * (B) Its data plane thread is in RUNNING state. - */ -static inline int -pipeline_is_running(struct pipeline *p) +void +softnic_thread_pipeline_disable_all(struct pmd_internals *softnic) { - if (p->enabled == 0) - return 0; + uint32_t thread_id; - return thread_is_running(p->thread_id); + for (thread_id = 0; thread_id < RTE_MAX_LCORE; thread_id++) { + struct softnic_thread_data *td = &softnic->thread_data[thread_id]; + + if (!thread_is_valid(softnic, thread_id)) + continue; + + if (softnic->params.sc && td->n_pipelines) + thread_sc_service_down(softnic, thread_id); + + td->n_pipelines = 0; + } } /** @@ -218,18 +219,11 @@ struct thread_msg_req { union { struct { - struct rte_pipeline *p; - struct { - struct rte_table_action *a; - } table[RTE_PIPELINE_TABLE_MAX]; - struct rte_ring *msgq_req; - struct rte_ring *msgq_rsp; - uint32_t timer_period_ms; - uint32_t n_tables; + struct rte_swx_pipeline *p; } pipeline_enable; struct { - struct rte_pipeline *p; + struct rte_swx_pipeline *p; } pipeline_disable; }; }; @@ -283,20 +277,16 @@ thread_msg_send_recv(struct pmd_internals *softnic, int softnic_thread_pipeline_enable(struct pmd_internals *softnic, uint32_t thread_id, - const char *pipeline_name) + struct pipeline *p) { - struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name); struct thread_msg_req *req; struct thread_msg_rsp *rsp; - uint32_t n_pipelines, i; + uint32_t n_pipelines; int status; /* Check input params */ if (!thread_is_valid(softnic, thread_id) || (p == NULL) || - (p->n_ports_in == 0) || - (p->n_ports_out == 0) || - (p->n_tables == 0) || p->enabled) return -1; @@ -312,22 +302,9 @@ softnic_thread_pipeline_enable(struct pmd_internals *softnic, if (!thread_is_running(thread_id)) { struct softnic_thread_data *td = &softnic->thread_data[thread_id]; - struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines]; /* Data plane thread */ td->p[td->n_pipelines] = p->p; - - tdp->p = p->p; - for (i = 0; i < p->n_tables; i++) - tdp->table_data[i].a = - p->table[i].a; - tdp->n_tables = p->n_tables; - - tdp->msgq_req = p->msgq_req; - tdp->msgq_rsp = p->msgq_rsp; - tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000; - tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period; - td->n_pipelines++; /* Pipeline */ @@ -345,13 +322,6 @@ softnic_thread_pipeline_enable(struct pmd_internals *softnic, /* Write request */ req->type = THREAD_REQ_PIPELINE_ENABLE; req->pipeline_enable.p = p->p; - for (i = 0; i < p->n_tables; i++) - req->pipeline_enable.table[i].a = - p->table[i].a; - req->pipeline_enable.msgq_req = p->msgq_req; - req->pipeline_enable.msgq_rsp = p->msgq_rsp; - req->pipeline_enable.timer_period_ms = p->timer_period_ms; - req->pipeline_enable.n_tables = p->n_tables; /* Send request and wait for response */ rsp = thread_msg_send_recv(softnic, thread_id, req); @@ -375,9 +345,8 @@ softnic_thread_pipeline_enable(struct pmd_internals *softnic, int softnic_thread_pipeline_disable(struct pmd_internals *softnic, uint32_t thread_id, - const char *pipeline_name) + struct pipeline *p) { - struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name); struct thread_msg_req *req; struct thread_msg_rsp *rsp; uint32_t n_pipelines; @@ -397,21 +366,12 @@ softnic_thread_pipeline_disable(struct pmd_internals *softnic, uint32_t i; for (i = 0; i < td->n_pipelines; i++) { - struct pipeline_data *tdp = &td->pipeline_data[i]; - - if (tdp->p != p->p) + if (td->p[i] != p->p) continue; /* Data plane thread */ - if (i < td->n_pipelines - 1) { - struct rte_pipeline *pipeline_last = - td->p[td->n_pipelines - 1]; - struct pipeline_data *tdp_last = - &td->pipeline_data[td->n_pipelines - 1]; - - td->p[i] = pipeline_last; - memcpy(tdp, tdp_last, sizeof(*tdp)); - } + if (i < td->n_pipelines - 1) + td->p[i] = td->p[td->n_pipelines - 1]; td->n_pipelines--; @@ -490,25 +450,9 @@ thread_msg_handle_pipeline_enable(struct softnic_thread_data *t, struct thread_msg_req *req) { struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req; - struct pipeline_data *p = &t->pipeline_data[t->n_pipelines]; - uint32_t i; /* Request */ t->p[t->n_pipelines] = req->pipeline_enable.p; - - p->p = req->pipeline_enable.p; - for (i = 0; i < req->pipeline_enable.n_tables; i++) - p->table_data[i].a = - req->pipeline_enable.table[i].a; - - p->n_tables = req->pipeline_enable.n_tables; - - p->msgq_req = req->pipeline_enable.msgq_req; - p->msgq_rsp = req->pipeline_enable.msgq_rsp; - p->timer_period = - (rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000; - p->time_next = rte_get_tsc_cycles() + p->timer_period; - t->n_pipelines++; /* Response */ @@ -522,25 +466,16 @@ thread_msg_handle_pipeline_disable(struct softnic_thread_data *t, { struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req; uint32_t n_pipelines = t->n_pipelines; - struct rte_pipeline *pipeline = req->pipeline_disable.p; + struct rte_swx_pipeline *pipeline = req->pipeline_disable.p; uint32_t i; /* find pipeline */ for (i = 0; i < n_pipelines; i++) { - struct pipeline_data *p = &t->pipeline_data[i]; - - if (p->p != pipeline) + if (t->p[i] != pipeline) continue; - if (i < n_pipelines - 1) { - struct rte_pipeline *pipeline_last = - t->p[n_pipelines - 1]; - struct pipeline_data *p_last = - &t->pipeline_data[n_pipelines - 1]; - - t->p[i] = pipeline_last; - memcpy(p, p_last, sizeof(*p)); - } + if (i < n_pipelines - 1) + t->p[i] = t->p[n_pipelines - 1]; t->n_pipelines--; @@ -583,2464 +518,37 @@ thread_msg_handle(struct softnic_thread_data *t) } /** - * Main thread & data plane threads: message passing - */ -enum pipeline_req_type { - /* Port IN */ - PIPELINE_REQ_PORT_IN_STATS_READ, - PIPELINE_REQ_PORT_IN_ENABLE, - PIPELINE_REQ_PORT_IN_DISABLE, - - /* Port OUT */ - PIPELINE_REQ_PORT_OUT_STATS_READ, - - /* Table */ - PIPELINE_REQ_TABLE_STATS_READ, - PIPELINE_REQ_TABLE_RULE_ADD, - PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT, - PIPELINE_REQ_TABLE_RULE_ADD_BULK, - PIPELINE_REQ_TABLE_RULE_DELETE, - PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT, - PIPELINE_REQ_TABLE_RULE_STATS_READ, - PIPELINE_REQ_TABLE_MTR_PROFILE_ADD, - PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE, - PIPELINE_REQ_TABLE_RULE_MTR_READ, - PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE, - PIPELINE_REQ_TABLE_RULE_TTL_READ, - PIPELINE_REQ_MAX -}; - -struct pipeline_msg_req_port_in_stats_read { - int clear; -}; - -struct pipeline_msg_req_port_out_stats_read { - int clear; -}; - -struct pipeline_msg_req_table_stats_read { - int clear; -}; - -struct pipeline_msg_req_table_rule_add { - struct softnic_table_rule_match match; - struct softnic_table_rule_action action; -}; - -struct pipeline_msg_req_table_rule_add_default { - struct softnic_table_rule_action action; -}; - -struct pipeline_msg_req_table_rule_add_bulk { - struct softnic_table_rule_match *match; - struct softnic_table_rule_action *action; - void **data; - uint32_t n_rules; - int bulk; -}; - -struct pipeline_msg_req_table_rule_delete { - struct softnic_table_rule_match match; -}; - -struct pipeline_msg_req_table_rule_stats_read { - void *data; - int clear; -}; - -struct pipeline_msg_req_table_mtr_profile_add { - uint32_t meter_profile_id; - struct rte_table_action_meter_profile profile; -}; - -struct pipeline_msg_req_table_mtr_profile_delete { - uint32_t meter_profile_id; -}; - -struct pipeline_msg_req_table_rule_mtr_read { - void *data; - uint32_t tc_mask; - int clear; -}; - -struct pipeline_msg_req_table_dscp_table_update { - uint64_t dscp_mask; - struct rte_table_action_dscp_table dscp_table; -}; - -struct pipeline_msg_req_table_rule_ttl_read { - void *data; - int clear; -}; - -struct pipeline_msg_req { - enum pipeline_req_type type; - uint32_t id; /* Port IN, port OUT or table ID */ - - RTE_STD_C11 - union { - struct pipeline_msg_req_port_in_stats_read port_in_stats_read; - struct pipeline_msg_req_port_out_stats_read port_out_stats_read; - struct pipeline_msg_req_table_stats_read table_stats_read; - struct pipeline_msg_req_table_rule_add table_rule_add; - struct pipeline_msg_req_table_rule_add_default table_rule_add_default; - struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk; - struct pipeline_msg_req_table_rule_delete table_rule_delete; - struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read; - struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add; - struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete; - struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read; - struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update; - struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read; - }; -}; - -struct pipeline_msg_rsp_port_in_stats_read { - struct rte_pipeline_port_in_stats stats; -}; - -struct pipeline_msg_rsp_port_out_stats_read { - struct rte_pipeline_port_out_stats stats; -}; - -struct pipeline_msg_rsp_table_stats_read { - struct rte_pipeline_table_stats stats; -}; - -struct pipeline_msg_rsp_table_rule_add { - void *data; -}; - -struct pipeline_msg_rsp_table_rule_add_default { - void *data; -}; - -struct pipeline_msg_rsp_table_rule_add_bulk { - uint32_t n_rules; -}; - -struct pipeline_msg_rsp_table_rule_stats_read { - struct rte_table_action_stats_counters stats; -}; - -struct pipeline_msg_rsp_table_rule_mtr_read { - struct rte_table_action_mtr_counters stats; -}; - -struct pipeline_msg_rsp_table_rule_ttl_read { - struct rte_table_action_ttl_counters stats; -}; - -struct pipeline_msg_rsp { - int status; - - RTE_STD_C11 - union { - struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read; - struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read; - struct pipeline_msg_rsp_table_stats_read table_stats_read; - struct pipeline_msg_rsp_table_rule_add table_rule_add; - struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default; - struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk; - struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read; - struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read; - struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read; - }; -}; - -/** - * Main thread + * Data plane threads: main */ -static struct pipeline_msg_req * -pipeline_msg_alloc(void) -{ - size_t size = RTE_MAX(sizeof(struct pipeline_msg_req), - sizeof(struct pipeline_msg_rsp)); - - return calloc(1, size); -} - -static void -pipeline_msg_free(struct pipeline_msg_rsp *rsp) -{ - free(rsp); -} - -static struct pipeline_msg_rsp * -pipeline_msg_send_recv(struct pipeline *p, - struct pipeline_msg_req *req) -{ - struct rte_ring *msgq_req = p->msgq_req; - struct rte_ring *msgq_rsp = p->msgq_rsp; - struct pipeline_msg_rsp *rsp; - int status; - - /* send */ - do { - status = rte_ring_sp_enqueue(msgq_req, req); - } while (status == -ENOBUFS); - - /* recv */ - do { - status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp); - } while (status != 0); - - return rsp; -} - -int -softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t port_id, - struct rte_pipeline_port_in_stats *stats, - int clear) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL || - stats == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - port_id >= p->n_ports_in) - return -1; - - if (!pipeline_is_running(p)) { - status = rte_pipeline_port_in_stats_read(p->p, - port_id, - stats, - clear); - - return status; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_PORT_IN_STATS_READ; - req->id = port_id; - req->port_in_stats_read.clear = clear; - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - if (status) - memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats)); - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_port_in_enable(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t port_id) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - port_id >= p->n_ports_in) - return -1; - - if (!pipeline_is_running(p)) { - status = rte_pipeline_port_in_enable(p->p, port_id); - return status; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_PORT_IN_ENABLE; - req->id = port_id; - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_port_in_disable(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t port_id) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - port_id >= p->n_ports_in) - return -1; - - if (!pipeline_is_running(p)) { - status = rte_pipeline_port_in_disable(p->p, port_id); - return status; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_PORT_IN_DISABLE; - req->id = port_id; - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t port_id, - struct rte_pipeline_port_out_stats *stats, - int clear) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL || - stats == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - port_id >= p->n_ports_out) - return -1; - - if (!pipeline_is_running(p)) { - status = rte_pipeline_port_out_stats_read(p->p, - port_id, - stats, - clear); - - return status; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_PORT_OUT_STATS_READ; - req->id = port_id; - req->port_out_stats_read.clear = clear; - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - if (status) - memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats)); - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_table_stats_read(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t table_id, - struct rte_pipeline_table_stats *stats, - int clear) +static int32_t +rte_pmd_softnic_run_internal(void *arg) { - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL || - stats == NULL) - return -1; + struct rte_eth_dev *dev = arg; + struct pmd_internals *softnic; + struct softnic_thread_data *t; + uint32_t thread_id, j; - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - table_id >= p->n_tables) - return -1; + softnic = dev->data->dev_private; + thread_id = rte_lcore_id(); + t = &softnic->thread_data[thread_id]; + t->iter++; - if (!pipeline_is_running(p)) { - status = rte_pipeline_table_stats_read(p->p, - table_id, - stats, - clear); + /* Data Plane */ + for (j = 0; j < t->n_pipelines; j++) + rte_swx_pipeline_run(t->p[j], PIPELINE_INSTR_QUANTA); - return status; - } + /* Control Plane */ + if ((t->iter & 0xFLLU) == 0) { + uint64_t time = rte_get_tsc_cycles(); + uint64_t time_next = t->time_next; - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_TABLE_STATS_READ; - req->id = table_id; - req->table_stats_read.clear = clear; - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - if (status) - memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats)); - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -static int -match_check(struct softnic_table_rule_match *match, - struct pipeline *p, - uint32_t table_id) -{ - struct softnic_table *table; - - if (match == NULL || - p == NULL || - table_id >= p->n_tables) - return -1; - - table = &p->table[table_id]; - if (match->match_type != table->params.match_type) - return -1; - - switch (match->match_type) { - case TABLE_ACL: - { - struct softnic_table_acl_params *t = &table->params.match.acl; - struct softnic_table_rule_match_acl *r = &match->match.acl; - - if ((r->ip_version && (t->ip_version == 0)) || - ((r->ip_version == 0) && t->ip_version)) - return -1; - - if (r->ip_version) { - if (r->sa_depth > 32 || - r->da_depth > 32) - return -1; - } else { - if (r->sa_depth > 128 || - r->da_depth > 128) - return -1; - } - return 0; - } - - case TABLE_ARRAY: - return 0; - - case TABLE_HASH: - return 0; - - case TABLE_LPM: - { - struct softnic_table_lpm_params *t = &table->params.match.lpm; - struct softnic_table_rule_match_lpm *r = &match->match.lpm; - - if ((r->ip_version && (t->key_size != 4)) || - ((r->ip_version == 0) && (t->key_size != 16))) - return -1; - - if (r->ip_version) { - if (r->depth > 32) - return -1; - } else { - if (r->depth > 128) - return -1; - } - return 0; - } - - case TABLE_STUB: - return -1; - - default: - return -1; - } -} - -static int -action_check(struct softnic_table_rule_action *action, - struct pipeline *p, - uint32_t table_id) -{ - struct softnic_table_action_profile *ap; - - if (action == NULL || - p == NULL || - table_id >= p->n_tables) - return -1; - - ap = p->table[table_id].ap; - if (action->action_mask != ap->params.action_mask) - return -1; - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { - if (action->fwd.action == RTE_PIPELINE_ACTION_PORT && - action->fwd.id >= p->n_ports_out) - return -1; - - if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE && - action->fwd.id >= p->n_tables) - return -1; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { - uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1; - uint32_t tc_mask1 = action->mtr.tc_mask; - - if (tc_mask1 != tc_mask0) - return -1; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { - uint32_t n_subports_per_port = - ap->params.tm.n_subports_per_port; - uint32_t n_pipes_per_subport = - ap->params.tm.n_pipes_per_subport; - uint32_t subport_id = action->tm.subport_id; - uint32_t pipe_id = action->tm.pipe_id; - - if (subport_id >= n_subports_per_port || - pipe_id >= n_pipes_per_subport) - return -1; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { - uint64_t encap_mask = ap->params.encap.encap_mask; - enum rte_table_action_encap_type type = action->encap.type; - - if ((encap_mask & (1LLU << type)) == 0) - return -1; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { - int ip_version0 = ap->params.common.ip_version; - int ip_version1 = action->nat.ip_version; - - if ((ip_version1 && (ip_version0 == 0)) || - ((ip_version1 == 0) && ip_version0)) - return -1; - } - - return 0; -} - -static int -action_default_check(struct softnic_table_rule_action *action, - struct pipeline *p, - uint32_t table_id) -{ - if (action == NULL || - action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD) || - p == NULL || - table_id >= p->n_tables) - return -1; - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { - if (action->fwd.action == RTE_PIPELINE_ACTION_PORT && - action->fwd.id >= p->n_ports_out) - return -1; - - if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE && - action->fwd.id >= p->n_tables) - return -1; - } - - return 0; -} - -union table_rule_match_low_level { - struct rte_table_acl_rule_add_params acl_add; - struct rte_table_acl_rule_delete_params acl_delete; - struct rte_table_array_key array; - uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX]; - struct rte_table_lpm_key lpm_ipv4; - struct rte_table_lpm_ipv6_key lpm_ipv6; -}; - -static int -match_convert(struct softnic_table_rule_match *mh, - union table_rule_match_low_level *ml, - int add); - -static int -action_convert(struct rte_table_action *a, - struct softnic_table_rule_action *action, - struct rte_pipeline_table_entry *data); - -int -softnic_pipeline_table_rule_add(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t table_id, - struct softnic_table_rule_match *match, - struct softnic_table_rule_action *action, - void **data) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL || - match == NULL || - action == NULL || - data == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - table_id >= p->n_tables || - match_check(match, p, table_id) || - action_check(action, p, table_id)) - return -1; - - if (!pipeline_is_running(p)) { - struct rte_table_action *a = p->table[table_id].a; - union table_rule_match_low_level match_ll; - struct rte_pipeline_table_entry *data_in, *data_out; - int key_found; - uint8_t *buffer; - - buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t)); - if (buffer == NULL) - return -1; - - /* Table match-action rule conversion */ - data_in = (struct rte_pipeline_table_entry *)buffer; - - status = match_convert(match, &match_ll, 1); - if (status) { - free(buffer); - return -1; - } - - status = action_convert(a, action, data_in); - if (status) { - free(buffer); - return -1; - } - - /* Add rule (match, action) to table */ - status = rte_pipeline_table_entry_add(p->p, - table_id, - &match_ll, - data_in, - &key_found, - &data_out); - if (status) { - free(buffer); - return -1; - } - - /* Write Response */ - *data = data_out; - - free(buffer); - return 0; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_TABLE_RULE_ADD; - req->id = table_id; - memcpy(&req->table_rule_add.match, match, sizeof(*match)); - memcpy(&req->table_rule_add.action, action, sizeof(*action)); - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - if (status == 0) - *data = rsp->table_rule_add.data; - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t table_id, - struct softnic_table_rule_action *action, - void **data) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL || - action == NULL || - data == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - table_id >= p->n_tables || - action_default_check(action, p, table_id)) - return -1; - - if (!pipeline_is_running(p)) { - struct rte_pipeline_table_entry *data_in, *data_out; - uint8_t *buffer; - - buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t)); - if (buffer == NULL) - return -1; - - /* Apply actions */ - data_in = (struct rte_pipeline_table_entry *)buffer; - - data_in->action = action->fwd.action; - if (action->fwd.action == RTE_PIPELINE_ACTION_PORT) - data_in->port_id = action->fwd.id; - if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE) - data_in->table_id = action->fwd.id; - - /* Add default rule to table */ - status = rte_pipeline_table_default_entry_add(p->p, - table_id, - data_in, - &data_out); - if (status) { - free(buffer); - return -1; - } - - /* Write Response */ - *data = data_out; - - free(buffer); - return 0; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT; - req->id = table_id; - memcpy(&req->table_rule_add_default.action, action, sizeof(*action)); - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - if (status == 0) - *data = rsp->table_rule_add_default.data; - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t table_id, - struct softnic_table_rule_match *match, - struct softnic_table_rule_action *action, - void **data, - uint32_t *n_rules) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - uint32_t i; - int status; - - /* Check input params */ - if (pipeline_name == NULL || - match == NULL || - action == NULL || - data == NULL || - n_rules == NULL || - (*n_rules == 0)) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - table_id >= p->n_tables) - return -1; - - for (i = 0; i < *n_rules; i++) - if (match_check(match, p, table_id) || - action_check(action, p, table_id)) - return -1; - - if (!pipeline_is_running(p)) { - struct rte_table_action *a = p->table[table_id].a; - union table_rule_match_low_level *match_ll; - uint8_t *action_ll; - void **match_ll_ptr; - struct rte_pipeline_table_entry **action_ll_ptr; - struct rte_pipeline_table_entry **entries_ptr = - (struct rte_pipeline_table_entry **)data; - uint32_t bulk = - (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0; - int *found; - - /* Memory allocation */ - match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level)); - action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX); - match_ll_ptr = calloc(*n_rules, sizeof(void *)); - action_ll_ptr = - calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *)); - found = calloc(*n_rules, sizeof(int)); - - if (match_ll == NULL || - action_ll == NULL || - match_ll_ptr == NULL || - action_ll_ptr == NULL || - found == NULL) - goto fail; - - for (i = 0; i < *n_rules; i++) { - match_ll_ptr[i] = (void *)&match_ll[i]; - action_ll_ptr[i] = - (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX]; - } - - /* Rule match conversion */ - for (i = 0; i < *n_rules; i++) { - status = match_convert(&match[i], match_ll_ptr[i], 1); - if (status) - goto fail; - } - - /* Rule action conversion */ - for (i = 0; i < *n_rules; i++) { - status = action_convert(a, &action[i], action_ll_ptr[i]); - if (status) - goto fail; - } - - /* Add rule (match, action) to table */ - if (bulk) { - status = rte_pipeline_table_entry_add_bulk(p->p, - table_id, - match_ll_ptr, - action_ll_ptr, - *n_rules, - found, - entries_ptr); - if (status) - *n_rules = 0; - } else { - for (i = 0; i < *n_rules; i++) { - status = rte_pipeline_table_entry_add(p->p, - table_id, - match_ll_ptr[i], - action_ll_ptr[i], - &found[i], - &entries_ptr[i]); - if (status) { - *n_rules = i; - break; - } - } - } - - /* Free */ - free(found); - free(action_ll_ptr); - free(match_ll_ptr); - free(action_ll); - free(match_ll); - - return status; - -fail: - free(found); - free(action_ll_ptr); - free(match_ll_ptr); - free(action_ll); - free(match_ll); - - *n_rules = 0; - return -1; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK; - req->id = table_id; - req->table_rule_add_bulk.match = match; - req->table_rule_add_bulk.action = action; - req->table_rule_add_bulk.data = data; - req->table_rule_add_bulk.n_rules = *n_rules; - req->table_rule_add_bulk.bulk = - (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0; - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - if (status == 0) - *n_rules = rsp->table_rule_add_bulk.n_rules; - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_table_rule_delete(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t table_id, - struct softnic_table_rule_match *match) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL || - match == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - table_id >= p->n_tables || - match_check(match, p, table_id)) - return -1; - - if (!pipeline_is_running(p)) { - union table_rule_match_low_level match_ll; - int key_found; - - status = match_convert(match, &match_ll, 0); - if (status) - return -1; - - status = rte_pipeline_table_entry_delete(p->p, - table_id, - &match_ll, - &key_found, - NULL); - - return status; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_TABLE_RULE_DELETE; - req->id = table_id; - memcpy(&req->table_rule_delete.match, match, sizeof(*match)); - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t table_id) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - table_id >= p->n_tables) - return -1; - - if (!pipeline_is_running(p)) { - status = rte_pipeline_table_default_entry_delete(p->p, - table_id, - NULL); - - return status; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT; - req->id = table_id; - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t table_id, - void *data, - struct rte_table_action_stats_counters *stats, - int clear) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL || - data == NULL || - stats == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - table_id >= p->n_tables) - return -1; - - if (!pipeline_is_running(p)) { - struct rte_table_action *a = p->table[table_id].a; - - status = rte_table_action_stats_read(a, - data, - stats, - clear); - - return status; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ; - req->id = table_id; - req->table_rule_stats_read.data = data; - req->table_rule_stats_read.clear = clear; - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - if (status) - memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats)); - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_table_mtr_profile_add(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t table_id, - uint32_t meter_profile_id, - struct rte_table_action_meter_profile *profile) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - struct softnic_table *table; - struct softnic_table_meter_profile *mp; - int status; - - /* Check input params */ - if (pipeline_name == NULL || - profile == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - table_id >= p->n_tables) - return -1; - - table = &p->table[table_id]; - mp = softnic_pipeline_table_meter_profile_find(table, meter_profile_id); - if (mp) - return -1; - - /* Resource Allocation */ - mp = calloc(1, sizeof(struct softnic_table_meter_profile)); - if (mp == NULL) - return -1; - - mp->meter_profile_id = meter_profile_id; - memcpy(&mp->profile, profile, sizeof(mp->profile)); - - if (!pipeline_is_running(p)) { - status = rte_table_action_meter_profile_add(table->a, - meter_profile_id, - profile); - if (status) { - free(mp); - return status; - } - - /* Add profile to the table. */ - TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node); - - return status; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) { - free(mp); - return -1; - } - - /* Write request */ - req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD; - req->id = table_id; - req->table_mtr_profile_add.meter_profile_id = meter_profile_id; - memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile)); - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - if (status == 0) - TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node); - else - free(mp); - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t table_id, - uint32_t meter_profile_id) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - table_id >= p->n_tables) - return -1; - - if (!pipeline_is_running(p)) { - struct rte_table_action *a = p->table[table_id].a; - - status = rte_table_action_meter_profile_delete(a, - meter_profile_id); - - return status; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE; - req->id = table_id; - req->table_mtr_profile_delete.meter_profile_id = meter_profile_id; - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t table_id, - void *data, - uint32_t tc_mask, - struct rte_table_action_mtr_counters *stats, - int clear) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL || - data == NULL || - stats == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - table_id >= p->n_tables) - return -1; - - if (!pipeline_is_running(p)) { - struct rte_table_action *a = p->table[table_id].a; - - status = rte_table_action_meter_read(a, - data, - tc_mask, - stats, - clear); - - return status; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ; - req->id = table_id; - req->table_rule_mtr_read.data = data; - req->table_rule_mtr_read.tc_mask = tc_mask; - req->table_rule_mtr_read.clear = clear; - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - if (status) - memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats)); - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t table_id, - uint64_t dscp_mask, - struct rte_table_action_dscp_table *dscp_table) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL || - dscp_table == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - table_id >= p->n_tables) - return -1; - - if (!pipeline_is_running(p)) { - struct rte_table_action *a = p->table[table_id].a; - - status = rte_table_action_dscp_table_update(a, - dscp_mask, - dscp_table); - - /* Update table dscp table */ - if (!status) - memcpy(&p->table[table_id].dscp_table, dscp_table, - sizeof(p->table[table_id].dscp_table)); - - return status; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE; - req->id = table_id; - req->table_dscp_table_update.dscp_mask = dscp_mask; - memcpy(&req->table_dscp_table_update.dscp_table, - dscp_table, sizeof(*dscp_table)); - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - - /* Update table dscp table */ - if (!status) - memcpy(&p->table[table_id].dscp_table, dscp_table, - sizeof(p->table[table_id].dscp_table)); - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -int -softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic, - const char *pipeline_name, - uint32_t table_id, - void *data, - struct rte_table_action_ttl_counters *stats, - int clear) -{ - struct pipeline *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status; - - /* Check input params */ - if (pipeline_name == NULL || - data == NULL || - stats == NULL) - return -1; - - p = softnic_pipeline_find(softnic, pipeline_name); - if (p == NULL || - table_id >= p->n_tables) - return -1; - - if (!pipeline_is_running(p)) { - struct rte_table_action *a = p->table[table_id].a; - - status = rte_table_action_ttl_read(a, - data, - stats, - clear); - - return status; - } - - /* Allocate request */ - req = pipeline_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ; - req->id = table_id; - req->table_rule_ttl_read.data = data; - req->table_rule_ttl_read.clear = clear; - - /* Send request and wait for response */ - rsp = pipeline_msg_send_recv(p, req); - - /* Read response */ - status = rsp->status; - if (status) - memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats)); - - /* Free response */ - pipeline_msg_free(rsp); - - return status; -} - -/** - * Data plane threads: message handling - */ -static inline struct pipeline_msg_req * -pipeline_msg_recv(struct rte_ring *msgq_req) -{ - struct pipeline_msg_req *req; - - int status = rte_ring_sc_dequeue(msgq_req, (void **)&req); - - if (status != 0) - return NULL; - - return req; -} - -static inline void -pipeline_msg_send(struct rte_ring *msgq_rsp, - struct pipeline_msg_rsp *rsp) -{ - int status; - - do { - status = rte_ring_sp_enqueue(msgq_rsp, rsp); - } while (status == -ENOBUFS); -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - uint32_t port_id = req->id; - int clear = req->port_in_stats_read.clear; - - rsp->status = rte_pipeline_port_in_stats_read(p->p, - port_id, - &rsp->port_in_stats_read.stats, - clear); - - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_port_in_enable(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - uint32_t port_id = req->id; - - rsp->status = rte_pipeline_port_in_enable(p->p, - port_id); - - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_port_in_disable(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - uint32_t port_id = req->id; - - rsp->status = rte_pipeline_port_in_disable(p->p, - port_id); - - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - uint32_t port_id = req->id; - int clear = req->port_out_stats_read.clear; - - rsp->status = rte_pipeline_port_out_stats_read(p->p, - port_id, - &rsp->port_out_stats_read.stats, - clear); - - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_stats_read(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - uint32_t port_id = req->id; - int clear = req->table_stats_read.clear; - - rsp->status = rte_pipeline_table_stats_read(p->p, - port_id, - &rsp->table_stats_read.stats, - clear); - - return rsp; -} - -static int -match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32) -{ - if (depth > 128) - return -1; - - switch (depth / 32) { - case 0: - depth32[0] = depth; - depth32[1] = 0; - depth32[2] = 0; - depth32[3] = 0; - return 0; - - case 1: - depth32[0] = 32; - depth32[1] = depth - 32; - depth32[2] = 0; - depth32[3] = 0; - return 0; - - case 2: - depth32[0] = 32; - depth32[1] = 32; - depth32[2] = depth - 64; - depth32[3] = 0; - return 0; - - case 3: - depth32[0] = 32; - depth32[1] = 32; - depth32[2] = 32; - depth32[3] = depth - 96; - return 0; - - case 4: - depth32[0] = 32; - depth32[1] = 32; - depth32[2] = 32; - depth32[3] = 32; - return 0; - - default: - return -1; - } -} - -static int -match_convert(struct softnic_table_rule_match *mh, - union table_rule_match_low_level *ml, - int add) -{ - memset(ml, 0, sizeof(*ml)); - - switch (mh->match_type) { - case TABLE_ACL: - if (mh->match.acl.ip_version) - if (add) { - ml->acl_add.field_value[0].value.u8 = - mh->match.acl.proto; - ml->acl_add.field_value[0].mask_range.u8 = - mh->match.acl.proto_mask; - - ml->acl_add.field_value[1].value.u32 = - mh->match.acl.ipv4.sa; - ml->acl_add.field_value[1].mask_range.u32 = - mh->match.acl.sa_depth; - - ml->acl_add.field_value[2].value.u32 = - mh->match.acl.ipv4.da; - ml->acl_add.field_value[2].mask_range.u32 = - mh->match.acl.da_depth; - - ml->acl_add.field_value[3].value.u16 = - mh->match.acl.sp0; - ml->acl_add.field_value[3].mask_range.u16 = - mh->match.acl.sp1; - - ml->acl_add.field_value[4].value.u16 = - mh->match.acl.dp0; - ml->acl_add.field_value[4].mask_range.u16 = - mh->match.acl.dp1; - - ml->acl_add.priority = - (int32_t)mh->match.acl.priority; - } else { - ml->acl_delete.field_value[0].value.u8 = - mh->match.acl.proto; - ml->acl_delete.field_value[0].mask_range.u8 = - mh->match.acl.proto_mask; - - ml->acl_delete.field_value[1].value.u32 = - mh->match.acl.ipv4.sa; - ml->acl_delete.field_value[1].mask_range.u32 = - mh->match.acl.sa_depth; - - ml->acl_delete.field_value[2].value.u32 = - mh->match.acl.ipv4.da; - ml->acl_delete.field_value[2].mask_range.u32 = - mh->match.acl.da_depth; - - ml->acl_delete.field_value[3].value.u16 = - mh->match.acl.sp0; - ml->acl_delete.field_value[3].mask_range.u16 = - mh->match.acl.sp1; - - ml->acl_delete.field_value[4].value.u16 = - mh->match.acl.dp0; - ml->acl_delete.field_value[4].mask_range.u16 = - mh->match.acl.dp1; - } - else - if (add) { - uint32_t *sa32 = - (uint32_t *)mh->match.acl.ipv6.sa; - uint32_t *da32 = - (uint32_t *)mh->match.acl.ipv6.da; - uint32_t sa32_depth[4], da32_depth[4]; - int status; - - status = match_convert_ipv6_depth(mh->match.acl.sa_depth, - sa32_depth); - if (status) - return status; - - status = match_convert_ipv6_depth( - mh->match.acl.da_depth, - da32_depth); - if (status) - return status; - - ml->acl_add.field_value[0].value.u8 = - mh->match.acl.proto; - ml->acl_add.field_value[0].mask_range.u8 = - mh->match.acl.proto_mask; - - ml->acl_add.field_value[1].value.u32 = - rte_be_to_cpu_32(sa32[0]); - ml->acl_add.field_value[1].mask_range.u32 = - sa32_depth[0]; - ml->acl_add.field_value[2].value.u32 = - rte_be_to_cpu_32(sa32[1]); - ml->acl_add.field_value[2].mask_range.u32 = - sa32_depth[1]; - ml->acl_add.field_value[3].value.u32 = - rte_be_to_cpu_32(sa32[2]); - ml->acl_add.field_value[3].mask_range.u32 = - sa32_depth[2]; - ml->acl_add.field_value[4].value.u32 = - rte_be_to_cpu_32(sa32[3]); - ml->acl_add.field_value[4].mask_range.u32 = - sa32_depth[3]; - - ml->acl_add.field_value[5].value.u32 = - rte_be_to_cpu_32(da32[0]); - ml->acl_add.field_value[5].mask_range.u32 = - da32_depth[0]; - ml->acl_add.field_value[6].value.u32 = - rte_be_to_cpu_32(da32[1]); - ml->acl_add.field_value[6].mask_range.u32 = - da32_depth[1]; - ml->acl_add.field_value[7].value.u32 = - rte_be_to_cpu_32(da32[2]); - ml->acl_add.field_value[7].mask_range.u32 = - da32_depth[2]; - ml->acl_add.field_value[8].value.u32 = - rte_be_to_cpu_32(da32[3]); - ml->acl_add.field_value[8].mask_range.u32 = - da32_depth[3]; - - ml->acl_add.field_value[9].value.u16 = - mh->match.acl.sp0; - ml->acl_add.field_value[9].mask_range.u16 = - mh->match.acl.sp1; - - ml->acl_add.field_value[10].value.u16 = - mh->match.acl.dp0; - ml->acl_add.field_value[10].mask_range.u16 = - mh->match.acl.dp1; - - ml->acl_add.priority = - (int32_t)mh->match.acl.priority; - } else { - uint32_t *sa32 = - (uint32_t *)mh->match.acl.ipv6.sa; - uint32_t *da32 = - (uint32_t *)mh->match.acl.ipv6.da; - uint32_t sa32_depth[4], da32_depth[4]; - int status; - - status = match_convert_ipv6_depth(mh->match.acl.sa_depth, - sa32_depth); - if (status) - return status; - - status = match_convert_ipv6_depth(mh->match.acl.da_depth, - da32_depth); - if (status) - return status; - - ml->acl_delete.field_value[0].value.u8 = - mh->match.acl.proto; - ml->acl_delete.field_value[0].mask_range.u8 = - mh->match.acl.proto_mask; - - ml->acl_delete.field_value[1].value.u32 = - rte_be_to_cpu_32(sa32[0]); - ml->acl_delete.field_value[1].mask_range.u32 = - sa32_depth[0]; - ml->acl_delete.field_value[2].value.u32 = - rte_be_to_cpu_32(sa32[1]); - ml->acl_delete.field_value[2].mask_range.u32 = - sa32_depth[1]; - ml->acl_delete.field_value[3].value.u32 = - rte_be_to_cpu_32(sa32[2]); - ml->acl_delete.field_value[3].mask_range.u32 = - sa32_depth[2]; - ml->acl_delete.field_value[4].value.u32 = - rte_be_to_cpu_32(sa32[3]); - ml->acl_delete.field_value[4].mask_range.u32 = - sa32_depth[3]; - - ml->acl_delete.field_value[5].value.u32 = - rte_be_to_cpu_32(da32[0]); - ml->acl_delete.field_value[5].mask_range.u32 = - da32_depth[0]; - ml->acl_delete.field_value[6].value.u32 = - rte_be_to_cpu_32(da32[1]); - ml->acl_delete.field_value[6].mask_range.u32 = - da32_depth[1]; - ml->acl_delete.field_value[7].value.u32 = - rte_be_to_cpu_32(da32[2]); - ml->acl_delete.field_value[7].mask_range.u32 = - da32_depth[2]; - ml->acl_delete.field_value[8].value.u32 = - rte_be_to_cpu_32(da32[3]); - ml->acl_delete.field_value[8].mask_range.u32 = - da32_depth[3]; - - ml->acl_delete.field_value[9].value.u16 = - mh->match.acl.sp0; - ml->acl_delete.field_value[9].mask_range.u16 = - mh->match.acl.sp1; - - ml->acl_delete.field_value[10].value.u16 = - mh->match.acl.dp0; - ml->acl_delete.field_value[10].mask_range.u16 = - mh->match.acl.dp1; - } - return 0; - - case TABLE_ARRAY: - ml->array.pos = mh->match.array.pos; - return 0; - - case TABLE_HASH: - memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash)); - return 0; - - case TABLE_LPM: - if (mh->match.lpm.ip_version) { - ml->lpm_ipv4.ip = mh->match.lpm.ipv4; - ml->lpm_ipv4.depth = mh->match.lpm.depth; - } else { - memcpy(ml->lpm_ipv6.ip, - mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip)); - ml->lpm_ipv6.depth = mh->match.lpm.depth; - } - - return 0; - - default: - return -1; - } -} - -static int -action_convert(struct rte_table_action *a, - struct softnic_table_rule_action *action, - struct rte_pipeline_table_entry *data) -{ - int status; - - /* Apply actions */ - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { - status = rte_table_action_apply(a, - data, - RTE_TABLE_ACTION_FWD, - &action->fwd); - - if (status) - return status; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) { - status = rte_table_action_apply(a, - data, - RTE_TABLE_ACTION_LB, - &action->lb); - - if (status) - return status; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { - status = rte_table_action_apply(a, - data, - RTE_TABLE_ACTION_MTR, - &action->mtr); - - if (status) - return status; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { - status = rte_table_action_apply(a, - data, - RTE_TABLE_ACTION_TM, - &action->tm); - - if (status) - return status; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { - status = rte_table_action_apply(a, - data, - RTE_TABLE_ACTION_ENCAP, - &action->encap); - - if (status) - return status; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { - status = rte_table_action_apply(a, - data, - RTE_TABLE_ACTION_NAT, - &action->nat); - - if (status) - return status; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) { - status = rte_table_action_apply(a, - data, - RTE_TABLE_ACTION_TTL, - &action->ttl); - - if (status) - return status; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) { - status = rte_table_action_apply(a, - data, - RTE_TABLE_ACTION_STATS, - &action->stats); - - if (status) - return status; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) { - status = rte_table_action_apply(a, - data, - RTE_TABLE_ACTION_TIME, - &action->time); - - if (status) - return status; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) { - status = rte_table_action_apply(a, - data, - RTE_TABLE_ACTION_TAG, - &action->tag); - - if (status) - return status; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) { - status = rte_table_action_apply(a, - data, - RTE_TABLE_ACTION_DECAP, - &action->decap); - - if (status) - return status; - } - - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) { - status = rte_table_action_apply(a, - data, - RTE_TABLE_ACTION_SYM_CRYPTO, - &action->sym_crypto); - - if (status) - return status; - } - - return 0; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_rule_add(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - union table_rule_match_low_level match_ll; - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - struct softnic_table_rule_match *match = &req->table_rule_add.match; - struct softnic_table_rule_action *action = &req->table_rule_add.action; - struct rte_pipeline_table_entry *data_in, *data_out; - uint32_t table_id = req->id; - int key_found, status; - struct rte_table_action *a = p->table_data[table_id].a; - - /* Apply actions */ - memset(p->buffer, 0, sizeof(p->buffer)); - data_in = (struct rte_pipeline_table_entry *)p->buffer; - - status = match_convert(match, &match_ll, 1); - if (status) { - rsp->status = -1; - return rsp; - } - - status = action_convert(a, action, data_in); - if (status) { - rsp->status = -1; - return rsp; - } - - status = rte_pipeline_table_entry_add(p->p, - table_id, - &match_ll, - data_in, - &key_found, - &data_out); - if (status) { - rsp->status = -1; - return rsp; - } - - /* Write response */ - rsp->status = 0; - rsp->table_rule_add.data = data_out; - - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - struct softnic_table_rule_action *action = &req->table_rule_add_default.action; - struct rte_pipeline_table_entry *data_in, *data_out; - uint32_t table_id = req->id; - int status; - - /* Apply actions */ - memset(p->buffer, 0, sizeof(p->buffer)); - data_in = (struct rte_pipeline_table_entry *)p->buffer; - - data_in->action = action->fwd.action; - if (action->fwd.action == RTE_PIPELINE_ACTION_PORT) - data_in->port_id = action->fwd.id; - if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE) - data_in->table_id = action->fwd.id; - - /* Add default rule to table */ - status = rte_pipeline_table_default_entry_add(p->p, - table_id, - data_in, - &data_out); - if (status) { - rsp->status = -1; - return rsp; - } - - /* Write response */ - rsp->status = 0; - rsp->table_rule_add_default.data = data_out; - - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - - uint32_t table_id = req->id; - struct softnic_table_rule_match *match = req->table_rule_add_bulk.match; - struct softnic_table_rule_action *action = req->table_rule_add_bulk.action; - struct rte_pipeline_table_entry **data = - (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data; - uint32_t n_rules = req->table_rule_add_bulk.n_rules; - uint32_t bulk = req->table_rule_add_bulk.bulk; - - struct rte_table_action *a = p->table_data[table_id].a; - union table_rule_match_low_level *match_ll; - uint8_t *action_ll; - void **match_ll_ptr; - struct rte_pipeline_table_entry **action_ll_ptr; - int *found, status; - uint32_t i; - - /* Memory allocation */ - match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level)); - action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX); - match_ll_ptr = calloc(n_rules, sizeof(void *)); - action_ll_ptr = - calloc(n_rules, sizeof(struct rte_pipeline_table_entry *)); - found = calloc(n_rules, sizeof(int)); - - if (match_ll == NULL || - action_ll == NULL || - match_ll_ptr == NULL || - action_ll_ptr == NULL || - found == NULL) - goto fail; - - for (i = 0; i < n_rules; i++) { - match_ll_ptr[i] = (void *)&match_ll[i]; - action_ll_ptr[i] = - (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX]; - } - - /* Rule match conversion */ - for (i = 0; i < n_rules; i++) { - status = match_convert(&match[i], match_ll_ptr[i], 1); - if (status) - goto fail; - } - - /* Rule action conversion */ - for (i = 0; i < n_rules; i++) { - status = action_convert(a, &action[i], action_ll_ptr[i]); - if (status) - goto fail; - } - - /* Add rule (match, action) to table */ - if (bulk) { - status = rte_pipeline_table_entry_add_bulk(p->p, - table_id, - match_ll_ptr, - action_ll_ptr, - n_rules, - found, - data); - if (status) - n_rules = 0; - } else { - for (i = 0; i < n_rules; i++) { - status = rte_pipeline_table_entry_add(p->p, - table_id, - match_ll_ptr[i], - action_ll_ptr[i], - &found[i], - &data[i]); - if (status) { - n_rules = i; - break; - } - } - } - - /* Write response */ - rsp->status = 0; - rsp->table_rule_add_bulk.n_rules = n_rules; - - /* Free */ - free(found); - free(action_ll_ptr); - free(match_ll_ptr); - free(action_ll); - free(match_ll); - - return rsp; - -fail: - free(found); - free(action_ll_ptr); - free(match_ll_ptr); - free(action_ll); - free(match_ll); - - rsp->status = -1; - rsp->table_rule_add_bulk.n_rules = 0; - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_rule_delete(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - union table_rule_match_low_level match_ll; - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - struct softnic_table_rule_match *match = &req->table_rule_delete.match; - uint32_t table_id = req->id; - int key_found, status; - - status = match_convert(match, &match_ll, 0); - if (status) { - rsp->status = -1; - return rsp; - } - - rsp->status = rte_pipeline_table_entry_delete(p->p, - table_id, - &match_ll, - &key_found, - NULL); - - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - uint32_t table_id = req->id; - - rsp->status = rte_pipeline_table_default_entry_delete(p->p, - table_id, - NULL); - - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - uint32_t table_id = req->id; - void *data = req->table_rule_stats_read.data; - int clear = req->table_rule_stats_read.clear; - struct rte_table_action *a = p->table_data[table_id].a; - - rsp->status = rte_table_action_stats_read(a, - data, - &rsp->table_rule_stats_read.stats, - clear); - - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - uint32_t table_id = req->id; - uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id; - struct rte_table_action_meter_profile *profile = - &req->table_mtr_profile_add.profile; - struct rte_table_action *a = p->table_data[table_id].a; - - rsp->status = rte_table_action_meter_profile_add(a, - meter_profile_id, - profile); - - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - uint32_t table_id = req->id; - uint32_t meter_profile_id = - req->table_mtr_profile_delete.meter_profile_id; - struct rte_table_action *a = p->table_data[table_id].a; - - rsp->status = rte_table_action_meter_profile_delete(a, - meter_profile_id); - - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - uint32_t table_id = req->id; - void *data = req->table_rule_mtr_read.data; - uint32_t tc_mask = req->table_rule_mtr_read.tc_mask; - int clear = req->table_rule_mtr_read.clear; - struct rte_table_action *a = p->table_data[table_id].a; - - rsp->status = rte_table_action_meter_read(a, - data, - tc_mask, - &rsp->table_rule_mtr_read.stats, - clear); - - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - uint32_t table_id = req->id; - uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask; - struct rte_table_action_dscp_table *dscp_table = - &req->table_dscp_table_update.dscp_table; - struct rte_table_action *a = p->table_data[table_id].a; - - rsp->status = rte_table_action_dscp_table_update(a, - dscp_mask, - dscp_table); - - return rsp; -} - -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; - uint32_t table_id = req->id; - void *data = req->table_rule_ttl_read.data; - int clear = req->table_rule_ttl_read.clear; - struct rte_table_action *a = p->table_data[table_id].a; - - rsp->status = rte_table_action_ttl_read(a, - data, - &rsp->table_rule_ttl_read.stats, - clear); - - return rsp; -} - -static void -pipeline_msg_handle(struct pipeline_data *p) -{ - for ( ; ; ) { - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - - req = pipeline_msg_recv(p->msgq_req); - if (req == NULL) - break; - - switch (req->type) { - case PIPELINE_REQ_PORT_IN_STATS_READ: - rsp = pipeline_msg_handle_port_in_stats_read(p, req); - break; - - case PIPELINE_REQ_PORT_IN_ENABLE: - rsp = pipeline_msg_handle_port_in_enable(p, req); - break; - - case PIPELINE_REQ_PORT_IN_DISABLE: - rsp = pipeline_msg_handle_port_in_disable(p, req); - break; - - case PIPELINE_REQ_PORT_OUT_STATS_READ: - rsp = pipeline_msg_handle_port_out_stats_read(p, req); - break; - - case PIPELINE_REQ_TABLE_STATS_READ: - rsp = pipeline_msg_handle_table_stats_read(p, req); - break; - - case PIPELINE_REQ_TABLE_RULE_ADD: - rsp = pipeline_msg_handle_table_rule_add(p, req); - break; - - case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT: - rsp = pipeline_msg_handle_table_rule_add_default(p, req); - break; - - case PIPELINE_REQ_TABLE_RULE_ADD_BULK: - rsp = pipeline_msg_handle_table_rule_add_bulk(p, req); - break; - - case PIPELINE_REQ_TABLE_RULE_DELETE: - rsp = pipeline_msg_handle_table_rule_delete(p, req); - break; - - case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT: - rsp = pipeline_msg_handle_table_rule_delete_default(p, req); - break; - - case PIPELINE_REQ_TABLE_RULE_STATS_READ: - rsp = pipeline_msg_handle_table_rule_stats_read(p, req); - break; - - case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD: - rsp = pipeline_msg_handle_table_mtr_profile_add(p, req); - break; - - case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE: - rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req); - break; - - case PIPELINE_REQ_TABLE_RULE_MTR_READ: - rsp = pipeline_msg_handle_table_rule_mtr_read(p, req); - break; - - case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE: - rsp = pipeline_msg_handle_table_dscp_table_update(p, req); - break; - - case PIPELINE_REQ_TABLE_RULE_TTL_READ: - rsp = pipeline_msg_handle_table_rule_ttl_read(p, req); - break; - - default: - rsp = (struct pipeline_msg_rsp *)req; - rsp->status = -1; - } - - pipeline_msg_send(p->msgq_rsp, rsp); - } -} - -/** - * Data plane threads: main - */ -static int32_t -rte_pmd_softnic_run_internal(void *arg) -{ - struct rte_eth_dev *dev = arg; - struct pmd_internals *softnic; - struct softnic_thread_data *t; - uint32_t thread_id, j; - - softnic = dev->data->dev_private; - thread_id = rte_lcore_id(); - t = &softnic->thread_data[thread_id]; - t->iter++; - - /* Data Plane */ - for (j = 0; j < t->n_pipelines; j++) - rte_pipeline_run(t->p[j]); - - /* Control Plane */ - if ((t->iter & 0xFLLU) == 0) { - uint64_t time = rte_get_tsc_cycles(); - uint64_t time_next_min = UINT64_MAX; - - if (time < t->time_next_min) - return 0; - - /* Pipeline message queues */ - for (j = 0; j < t->n_pipelines; j++) { - struct pipeline_data *p = - &t->pipeline_data[j]; - uint64_t time_next = p->time_next; - - if (time_next <= time) { - pipeline_msg_handle(p); - rte_pipeline_flush(p->p); - time_next = time + p->timer_period; - p->time_next = time_next; - } - - if (time_next < time_next_min) - time_next_min = time_next; - } + if (time < time_next) + return 0; /* Thread message queues */ - { - uint64_t time_next = t->time_next; - - if (time_next <= time) { - thread_msg_handle(t); - time_next = time + t->timer_period; - t->time_next = time_next; - } - - if (time_next < time_next_min) - time_next_min = time_next; - } + thread_msg_handle(t); - t->time_next_min = time_next_min; + t->time_next = time_next + t->timer_period; } return 0;