From patchwork Tue Sep 11 14:20:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Pattan, Reshma" X-Patchwork-Id: 44578 X-Patchwork-Delegate: cristian.dumitrescu@intel.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 DFDF85F12; Tue, 11 Sep 2018 16:21:09 +0200 (CEST) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id 2FDC756A3 for ; Tue, 11 Sep 2018 16:21:00 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 11 Sep 2018 07:20:59 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,360,1531810800"; d="scan'208";a="69156896" Received: from sivswdev02.ir.intel.com (HELO localhost.localdomain) ([10.237.217.46]) by fmsmga007.fm.intel.com with ESMTP; 11 Sep 2018 07:20:58 -0700 From: Reshma Pattan To: dev@dpdk.org Cc: Cristian Dumitrescu , Reshma Pattan Date: Tue, 11 Sep 2018 15:20:40 +0100 Message-Id: <1536675645-10105-11-git-send-email-reshma.pattan@intel.com> X-Mailer: git-send-email 1.7.0.7 In-Reply-To: <1536251222-17275-1-git-send-email-reshma.pattan@intel.com> References: <1536251222-17275-1-git-send-email-reshma.pattan@intel.com> Subject: [dpdk-dev] [PATCH v2 10/15] net/softnic: validate and map flow with hash table match 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" Support for validating and mapping flow rule with HASH table match is added. As part of this, below helper functions are added. flow_rule_match_hash_get() hash_key_mask_is_same() Signed-off-by: Cristian Dumitrescu Signed-off-by: Reshma Pattan --- drivers/net/softnic/rte_eth_softnic_flow.c | 201 ++++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 1 deletion(-) diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c index 94af66391..dc3dd493b 100644 --- a/drivers/net/softnic/rte_eth_softnic_flow.c +++ b/drivers/net/softnic/rte_eth_softnic_flow.c @@ -791,7 +791,195 @@ flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused, return 0; } - static int +/*** + * Both *tmask* and *fmask* are byte arrays of size *tsize* and *fsize* + * respectively. + * They are located within a larger buffer at offsets *toffset* and *foffset* + * respectivelly. Both *tmask* and *fmask* represent bitmasks for the larger + * buffer. + * Question: are the two masks equivalent? + * + * Notes: + * 1. Offset basically indicates that the first offset bytes in the buffer + * are "don't care", so offset is equivalent to pre-pending an "all-zeros" + * array of *offset* bytes to the *mask*. + * 2. Each *mask* might contain a number of zero bytes at the beginning or + * at the end. + * 3. Bytes in the larger buffer after the end of the *mask* are also considered + * "don't care", so they are equivalent to appending an "all-zeros" array of + * bytes to the *mask*. + * + * Example: + * Buffer = [xx xx xx xx xx xx xx xx], buffer size = 8 bytes + * tmask = [00 22 00 33 00], toffset = 2, tsize = 5 + * => buffer mask = [00 00 00 22 00 33 00 00] + * fmask = [22 00 33], foffset = 3, fsize = 3 => + * => buffer mask = [00 00 00 22 00 33 00 00] + * Therefore, the tmask and fmask from this example are equivalent. + */ +static int +hash_key_mask_is_same(uint8_t *tmask, + size_t toffset, + size_t tsize, + uint8_t *fmask, + size_t foffset, + size_t fsize, + size_t *toffset_plus, + size_t *foffset_plus) +{ + size_t tpos; /* Position of first non-zero byte in the tmask buffer. */ + size_t fpos; /* Position of first non-zero byte in the fmask buffer. */ + + /* Compute tpos and fpos. */ + for (tpos = 0; tmask[tpos] == 0; tpos++) + ; + for (fpos = 0; fmask[fpos] == 0; fpos++) + ; + + if (toffset + tpos != foffset + fpos) + return 0; /* FALSE */ + + tsize -= tpos; + fsize -= fpos; + + if (tsize < fsize) { + size_t i; + + for (i = 0; i < tsize; i++) + if (tmask[tpos + i] != fmask[fpos + i]) + return 0; /* FALSE */ + + for ( ; i < fsize; i++) + if (fmask[fpos + i]) + return 0; /* FALSE */ + } else { + size_t i; + + for (i = 0; i < fsize; i++) + if (tmask[tpos + i] != fmask[fpos + i]) + return 0; /* FALSE */ + + for ( ; i < tsize; i++) + if (tmask[tpos + i]) + return 0; /* FALSE */ + } + + if (toffset_plus) + *toffset_plus = tpos; + + if (foffset_plus) + *foffset_plus = fpos; + + return 1; /* TRUE */ +} + +static int +flow_rule_match_hash_get(struct pmd_internals *softnic __rte_unused, + struct pipeline *pipeline __rte_unused, + struct softnic_table *table, + const struct rte_flow_attr *attr __rte_unused, + const struct rte_flow_item *item, + struct softnic_table_rule_match *rule_match, + struct rte_flow_error *error) +{ + struct softnic_table_rule_match_hash key, key_mask; + struct softnic_table_hash_params *params = &table->params.match.hash; + size_t offset = 0, length = 0, tpos, fpos; + int status; + + memset(&key, 0, sizeof(key)); + memset(&key_mask, 0, sizeof(key_mask)); + + /* VOID or disabled protos only, if any. */ + status = flow_item_skip_disabled_protos(&item, 0, &offset, error); + if (status) + return status; + + if (item->type == RTE_FLOW_ITEM_TYPE_END) + return rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "HASH: END detected too early"); + + /* VOID or any protocols (enabled or disabled). */ + for ( ; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { + union flow_item spec, mask; + size_t size; + int disabled, status; + + if (item->type == RTE_FLOW_ITEM_TYPE_VOID) + continue; + + status = flow_item_proto_preprocess(item, + &spec, + &mask, + &size, + &disabled, + error); + if (status) + return status; + + if (length + size > sizeof(key)) { + if (disabled) + break; + + return rte_flow_error_set(error, + ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "HASH: Item too big"); + } + + memcpy(&key.key[length], &spec, size); + memcpy(&key_mask.key[length], &mask, size); + length += size; + } + + if (item->type != RTE_FLOW_ITEM_TYPE_END) { + /* VOID or disabled protos only, if any. */ + status = flow_item_skip_disabled_protos(&item, 0, NULL, error); + if (status) + return status; + + /* END only. */ + if (item->type != RTE_FLOW_ITEM_TYPE_END) + return rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "HASH: Expecting END item"); + } + + /* Compare flow key mask against table key mask. */ + offset += sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM; + + if (!hash_key_mask_is_same(params->key_mask, + params->key_offset, + params->key_size, + key_mask.key, + offset, + length, + &tpos, + &fpos)) + return rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, + "HASH: Item list is not observing the match format"); + + /* Rule match. */ + memset(rule_match, 0, sizeof(*rule_match)); + rule_match->match_type = TABLE_HASH; + memcpy(&rule_match->match.hash.key[tpos], + &key.key[fpos], + RTE_MIN(sizeof(rule_match->match.hash.key) - tpos, + length - fpos)); + + return 0; +} + +static int flow_rule_match_get(struct pmd_internals *softnic, struct pipeline *pipeline, struct softnic_table *table, @@ -809,7 +997,18 @@ flow_rule_match_get(struct pmd_internals *softnic, item, rule_match, error); + /* FALLTHROUGH */ + + case TABLE_HASH: + return flow_rule_match_hash_get(softnic, + pipeline, + table, + attr, + item, + rule_match, + error); + default: return rte_flow_error_set(error, ENOTSUP,