From patchwork Sun Jun 2 15:24:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerin Jacob Kollanukkaran X-Patchwork-Id: 54081 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 DB37C1BB42; Sun, 2 Jun 2019 17:26:28 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by dpdk.org (Postfix) with ESMTP id AFEFC1B9A4 for ; Sun, 2 Jun 2019 17:26:22 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x52FKK4l020364; Sun, 2 Jun 2019 08:26:22 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0818; bh=PB4f3J2hons1wojb3dpqGrFDiIi8QBRGUHGgsuAoudk=; b=Jmq3SPnmztwvf36wndV3aVktJWumpM8X41v3HEcu4q9VxMIprb3Tf9AS9XQqdCZvc5Az WoHEetUtQNd5yGzax8/G+/arjM0giJ35oMr/fKaYWCwoyyEn7ew4lYan2TGzdSeXq4x/ me9MCjVJ2CgOvJbI3pNmFsICpLT7B02ARaLUa8Hi4UnEar3Yf4UVtud9VzXIlVfvBj2n 6xIObByAeQIgovXb0eTNTWp+jefA3mm37nqMLki3xDiKivRkvZXn0AXQ7iam5spGzyGc 6XrqUvjo2uwnhK/lHGFOM57AfVahXEbteGMJm7ruXDKIS6Ljpi6VXYp2YlrDVEngWmnu 7g== Received: from sc-exch01.marvell.com ([199.233.58.181]) by mx0b-0016f401.pphosted.com with ESMTP id 2survk4975-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Sun, 02 Jun 2019 08:26:22 -0700 Received: from SC-EXCH01.marvell.com (10.93.176.81) by SC-EXCH01.marvell.com (10.93.176.81) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Sun, 2 Jun 2019 08:26:20 -0700 Received: from maili.marvell.com (10.93.176.43) by SC-EXCH01.marvell.com (10.93.176.81) with Microsoft SMTP Server id 15.0.1367.3 via Frontend Transport; Sun, 2 Jun 2019 08:26:20 -0700 Received: from jerin-lab.marvell.com (jerin-lab.marvell.com [10.28.34.14]) by maili.marvell.com (Postfix) with ESMTP id C46433F703F; Sun, 2 Jun 2019 08:26:18 -0700 (PDT) From: To: , Jerin Jacob , Nithin Dabilpuram , Kiran Kumar K CC: , Vivek Sharma Date: Sun, 2 Jun 2019 20:54:10 +0530 Message-ID: <20190602152434.23996-35-jerinj@marvell.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190602152434.23996-1-jerinj@marvell.com> References: <20190602152434.23996-1-jerinj@marvell.com> MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-06-02_09:, , signatures=0 Subject: [dpdk-dev] [PATCH v1 34/58] net/octeontx2: flow utility functions 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" From: Kiran Kumar K First pass rte_flow utility functions for octeontx2. These will be used to communicate with AF driver. Signed-off-by: Kiran Kumar K Signed-off-by: Vivek Sharma --- drivers/net/octeontx2/Makefile | 1 + drivers/net/octeontx2/meson.build | 1 + drivers/net/octeontx2/otx2_flow_utils.c | 369 ++++++++++++++++++++++++ 3 files changed, 371 insertions(+) create mode 100644 drivers/net/octeontx2/otx2_flow_utils.c diff --git a/drivers/net/octeontx2/Makefile b/drivers/net/octeontx2/Makefile index b1c8e4e52..7773643af 100644 --- a/drivers/net/octeontx2/Makefile +++ b/drivers/net/octeontx2/Makefile @@ -39,6 +39,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX2_PMD) += \ otx2_lookup.c \ otx2_ethdev.c \ otx2_flow_ctrl.c \ + otx2_flow_utils.c \ otx2_ethdev_irq.c \ otx2_ethdev_ops.c \ otx2_ethdev_debug.c \ diff --git a/drivers/net/octeontx2/meson.build b/drivers/net/octeontx2/meson.build index 57d6c0a58..cd168c32f 100644 --- a/drivers/net/octeontx2/meson.build +++ b/drivers/net/octeontx2/meson.build @@ -12,6 +12,7 @@ sources = files( 'otx2_lookup.c', 'otx2_ethdev.c', 'otx2_flow_ctrl.c', + 'otx2_flow_utils.c', 'otx2_ethdev_irq.c', 'otx2_ethdev_ops.c', 'otx2_ethdev_debug.c', diff --git a/drivers/net/octeontx2/otx2_flow_utils.c b/drivers/net/octeontx2/otx2_flow_utils.c new file mode 100644 index 000000000..bf20d7319 --- /dev/null +++ b/drivers/net/octeontx2/otx2_flow_utils.c @@ -0,0 +1,369 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2019 Marvell International Ltd. + */ + +#include "otx2_ethdev.h" +#include "otx2_flow.h" + +int +otx2_flow_mcam_free_counter(struct otx2_mbox *mbox, uint16_t ctr_id) +{ + struct npc_mcam_oper_counter_req *req; + int rc; + + req = otx2_mbox_alloc_msg_npc_mcam_free_counter(mbox); + req->cntr = ctr_id; + otx2_mbox_msg_send(mbox, 0); + rc = otx2_mbox_get_rsp(mbox, 0, NULL); + + return rc; +} + +int +otx2_flow_mcam_read_counter(struct otx2_mbox *mbox, uint32_t ctr_id, + uint64_t *count) +{ + struct npc_mcam_oper_counter_req *req; + struct npc_mcam_oper_counter_rsp *rsp; + int rc; + + req = otx2_mbox_alloc_msg_npc_mcam_counter_stats(mbox); + req->cntr = ctr_id; + otx2_mbox_msg_send(mbox, 0); + rc = otx2_mbox_get_rsp(mbox, 0, (void *)&rsp); + + *count = rsp->stat; + return rc; +} + +int +otx2_flow_mcam_clear_counter(struct otx2_mbox *mbox, uint32_t ctr_id) +{ + struct npc_mcam_oper_counter_req *req; + int rc; + + req = otx2_mbox_alloc_msg_npc_mcam_clear_counter(mbox); + req->cntr = ctr_id; + otx2_mbox_msg_send(mbox, 0); + rc = otx2_mbox_get_rsp(mbox, 0, NULL); + + return rc; +} + +int +otx2_flow_mcam_free_entry(struct otx2_mbox *mbox, uint32_t entry) +{ + struct npc_mcam_free_entry_req *req; + int rc; + + req = otx2_mbox_alloc_msg_npc_mcam_free_entry(mbox); + req->entry = entry; + otx2_mbox_msg_send(mbox, 0); + rc = otx2_mbox_get_rsp(mbox, 0, NULL); + + return rc; +} + +int +otx2_flow_mcam_free_all_entries(struct otx2_mbox *mbox) +{ + struct npc_mcam_free_entry_req *req; + int rc; + + req = otx2_mbox_alloc_msg_npc_mcam_free_entry(mbox); + req->all = 1; + otx2_mbox_msg_send(mbox, 0); + rc = otx2_mbox_get_rsp(mbox, 0, NULL); + + return rc; +} + +static void +flow_prep_mcam_ldata(uint8_t *ptr, const uint8_t *data, int len) +{ + int idx; + + for (idx = 0; idx < len; idx++) + ptr[idx] = data[len - 1 - idx]; +} + +static size_t +flow_check_copysz(size_t size, size_t len) +{ + if (len <= size) + return len; + + rte_panic("String op-overflow"); +} + +static inline int +flow_mem_is_zero(const void *mem, int len) +{ + const char *m = mem; + int i; + + for (i = 0; i < len; i++) { + if (m[i] != 0) + return 0; + } + return 1; +} + +void +otx2_flow_get_hw_supp_mask(struct otx2_parse_state *pst, + struct otx2_flow_item_info *info, int lid, int lt) +{ + struct npc_xtract_info *xinfo; + char *hw_mask = info->hw_mask; + int i, j; + int intf; + + intf = pst->flow->nix_intf; + xinfo = pst->npc->prx_dxcfg[intf][lid][lt].xtract; + memset(hw_mask, 0, info->len); + + for (i = 0; i < NPC_MAX_LD; i++) { + int max_off = xinfo[i].hdr_off + xinfo[i].len; + + if (xinfo[i].enable == 0) + continue; + + if (max_off > info->len) + max_off = info->len; + + for (j = xinfo[i].hdr_off; j < max_off; j++) + hw_mask[j] = 0xff; + } +} + +int +otx2_flow_update_parse_state(struct otx2_parse_state *pst, + struct otx2_flow_item_info *info, int lid, int lt, + uint8_t flags) +{ + uint8_t int_info_mask[NPC_MAX_EXTRACT_DATA_LEN]; + uint8_t int_info[NPC_MAX_EXTRACT_DATA_LEN]; + struct npc_lid_lt_xtract_info *xinfo; + int len = 0; + int intf; + int i; + + otx2_npc_dbg("Parse state function info mask total %s", + (const uint8_t *)info->mask); + + pst->layer_mask |= lid; + pst->lt[lid] = lt; + pst->flags[lid] = flags; + + intf = pst->flow->nix_intf; + xinfo = &pst->npc->prx_dxcfg[intf][lid][lt]; + otx2_npc_dbg("Is_terminating = %d", xinfo->is_terminating); + if (xinfo->is_terminating) + pst->terminate = 1; + + /* Need to check if flags are supported but in latest + * KPU profile, flags are used as enumeration! No way, + * it can be validated unless MBOX is changed to return + * set of valid values out of 2**8 possible values. + */ + if (info->spec == NULL) { /* Nothing to match */ + otx2_npc_dbg("Info spec NULL"); + goto done; + } + + /* Copy spec and mask into mcam match string, mask. + * Since both RTE FLOW and OTX2 MCAM use network-endianness + * for data, we are saved from nasty conversions. + */ + for (i = 0; i < NPC_MAX_LD; i++) { + struct npc_xtract_info *x; + int k, idx; + + x = &xinfo->xtract[i]; + len = x->len; + + if (x->enable == 0) + continue; + + otx2_npc_dbg("x->hdr_off = %d, len = %d, info->len = %d," + "x->key_off = %d", x->hdr_off, len, info->len, + x->key_off); + + if (x->hdr_off + len > info->len) + len = info->len - x->hdr_off; + + /* Check for over-write of previous layer */ + if (!flow_mem_is_zero(pst->mcam_mask + x->key_off, + len)) { + /* Cannot support this data match */ + rte_flow_error_set(pst->error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, + pst->pattern, + "Extraction unsupported"); + return -rte_errno; + } + + len = flow_check_copysz((OTX2_MAX_MCAM_WIDTH_DWORDS * 8) + - x->key_off, + len); + /* Need to reverse complete structure so that dest addr is at + * MSB so as to program the MCAM using mcam_data & mcam_mask + * arrays + */ + flow_prep_mcam_ldata(int_info, + (const uint8_t *)info->spec + x->hdr_off, + x->len); + flow_prep_mcam_ldata(int_info_mask, + (const uint8_t *)info->mask + x->hdr_off, + x->len); + + otx2_npc_dbg("Spec: "); + for (k = 0; k < info->len; k++) + otx2_npc_dbg("0x%.2x ", + ((const uint8_t *)info->spec)[k]); + + otx2_npc_dbg("Int_info: "); + for (k = 0; k < info->len; k++) + otx2_npc_dbg("0x%.2x ", int_info[k]); + + memcpy(pst->mcam_mask + x->key_off, int_info_mask, len); + memcpy(pst->mcam_data + x->key_off, int_info, len); + + otx2_npc_dbg("Parse state mcam data & mask"); + for (idx = 0; idx < len ; idx++) + otx2_npc_dbg("data[%d]: 0x%x, mask[%d]: 0x%x", idx, + *(pst->mcam_data + idx + x->key_off), idx, + *(pst->mcam_mask + idx + x->key_off)); + } + +done: + /* Next pattern to parse by subsequent layers */ + pst->pattern++; + return 0; +} + +static inline int +flow_range_is_valid(const char *spec, const char *last, const char *mask, + int len) +{ + /* Mask must be zero or equal to spec as we do not support + * non-contiguous ranges. + */ + while (len--) { + if (last[len] && + (spec[len] & mask[len]) != (last[len] & mask[len])) + return 0; /* False */ + } + return 1; +} + + +static inline int +flow_mask_is_supported(const char *mask, const char *hw_mask, int len) +{ + /* + * If no hw_mask, assume nothing is supported. + * mask is never NULL + */ + if (hw_mask == NULL) + return flow_mem_is_zero(mask, len); + + while (len--) { + if ((mask[len] | hw_mask[len]) != hw_mask[len]) + return 0; /* False */ + } + return 1; +} + +int +otx2_flow_parse_item_basic(const struct rte_flow_item *item, + struct otx2_flow_item_info *info, + struct rte_flow_error *error) +{ + /* Item must not be NULL */ + if (item == NULL) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, NULL, + "Item is NULL"); + return -rte_errno; + } + /* If spec is NULL, both mask and last must be NULL, this + * makes it to match ANY value (eq to mask = 0). + * Setting either mask or last without spec is an error + */ + if (item->spec == NULL) { + if (item->last == NULL && item->mask == NULL) { + info->spec = NULL; + return 0; + } + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "mask or last set without spec"); + return -rte_errno; + } + + /* We have valid spec */ + info->spec = item->spec; + + /* If mask is not set, use default mask, err if default mask is + * also NULL. + */ + if (item->mask == NULL) { + otx2_npc_dbg("Item mask null, using default mask"); + if (info->def_mask == NULL) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "No mask or default mask given"); + return -rte_errno; + } + info->mask = info->def_mask; + } else { + info->mask = item->mask; + } + + /* mask specified must be subset of hw supported mask + * mask | hw_mask == hw_mask + */ + if (!flow_mask_is_supported(info->mask, info->hw_mask, info->len)) { + rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, + item, "Unsupported field in the mask"); + return -rte_errno; + } + + /* Now we have spec and mask. OTX2 does not support non-contiguous + * range. We should have either: + * - spec & mask == last & mask or, + * - last == 0 or, + * - last == NULL + */ + if (item->last != NULL && !flow_mem_is_zero(item->last, info->len)) { + if (!flow_range_is_valid(item->spec, item->last, info->mask, + info->len)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Unsupported range for match"); + return -rte_errno; + } + } + + return 0; +} + +void +otx2_flow_keyx_compress(uint64_t *data, uint32_t nibble_mask) +{ + uint64_t cdata[2] = {0ULL, 0ULL}, nibble; + int i, j = 0; + + for (i = 0; i < NPC_MAX_KEY_NIBBLES; i++) { + if (nibble_mask & (1 << i)) { + nibble = (data[i / 16] >> ((i & 0xf) * 4)) & 0xf; + cdata[j / 16] |= (nibble << ((j & 0xf) * 4)); + j += 1; + } + } + + data[0] = cdata[0]; + data[1] = cdata[1]; +} +