From patchwork Thu Nov 30 20:08:43 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 31843 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 695231B19E; Thu, 30 Nov 2017 20:55:49 +0100 (CET) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by dpdk.org (Postfix) with ESMTP id 8691B1ADD3 for ; Thu, 30 Nov 2017 20:55:45 +0100 (CET) Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Nov 2017 11:55:45 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.45,343,1508828400"; d="scan'208";a="8083898" Received: from silpixa00381635.ir.intel.com (HELO silpixa00381635.ger.corp.intel.com) ([10.237.222.149]) by fmsmga004.fm.intel.com with ESMTP; 30 Nov 2017 11:55:44 -0800 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, ferruh.yigit@intel.com Date: Thu, 30 Nov 2017 20:08:43 +0000 Message-Id: <20171130200843.98621-3-jasvinder.singh@intel.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20171130200843.98621-1-jasvinder.singh@intel.com> References: <20171130200843.98621-1-jasvinder.singh@intel.com> Subject: [dpdk-dev] [PATCH 2/2] net/softnic: add flow classification ops X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" To manage and configure flow rules, implements operations to validate, create, destroy and flush the flow rules. Signed-off-by: Jasvinder Singh --- drivers/net/softnic/rte_eth_softnic_fc.c | 311 ++++++++++++++++++++++++++++++- 1 file changed, 307 insertions(+), 4 deletions(-) diff --git a/drivers/net/softnic/rte_eth_softnic_fc.c b/drivers/net/softnic/rte_eth_softnic_fc.c index 83f7fd3..e41eb57 100644 --- a/drivers/net/softnic/rte_eth_softnic_fc.c +++ b/drivers/net/softnic/rte_eth_softnic_fc.c @@ -330,6 +330,9 @@ fc_flow_uninit(struct pmd_internals *p) break; TAILQ_REMOVE(&p->soft.fc.flow_list, flow, node); + + free(flow->pattern); + free(flow->actions); free(flow); } } @@ -369,9 +372,309 @@ fc_free(struct pmd_internals *p) rte_free(p->soft.fc.pkts); } +static struct rte_flow * +fc_flow_search(struct pmd_internals *p, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[]) +{ + struct fc_flow_list *fl = &p->soft.fc.flow_list; + struct rte_flow *f; + uint32_t n_item, n_act, n_match_params; + + TAILQ_FOREACH(f, fl, node) { + n_item = 0; + n_act = 0; + n_match_params = 0; + + /* Check: Flow attr */ + if (memcmp(&f->attr, + (const void *)attr, sizeof(*attr))) + continue; + else + n_match_params += 1; + + /* Check: Flow pattern */ + while (pattern[n_item].type != RTE_FLOW_ITEM_TYPE_END) { + if (pattern[n_item].type != f->pattern[n_item].type) + n_match_params = 0; + + n_item++; + } + + if (n_match_params) + n_match_params += 1; + else + continue; + + /* Check: Flow action */ + while (actions[n_act].type != RTE_FLOW_ACTION_TYPE_END) { + if (actions[n_act].type != f->actions[n_act].type) + n_match_params = 0; + + n_act++; + } + + if (n_match_params) + n_match_params += 1; + else + continue; + + if (n_match_params == 3) + return f; + } + return NULL; +} + +static int rule_add_check(struct pmd_internals *p, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + struct rte_flow *flow; + uint32_t n_flow_rules; + + /** Check: Number of rules */ + n_flow_rules = p->soft.fc.n_flow_rules; + if (n_flow_rules >= p->params.soft.fc.nb_rules) { + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, + "Number of Flow rule exceeds."); + return -EINVAL; + } + + flow = fc_flow_search(p, attr, pattern, actions); + if (flow != NULL) { + rte_flow_error_set(error, + EEXIST, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, + "Flow rule exists."); + return -EEXIST; + } + + return 0; +} + +/* Flow rule validate */ +static int +pmd_flow_validate(__rte_unused struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + if (!pattern) { + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM_NUM, + NULL, + "NULL pattern."); + return -rte_errno; + } + + if (!actions) { + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION_NUM, + NULL, + "NULL action."); + return -rte_errno; + } + + if (!attr) { + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_ATTR, + NULL, + "NULL attribute."); + return -rte_errno; + } + + /* Add validate function */ + + return 0; +} + +/* Create flow rule */ +static struct rte_flow * +pmd_flow_create(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + struct pmd_internals *p = dev->data->dev_private; + struct fc_flow_list *fl = &p->soft.fc.flow_list; + struct rte_flow *f; + uint32_t n_item = 0, n_act = 0; + int status; + + /** Check: Attributes */ + if (!attr) { + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_ATTR, + NULL, + "NULL attribute."); + return NULL; + } + + /** Check: Pattern */ + if (!pattern) { + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM_NUM, + NULL, + "NULL pattern."); + return NULL; + } + + /** Check: Actions */ + if (!actions) { + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION_NUM, + NULL, + "NULL action."); + return NULL; + } + + /** Check: Rule */ + status = rule_add_check(p, attr, pattern, actions, error); + if (status) + return NULL; + + /** Add rule to the table */ + + /* Memory allocation */ + f = calloc(1, sizeof(struct rte_flow)); + if (f == NULL) { + rte_flow_error_set(error, + ENOMEM, + RTE_TM_ERROR_TYPE_UNSPECIFIED, + NULL, + "Failed to create flow."); + return NULL; + } + + /** Add attr to list */ + memcpy((void *)&f->attr, (const void *)attr, sizeof(*attr)); + + /** Allocate for pattern */ + while ((pattern + n_item)->type != RTE_FLOW_ITEM_TYPE_END) + n_item++; + + n_item++; + + f->pattern = calloc(n_item, sizeof(struct rte_flow_item)); + if (f->pattern) { + rte_flow_error_set(error, + ENOMEM, + RTE_TM_ERROR_TYPE_UNSPECIFIED, + NULL, + "Failed to create flow."); + return NULL; + } + + /** Add pattern */ + memcpy((void *)f->pattern, (const void *)pattern, sizeof(*f->pattern)); + + /** Allocate for action */ + while ((actions + n_act)->type != RTE_FLOW_ACTION_TYPE_END) + n_act++; + + n_act++; + + f->actions = calloc(n_act, sizeof(struct rte_flow_action)); + if (f->actions) { + rte_flow_error_set(error, + ENOMEM, + RTE_TM_ERROR_TYPE_UNSPECIFIED, + NULL, + "Failed to create flow."); + return NULL; + } + + /** Add actions */ + memcpy((void *)f->actions, (const void *)actions, sizeof(*f->actions)); + + TAILQ_INSERT_TAIL(fl, f, node); + p->soft.fc.n_flow_rules++; + + return f; +} + +/* Destroy flow rule */ +static int +pmd_flow_destroy(struct rte_eth_dev *dev, + struct rte_flow *flow, + struct rte_flow_error *error) +{ + struct pmd_internals *p = dev->data->dev_private; + struct fc_flow_list *fl = &p->soft.fc.flow_list; + struct rte_flow *f; + + /** Check: flow */ + if (!flow) { + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, + "NULL flow."); + return -EINVAL; + } + /* Check existing */ + f = fc_flow_search(p, &flow->attr, flow->pattern, flow->actions); + if (f == NULL) { + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, + "Flow not exist"); + return -EINVAL; + } + + /** Remove from Classifier table */ + + /** Remove from list */ + TAILQ_REMOVE(fl, f, node); + p->soft.fc.n_flow_rules--; + free(f); + + return 0; +} + +/* Destroy flow rules */ +static int +pmd_flow_flush(struct rte_eth_dev *dev, + __rte_unused struct rte_flow_error *error) +{ + struct pmd_internals *p = dev->data->dev_private; + + for ( ; ; ) { + struct rte_flow *f; + + f = TAILQ_FIRST(&p->soft.fc.flow_list); + if (f == NULL) + break; + + /** Remove from Classifier table */ + + /** Remove from list */ + TAILQ_REMOVE(&p->soft.fc.flow_list, f, node); + free(f); + } + + return 0; +} + const struct rte_flow_ops pmd_flow_ops = { - .validate = NULL, - .create = NULL, - .destroy = NULL, - .flush = NULL, + .validate = pmd_flow_validate, + .create = pmd_flow_create, + .destroy = pmd_flow_destroy, + .flush = pmd_flow_flush, };