From patchwork Mon Aug 7 13:48:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: edward.cree@amd.com X-Patchwork-Id: 13344279 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 542481095F for ; Mon, 7 Aug 2023 13:49:37 +0000 (UTC) Received: from NAM12-MW2-obe.outbound.protection.outlook.com (mail-mw2nam12on2046.outbound.protection.outlook.com [40.107.244.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2D6DB1703 for ; Mon, 7 Aug 2023 06:49:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=k+BOXaHI71pzgI9vlE502dZQc6q/4l3uVzcPXGjorpvRT/uOUXP1uszFDLsxrbzJuvj/Z5dWPzn6388uS0cgp9IGGlc4lvWbOwXLpqhp56aFGWwVJEhDmkmFLAUw+wSnvSE1dG2S5zkqfq0WwUVUFM1BGFLW+rLhlthGdm34jxUOhKSZvy5EZsvaisjqq+iiDIz3H6IC/pk01rIj00fSa2CEmqa95bYYVsr1K2SBh9S2W0QDNssq04JIt9Tk3I3GR8ycqHPx5pezx5+EdUs9/niPThJXvEUx4Ma2bPoQYZLsl2qWgAMCnL2t7AMkprOvTFBYfFm3F514y4DqdpYA4A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=0oN+5kTYFvfeL3m0yJeYfZtKna5MnR9Cd7BZAad79ug=; b=NfMxg0IkhdA7SagrUY+T6O/2WWI5jLD8pBpDr2D08jdQmGx3Ap6F/xPV/TSfYcYpE1QpiIIOucq4hlLk1DVDOnX/axwKA9HopEC94xnFAG8Lo5lEZh/chHIAvkSl12E0M6Jrjsype6q71uYtfGPCJSGUi+mG0nz9ydtXvaYGRyO7bfrRBgmoUllu2am7L5HfRKCJwsyik1Ub2GEkbT+x2TdP2gZfrQNLZ+B1h4u3D9l1rDzu5NFFVhjLoaBU1WYZ0wc9bCWxXFhwC8v2K7OWBF4cAohRrThX3OOcuvWST6g+51qAurgf98C2vW+yjKCzHKpHhlxxgQqnmtkQzZlbpg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=davemloft.net smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=0oN+5kTYFvfeL3m0yJeYfZtKna5MnR9Cd7BZAad79ug=; b=G3HMJjmxyDQzeqDSXTA+mr7o/NcgzHuS5bayC9cewDx4xCgLaInFYNPDNNs3QK0Ei8r7x867tHVb1HM9Z9aQAp8wV4fRZFUyqvc5RMq3cjp/W+sthbry5uNp/8VV1BuanNx5pfrfjkSQY/saYwGQgVjbcrmpw0JzyKLeV9pERR0= Received: from SJ0PR05CA0137.namprd05.prod.outlook.com (2603:10b6:a03:33d::22) by DM6PR12MB4107.namprd12.prod.outlook.com (2603:10b6:5:218::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6652.26; Mon, 7 Aug 2023 13:49:17 +0000 Received: from CO1PEPF000042A7.namprd03.prod.outlook.com (2603:10b6:a03:33d:cafe::d) by SJ0PR05CA0137.outlook.office365.com (2603:10b6:a03:33d::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6678.15 via Frontend Transport; Mon, 7 Aug 2023 13:49:16 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by CO1PEPF000042A7.mail.protection.outlook.com (10.167.243.36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6652.19 via Frontend Transport; Mon, 7 Aug 2023 13:49:15 +0000 Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Mon, 7 Aug 2023 08:49:13 -0500 Received: from xcbecree41x.xilinx.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27 via Frontend Transport; Mon, 7 Aug 2023 08:49:12 -0500 From: To: , , , , CC: Edward Cree , , , Pieter Jansen van Vuuren , Simon Horman Subject: [PATCH v2 net-next 1/7] sfc: add MAE table machinery for conntrack table Date: Mon, 7 Aug 2023 14:48:05 +0100 Message-ID: X-Mailer: git-send-email 2.27.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PEPF000042A7:EE_|DM6PR12MB4107:EE_ X-MS-Office365-Filtering-Correlation-Id: 863461eb-e3a6-45b5-6e09-08db974d1744 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 2DA8TBteEmyZelse2PLHjvb1EjhrvNqFIW1aJDrIKzhkyODWc65IrNKISMj9GkDYljbbToiDIcp/56beccqcykyPgXHYGjlK2r5qnz4Ubs5QuDaX6ydGuGi7L+ByPeKaGek3zUV34XD+u08+0SYK28wgr9bl/Rgk0C7OjuFFF4T50XJ8TJZzpv9pQpdF+SjYxFUMqp+2C6gQDaADVEuNkAEW84FSafwcmS3HowKMQkapBpstJmreyjIR4C54j7ayLQFNK+KTaRjvFvWEGiGkk8HYil7NUlhK9M6sEnOYJiFqLflQ/UFWBR0+k2oXNlJs5zDmEwQwGLr4tk7kpEqGL4mLnGKFx7GmfmpeQjUxhNPKykvLxUcW2qnD+qVmssk+WFkH+pUi7WsxWh/eGEid0kegCAfQpW8PPk6Q/2p5lzzR/NyIAl/3pP9ccd7mdXzzlbrnsz9V2qs1aeTZg2vwr5MopJtxd2qapCy1xsKPGE7Jd/Pi1timH3hypIE+j1n4yofmQ61lHo9P9p14MGyzVlx9DVBPwM3FsxIxGdNXskDg8jMhA94a3nG07ojF9prr5yHIWyejuBf/Z3GfYLcU8P0vb/yN+EBkxHFfYey4o2RRyEdhKNVyEp8chwdy1D+LNSfST+IEYN/+53VFEOroh5QZK1Wbn2JwRXIhFErsjYsrtlY1sXBWCwiVdZ+IZ4BU9b9izPJYHNKKdUF3+iqSDjfLBSiWiimrnD8MpDdjo3b6Y20PVNQrfQib7cQJujcD833lghFXE+sM/LMtgNDXYA== X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:SATLEXMB04.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230028)(4636009)(39860400002)(396003)(136003)(376002)(346002)(82310400008)(451199021)(1800799003)(186006)(46966006)(36840700001)(40470700004)(36860700001)(36756003)(86362001)(55446002)(83380400001)(81166007)(356005)(82740400003)(40460700003)(40480700001)(9686003)(6666004)(336012)(26005)(316002)(41300700001)(70206006)(4326008)(478600001)(110136005)(54906003)(30864003)(2876002)(2906002)(5660300002)(426003)(47076005)(8936002)(8676002)(70586007)(36900700001);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Aug 2023 13:49:15.9974 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 863461eb-e3a6-45b5-6e09-08db974d1744 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CO1PEPF000042A7.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR12MB4107 X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_SPF_HELO, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Edward Cree Access to the connection tracking table in EF100 hardware is through a "generic" table mechanism, whereby a firmware call at probe time gives the driver a description of the field widths and offsets, so that the driver can then construct key and response bitstrings at runtime. Probe the NIC for this information and populate the needed metadata into a new meta_ct field of struct efx_tc_state. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree --- drivers/net/ethernet/sfc/mae.c | 250 ++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/mae.h | 3 + drivers/net/ethernet/sfc/mcdi.h | 3 + drivers/net/ethernet/sfc/tc.c | 9 +- drivers/net/ethernet/sfc/tc.h | 44 ++++++ 5 files changed, 308 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index 0cab508f2f9d..33ae2c852b44 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -227,6 +227,256 @@ void efx_mae_counters_grant_credits(struct work_struct *work) rx_queue->granted_count += credits; } +static int efx_mae_table_get_desc(struct efx_nic *efx, + struct efx_tc_table_desc *desc, + u32 table_id) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_TABLE_DESCRIPTOR_OUT_LEN(16)); + MCDI_DECLARE_BUF(inbuf, MC_CMD_TABLE_DESCRIPTOR_IN_LEN); + unsigned int offset = 0, i; + size_t outlen; + int rc; + + memset(desc, 0, sizeof(*desc)); + + MCDI_SET_DWORD(inbuf, TABLE_DESCRIPTOR_IN_TABLE_ID, table_id); +more: + MCDI_SET_DWORD(inbuf, TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX, offset); + rc = efx_mcdi_rpc(efx, MC_CMD_TABLE_DESCRIPTOR, inbuf, sizeof(inbuf), + outbuf, sizeof(outbuf), &outlen); + if (rc) + goto fail; + if (outlen < MC_CMD_TABLE_DESCRIPTOR_OUT_LEN(1)) { + rc = -EIO; + goto fail; + } + if (!offset) { /* first iteration: get metadata */ + desc->type = MCDI_WORD(outbuf, TABLE_DESCRIPTOR_OUT_TYPE); + desc->key_width = MCDI_WORD(outbuf, TABLE_DESCRIPTOR_OUT_KEY_WIDTH); + desc->resp_width = MCDI_WORD(outbuf, TABLE_DESCRIPTOR_OUT_RESP_WIDTH); + desc->n_keys = MCDI_WORD(outbuf, TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS); + desc->n_resps = MCDI_WORD(outbuf, TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS); + desc->n_prios = MCDI_WORD(outbuf, TABLE_DESCRIPTOR_OUT_N_PRIORITIES); + desc->flags = MCDI_BYTE(outbuf, TABLE_DESCRIPTOR_OUT_FLAGS); + rc = -EOPNOTSUPP; + if (desc->flags) + goto fail; + desc->scheme = MCDI_BYTE(outbuf, TABLE_DESCRIPTOR_OUT_SCHEME); + if (desc->scheme) + goto fail; + rc = -ENOMEM; + desc->keys = kcalloc(desc->n_keys, + sizeof(struct efx_tc_table_field_fmt), + GFP_KERNEL); + if (!desc->keys) + goto fail; + desc->resps = kcalloc(desc->n_resps, + sizeof(struct efx_tc_table_field_fmt), + GFP_KERNEL); + if (!desc->resps) + goto fail; + } + /* FW could have returned more than the 16 field_descrs we + * made room for in our outbuf + */ + outlen = min(outlen, sizeof(outbuf)); + for (i = 0; i + offset < desc->n_keys + desc->n_resps; i++) { + struct efx_tc_table_field_fmt *field; + MCDI_DECLARE_STRUCT_PTR(fdesc); + + if (outlen < MC_CMD_TABLE_DESCRIPTOR_OUT_LEN(i + 1)) { + offset += i; + goto more; + } + if (i + offset < desc->n_keys) + field = desc->keys + i + offset; + else + field = desc->resps + (i + offset - desc->n_keys); + fdesc = MCDI_ARRAY_STRUCT_PTR(outbuf, + TABLE_DESCRIPTOR_OUT_FIELDS, i); + field->field_id = MCDI_STRUCT_WORD(fdesc, + TABLE_FIELD_DESCR_FIELD_ID); + field->lbn = MCDI_STRUCT_WORD(fdesc, TABLE_FIELD_DESCR_LBN); + field->width = MCDI_STRUCT_WORD(fdesc, TABLE_FIELD_DESCR_WIDTH); + field->masking = MCDI_STRUCT_BYTE(fdesc, TABLE_FIELD_DESCR_MASK_TYPE); + field->scheme = MCDI_STRUCT_BYTE(fdesc, TABLE_FIELD_DESCR_SCHEME); + } + return 0; + +fail: + kfree(desc->keys); + kfree(desc->resps); + return rc; +} + +static int efx_mae_table_hook_find(u16 n_fields, + struct efx_tc_table_field_fmt *fields, + u16 field_id) +{ + unsigned int i; + + for (i = 0; i < n_fields; i++) { + if (fields[i].field_id == field_id) + return i; + } + return -EPROTO; +} + +#define TABLE_FIND_KEY(_desc, _id) \ + efx_mae_table_hook_find((_desc)->n_keys, (_desc)->keys, _id) +#define TABLE_FIND_RESP(_desc, _id) \ + efx_mae_table_hook_find((_desc)->n_resps, (_desc)->resps, _id) + +#define TABLE_HOOK_KEY(_meta, _name, _mcdi_name) ({ \ + int _rc = TABLE_FIND_KEY(&_meta->desc, TABLE_FIELD_ID_##_mcdi_name); \ + \ + if (_rc > U8_MAX) \ + _rc = -EOPNOTSUPP; \ + if (_rc >= 0) { \ + _meta->keys._name##_idx = _rc; \ + _rc = 0; \ + } \ + _rc; \ +}) +#define TABLE_HOOK_RESP(_meta, _name, _mcdi_name) ({ \ + int _rc = TABLE_FIND_RESP(&_meta->desc, TABLE_FIELD_ID_##_mcdi_name); \ + \ + if (_rc > U8_MAX) \ + _rc = -EOPNOTSUPP; \ + if (_rc >= 0) { \ + _meta->resps._name##_idx = _rc; \ + _rc = 0; \ + } \ + _rc; \ +}) + +static int efx_mae_table_hook_ct(struct efx_nic *efx, + struct efx_tc_table_ct *meta_ct) +{ + int rc; + + rc = TABLE_HOOK_KEY(meta_ct, eth_proto, ETHER_TYPE); + if (rc) + return rc; + rc = TABLE_HOOK_KEY(meta_ct, ip_proto, IP_PROTO); + if (rc) + return rc; + rc = TABLE_HOOK_KEY(meta_ct, src_ip, SRC_IP); + if (rc) + return rc; + rc = TABLE_HOOK_KEY(meta_ct, dst_ip, DST_IP); + if (rc) + return rc; + rc = TABLE_HOOK_KEY(meta_ct, l4_sport, SRC_PORT); + if (rc) + return rc; + rc = TABLE_HOOK_KEY(meta_ct, l4_dport, DST_PORT); + if (rc) + return rc; + rc = TABLE_HOOK_KEY(meta_ct, zone, DOMAIN); + if (rc) + return rc; + rc = TABLE_HOOK_RESP(meta_ct, dnat, NAT_DIR); + if (rc) + return rc; + rc = TABLE_HOOK_RESP(meta_ct, nat_ip, NAT_IP); + if (rc) + return rc; + rc = TABLE_HOOK_RESP(meta_ct, l4_natport, NAT_PORT); + if (rc) + return rc; + rc = TABLE_HOOK_RESP(meta_ct, mark, CT_MARK); + if (rc) + return rc; + rc = TABLE_HOOK_RESP(meta_ct, counter_id, COUNTER_ID); + if (rc) + return rc; + meta_ct->hooked = true; + return 0; +} + +static void efx_mae_table_free_desc(struct efx_tc_table_desc *desc) +{ + kfree(desc->keys); + kfree(desc->resps); + memset(desc, 0, sizeof(*desc)); +} + +static bool efx_mae_check_table_exists(struct efx_nic *efx, u32 tbl_req) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_TABLE_LIST_OUT_LEN(16)); + MCDI_DECLARE_BUF(inbuf, MC_CMD_TABLE_LIST_IN_LEN); + u32 tbl_id, tbl_total, tbl_cnt, pos = 0; + size_t outlen, msg_max; + bool ct_tbl = false; + int rc, idx; + + msg_max = sizeof(outbuf); + efx->tc->meta_ct.hooked = false; +more: + memset(outbuf, 0, sizeof(*outbuf)); + MCDI_SET_DWORD(inbuf, TABLE_LIST_IN_FIRST_TABLE_ID_INDEX, pos); + rc = efx_mcdi_rpc(efx, MC_CMD_TABLE_LIST, inbuf, sizeof(inbuf), outbuf, + msg_max, &outlen); + if (rc) + return false; + + if (outlen < MC_CMD_TABLE_LIST_OUT_LEN(1)) + return false; + + tbl_total = MCDI_DWORD(outbuf, TABLE_LIST_OUT_N_TABLES); + tbl_cnt = MC_CMD_TABLE_LIST_OUT_TABLE_ID_NUM(min(outlen, msg_max)); + + for (idx = 0; idx < tbl_cnt; idx++) { + tbl_id = MCDI_ARRAY_DWORD(outbuf, TABLE_LIST_OUT_TABLE_ID, idx); + if (tbl_id == tbl_req) { + ct_tbl = true; + break; + } + } + + pos += tbl_cnt; + if (!ct_tbl && pos < tbl_total) + goto more; + + return ct_tbl; +} + +int efx_mae_get_tables(struct efx_nic *efx) +{ + int rc; + + efx->tc->meta_ct.hooked = false; + if (efx_mae_check_table_exists(efx, TABLE_ID_CONNTRACK_TABLE)) { + rc = efx_mae_table_get_desc(efx, &efx->tc->meta_ct.desc, + TABLE_ID_CONNTRACK_TABLE); + if (rc) { + pci_info(efx->pci_dev, + "FW does not support conntrack desc rc %d\n", + rc); + return 0; + } + + rc = efx_mae_table_hook_ct(efx, &efx->tc->meta_ct); + if (rc) { + pci_info(efx->pci_dev, + "FW does not support conntrack hook rc %d\n", + rc); + return 0; + } + } else { + pci_info(efx->pci_dev, + "FW does not support conntrack table\n"); + } + return 0; +} + +void efx_mae_free_tables(struct efx_nic *efx) +{ + efx_mae_table_free_desc(&efx->tc->meta_ct.desc); + efx->tc->meta_ct.hooked = false; +} + static int efx_mae_get_basic_caps(struct efx_nic *efx, struct mae_caps *caps) { MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_GET_CAPS_OUT_LEN); diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h index 24abfe509690..afdf738254b2 100644 --- a/drivers/net/ethernet/sfc/mae.h +++ b/drivers/net/ethernet/sfc/mae.h @@ -66,6 +66,9 @@ int efx_mae_start_counters(struct efx_nic *efx, struct efx_rx_queue *rx_queue); int efx_mae_stop_counters(struct efx_nic *efx, struct efx_rx_queue *rx_queue); void efx_mae_counters_grant_credits(struct work_struct *work); +int efx_mae_get_tables(struct efx_nic *efx); +void efx_mae_free_tables(struct efx_nic *efx); + #define MAE_NUM_FIELDS (MAE_FIELD_ENC_VNET_ID + 1) struct mae_caps { diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 454e9d51a4c2..995a26686fd8 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -221,6 +221,9 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); #define MCDI_BYTE(_buf, _field) \ ((void)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 1), \ *MCDI_PTR(_buf, _field)) +#define MCDI_STRUCT_BYTE(_buf, _field) \ + ((void)BUILD_BUG_ON_ZERO(_field ## _LEN != 1), \ + *MCDI_STRUCT_PTR(_buf, _field)) #define MCDI_SET_WORD(_buf, _field, _value) do { \ BUILD_BUG_ON(MC_CMD_ ## _field ## _LEN != 2); \ BUILD_BUG_ON(MC_CMD_ ## _field ## _OFST & 1); \ diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 4dc881159246..4dc979fdc968 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -1658,13 +1658,19 @@ int efx_init_tc(struct efx_nic *efx) if (rc) return rc; rc = efx_tc_configure_fallback_acts_reps(efx); + if (rc) + return rc; + rc = efx_mae_get_tables(efx); if (rc) return rc; efx->tc->up = true; rc = flow_indr_dev_register(efx_tc_indr_setup_cb, efx); if (rc) - return rc; + goto out_free; return 0; +out_free: + efx_mae_free_tables(efx); + return rc; } void efx_fini_tc(struct efx_nic *efx) @@ -1680,6 +1686,7 @@ void efx_fini_tc(struct efx_nic *efx) efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.pf); efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.reps); efx->tc->up = false; + efx_mae_free_tables(efx); } /* At teardown time, all TC filter rules (and thus all resources they created) diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index 1549c3df43bb..27592f10b536 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -143,6 +143,48 @@ enum efx_tc_rule_prios { EFX_TC_PRIO__NUM }; +struct efx_tc_table_field_fmt { + u16 field_id; + u16 lbn; + u16 width; + u8 masking; + u8 scheme; +}; + +struct efx_tc_table_desc { + u16 type; + u16 key_width; + u16 resp_width; + u16 n_keys; + u16 n_resps; + u16 n_prios; + u8 flags; + u8 scheme; + struct efx_tc_table_field_fmt *keys; + struct efx_tc_table_field_fmt *resps; +}; + +struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ + struct efx_tc_table_desc desc; + bool hooked; + struct { /* indices of named fields within @desc.keys */ + u8 eth_proto_idx; + u8 ip_proto_idx; + u8 src_ip_idx; /* either v4 or v6 */ + u8 dst_ip_idx; + u8 l4_sport_idx; + u8 l4_dport_idx; + u8 zone_idx; /* for TABLE_FIELD_ID_DOMAIN */ + } keys; + struct { /* indices of named fields within @desc.resps */ + u8 dnat_idx; + u8 nat_ip_idx; + u8 l4_natport_idx; + u8 mark_idx; + u8 counter_id_idx; + } resps; +}; + /** * struct efx_tc_state - control plane data for TC offload * @@ -155,6 +197,7 @@ enum efx_tc_rule_prios { * @encap_match_ht: Hashtable of TC encap matches * @match_action_ht: Hashtable of TC match-action rules * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) + * @meta_ct: MAE table layout for conntrack table * @reps_mport_id: MAE port allocated for representor RX * @reps_filter_uc: VNIC filter for representor unicast RX (promisc) * @reps_filter_mc: VNIC filter for representor multicast RX (allmulti) @@ -186,6 +229,7 @@ struct efx_tc_state { struct rhashtable encap_match_ht; struct rhashtable match_action_ht; struct rhashtable neigh_ht; + struct efx_tc_table_ct meta_ct; u32 reps_mport_id, reps_mport_vport_id; s32 reps_filter_uc, reps_filter_mc; bool flush_counters; From patchwork Mon Aug 7 13:48:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: edward.cree@amd.com X-Patchwork-Id: 13344278 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A7406107AC for ; Mon, 7 Aug 2023 13:49:35 +0000 (UTC) Received: from NAM12-BN8-obe.outbound.protection.outlook.com (mail-bn8nam12on2053.outbound.protection.outlook.com [40.107.237.53]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 946E4172A for ; Mon, 7 Aug 2023 06:49:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=cBfRr7mS4caB9f27oGMHps+p5aGHSte+N/Csk4mz+SVigwOUPYS/y48MMH5K/wqumWJ2ZvBSI5Q1V/F+1+YrK8y1NwpIuqEWWIMHn9AD5SeOv+CbxG848za7R1IOjttRs1KtmhL0J7tcMIA5V83R0qojBlU8tUNLqfnB8aO1az0mwqzHUJsCyMb77i6V26PTP31kPTj8SvzFOvPe7jLy2PJSG9++jpAb/wxcmtdr3BHiIcm9glHlQq/ZjzcU/vwVx8WVfRMepIKgx9XjaS3aYS0C++1KuDrDKa+hRsIyp7FKx7Tc/0/s96UB7SaK+MG0cXTprZaUEgL+fre+0LrmXg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=8i1K5mOlDU7uP0/QQpH+v3n5tCe0o8+6YYEQIAgp/vs=; b=gQ/Jh2JWXT5kNmbYUPcJ62v65iFYF1RTxKP6StTRI7Ra6EHSPr3kW/XjjDwB7T75ZxBHnIbrdGGGK4/IT4w3mYAdNmQIur+R9IyVqkIYC0VITIjXLDCt7S6xSf29MDzlON6+/9h51qYRWXeIjDOmMSF+5m2EvSLHk0cu9+lElqNgbq+Xn0WphRzhZF8mQrVYQ8EOdvwzrEzxBBIpc7mmNTr9xfMZXKpZSxrkQWV+w7XdfurWXtWwHs19BQpBAqT43Vhzq3+SpWBFcQTW5AHEeJSdjROY/vKlXodF4Hh+JB0u0bmFgXaLGMyzwpHpYdhG64rLSxPJbXy+7KNGlGN4kA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=davemloft.net smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=8i1K5mOlDU7uP0/QQpH+v3n5tCe0o8+6YYEQIAgp/vs=; b=I5gCpTB5x2sGDSV7w+5YSM32HbWsDMoUUoKa+FOajeKfLWPMALSOeyDgaU6yhiQqyICjq23MhmdGV7WN/+tpszpWhPuX7yA/lv9g7AZb2nzwMgtb3tNJmMsxm+X+PV8qFijB4hQ9+C984upTFf+2Ztfq1NG/i6+dvBYHZKdPGG8= Received: from CYZPR19CA0014.namprd19.prod.outlook.com (2603:10b6:930:8e::6) by PH7PR12MB7985.namprd12.prod.outlook.com (2603:10b6:510:27b::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6652.26; Mon, 7 Aug 2023 13:49:18 +0000 Received: from CY4PEPF0000E9D8.namprd05.prod.outlook.com (2603:10b6:930:8e:cafe::23) by CYZPR19CA0014.outlook.office365.com (2603:10b6:930:8e::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6652.27 via Frontend Transport; Mon, 7 Aug 2023 13:49:17 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB03.amd.com; pr=C Received: from SATLEXMB03.amd.com (165.204.84.17) by CY4PEPF0000E9D8.mail.protection.outlook.com (10.167.241.83) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6652.19 via Frontend Transport; Mon, 7 Aug 2023 13:49:17 +0000 Received: from SATLEXMB08.amd.com (10.181.40.132) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Mon, 7 Aug 2023 08:49:15 -0500 Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB08.amd.com (10.181.40.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Mon, 7 Aug 2023 06:49:14 -0700 Received: from xcbecree41x.xilinx.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27 via Frontend Transport; Mon, 7 Aug 2023 08:49:13 -0500 From: To: , , , , CC: Edward Cree , , , Pieter Jansen van Vuuren , Simon Horman Subject: [PATCH v2 net-next 2/7] sfc: functions to register for conntrack zone offload Date: Mon, 7 Aug 2023 14:48:06 +0100 Message-ID: <53ef14cda15c4c642dd2247bf452f30b06882731.1691415479.git.ecree.xilinx@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CY4PEPF0000E9D8:EE_|PH7PR12MB7985:EE_ X-MS-Office365-Filtering-Correlation-Id: 90ea20c5-e157-4e77-9a75-08db974d17e9 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: gSpsUayN2akCvf0CLR7ECOGyY0j0ZRTEO/24j+cU8NsRCUDm6xo1o0RWMGoxX+SZokkumLcRPtPju95l3TA5a6VYnZdIDedgD9H1sKbPKqxfddVOG7d7XKdTfAacuA4O1WKT7Qm1D/w2lV9u2h+OdPJccw1WdqRpPpNporsPvVAtmDBOTiZ7qJXa7V8RPQ684hSF+PvjEX9Pg3K0Ejvg2mCtkm70hlv6Dc7EFshLVSMM/ayfzgIUw2BVZ8fMsIZT/m1CINmaGwTtsKyGn9m8vGwa5GjVgMX5R0YaxykvUF8jpZg5HdFC9cZAUJQU+Fg5XQkUSUYzehxDFQyXuzuzmB5dimYsXScJNjLO002hBmsmh3AtGrsf1Yj7eXTMaW0vJmgXSQzMuAFE1g/7mwGObLjv1TlHfRkYk7a1FRdiUhirUSnkGm4mNicd6ddVZclDAJKHopXRVxOg0E0IFAbw+xX9n4EMHjVL2JgGjvU5ezlSul259NIkLe/tk9FeNtHtHuSpUTMT8NKWVY/PhuFJlnsvzmSLIFYraFhJkZXYp/2UmB+I2tef1xvJ+1YsSdnaPvNS4o0FcenNyj0otrbAssKGmQqi08KBlDl1QxJZ7Ql7bD6A0Vs5h4TIenYM6mcttgyKqeSnIAGfkpoKta8IFaothd6AqNhFMQ460di5qNtA5KCSoG9uv2nsnMCO2T2l+i8JAc3fhwyNUD4g2mGJaR6W5fzGAo0Q2wYiLjT52BHPJoqVc80217hUu0K1rOC5evoC+ByU/AvG3Nnoh7puXRwRDPKghzoXon8+EnPNY1k= X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:SATLEXMB03.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230028)(4636009)(39860400002)(396003)(346002)(376002)(136003)(451199021)(1800799003)(186006)(82310400008)(46966006)(40470700004)(36840700001)(47076005)(2876002)(2906002)(36756003)(83380400001)(5660300002)(426003)(36860700001)(110136005)(54906003)(6666004)(70206006)(70586007)(356005)(9686003)(4326008)(82740400003)(81166007)(316002)(40480700001)(41300700001)(55446002)(86362001)(40460700003)(8936002)(26005)(8676002)(336012)(478600001)(2004002)(36900700001);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Aug 2023 13:49:17.1424 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 90ea20c5-e157-4e77-9a75-08db974d17e9 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB03.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CY4PEPF0000E9D8.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB7985 X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_SPF_HELO, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Edward Cree Bind a stub callback to the netfilter flow table. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree --- drivers/net/ethernet/sfc/Makefile | 2 +- drivers/net/ethernet/sfc/tc.c | 7 ++ drivers/net/ethernet/sfc/tc.h | 2 + drivers/net/ethernet/sfc/tc_conntrack.c | 109 ++++++++++++++++++++++++ drivers/net/ethernet/sfc/tc_conntrack.h | 37 ++++++++ 5 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/sfc/tc_conntrack.c create mode 100644 drivers/net/ethernet/sfc/tc_conntrack.h diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile index 16293b58e0a8..8f446b9bd5ee 100644 --- a/drivers/net/ethernet/sfc/Makefile +++ b/drivers/net/ethernet/sfc/Makefile @@ -11,7 +11,7 @@ sfc-y += efx.o efx_common.o efx_channels.o nic.o \ sfc-$(CONFIG_SFC_MTD) += mtd.o sfc-$(CONFIG_SFC_SRIOV) += sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o \ mae.o tc.o tc_bindings.o tc_counters.o \ - tc_encap_actions.o + tc_encap_actions.o tc_conntrack.o obj-$(CONFIG_SFC) += sfc.o diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 4dc979fdc968..44a6fc30b722 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -15,6 +15,7 @@ #include "tc.h" #include "tc_bindings.h" #include "tc_encap_actions.h" +#include "tc_conntrack.h" #include "mae.h" #include "ef100_rep.h" #include "efx.h" @@ -1747,6 +1748,9 @@ int efx_init_struct_tc(struct efx_nic *efx) rc = rhashtable_init(&efx->tc->match_action_ht, &efx_tc_match_action_ht_params); if (rc < 0) goto fail_match_action_ht; + rc = efx_tc_init_conntrack(efx); + if (rc < 0) + goto fail_conntrack; efx->tc->reps_filter_uc = -1; efx->tc->reps_filter_mc = -1; INIT_LIST_HEAD(&efx->tc->dflt.pf.acts.list); @@ -1759,6 +1763,8 @@ int efx_init_struct_tc(struct efx_nic *efx) efx->tc->facts.reps.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL; efx->extra_channel_type[EFX_EXTRA_CHANNEL_TC] = &efx_tc_channel_type; return 0; +fail_conntrack: + rhashtable_destroy(&efx->tc->match_action_ht); fail_match_action_ht: rhashtable_destroy(&efx->tc->encap_match_ht); fail_encap_match_ht: @@ -1792,6 +1798,7 @@ void efx_fini_struct_tc(struct efx_nic *efx) efx); rhashtable_free_and_destroy(&efx->tc->encap_match_ht, efx_tc_encap_match_free, NULL); + efx_tc_fini_conntrack(efx); efx_tc_fini_counters(efx); efx_tc_fini_encap_actions(efx); mutex_unlock(&efx->tc->mutex); diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index 27592f10b536..fc196eb897af 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -196,6 +196,7 @@ struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ * @encap_ht: Hashtable of TC encap actions * @encap_match_ht: Hashtable of TC encap matches * @match_action_ht: Hashtable of TC match-action rules + * @ct_zone_ht: Hashtable of TC conntrack flowtable bindings * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) * @meta_ct: MAE table layout for conntrack table * @reps_mport_id: MAE port allocated for representor RX @@ -228,6 +229,7 @@ struct efx_tc_state { struct rhashtable encap_ht; struct rhashtable encap_match_ht; struct rhashtable match_action_ht; + struct rhashtable ct_zone_ht; struct rhashtable neigh_ht; struct efx_tc_table_ct meta_ct; u32 reps_mport_id, reps_mport_vport_id; diff --git a/drivers/net/ethernet/sfc/tc_conntrack.c b/drivers/net/ethernet/sfc/tc_conntrack.c new file mode 100644 index 000000000000..d67302715ec3 --- /dev/null +++ b/drivers/net/ethernet/sfc/tc_conntrack.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0-only +/**************************************************************************** + * Driver for Solarflare network controllers and boards + * Copyright 2023, Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +#include "tc_conntrack.h" +#include "tc.h" +#include "mae.h" + +static int efx_tc_flow_block(enum tc_setup_type type, void *type_data, + void *cb_priv); + +static const struct rhashtable_params efx_tc_ct_zone_ht_params = { + .key_len = offsetof(struct efx_tc_ct_zone, linkage), + .key_offset = 0, + .head_offset = offsetof(struct efx_tc_ct_zone, linkage), +}; + +static void efx_tc_ct_zone_free(void *ptr, void *arg) +{ + struct efx_tc_ct_zone *zone = ptr; + struct efx_nic *efx = zone->efx; + + netif_err(efx, drv, efx->net_dev, + "tc ct_zone %u still present at teardown, removing\n", + zone->zone); + + nf_flow_table_offload_del_cb(zone->nf_ft, efx_tc_flow_block, zone); + kfree(zone); +} + +int efx_tc_init_conntrack(struct efx_nic *efx) +{ + int rc; + + rc = rhashtable_init(&efx->tc->ct_zone_ht, &efx_tc_ct_zone_ht_params); + if (rc < 0) + return rc; + return 0; +} + +void efx_tc_fini_conntrack(struct efx_nic *efx) +{ + rhashtable_free_and_destroy(&efx->tc->ct_zone_ht, efx_tc_ct_zone_free, NULL); +} + +static int efx_tc_flow_block(enum tc_setup_type type, void *type_data, + void *cb_priv) +{ + return -EOPNOTSUPP; +} + +struct efx_tc_ct_zone *efx_tc_ct_register_zone(struct efx_nic *efx, u16 zone, + struct nf_flowtable *ct_ft) +{ + struct efx_tc_ct_zone *ct_zone, *old; + int rc; + + ct_zone = kzalloc(sizeof(*ct_zone), GFP_USER); + if (!ct_zone) + return ERR_PTR(-ENOMEM); + ct_zone->zone = zone; + old = rhashtable_lookup_get_insert_fast(&efx->tc->ct_zone_ht, + &ct_zone->linkage, + efx_tc_ct_zone_ht_params); + if (old) { + /* don't need our new entry */ + kfree(ct_zone); + if (!refcount_inc_not_zero(&old->ref)) + return ERR_PTR(-EAGAIN); + /* existing entry found */ + WARN_ON_ONCE(old->nf_ft != ct_ft); + netif_dbg(efx, drv, efx->net_dev, + "Found existing ct_zone for %u\n", zone); + return old; + } + ct_zone->nf_ft = ct_ft; + ct_zone->efx = efx; + rc = nf_flow_table_offload_add_cb(ct_ft, efx_tc_flow_block, ct_zone); + netif_dbg(efx, drv, efx->net_dev, "Adding new ct_zone for %u, rc %d\n", + zone, rc); + if (rc < 0) + goto fail; + refcount_set(&ct_zone->ref, 1); + return ct_zone; +fail: + rhashtable_remove_fast(&efx->tc->ct_zone_ht, &ct_zone->linkage, + efx_tc_ct_zone_ht_params); + kfree(ct_zone); + return ERR_PTR(rc); +} + +void efx_tc_ct_unregister_zone(struct efx_nic *efx, + struct efx_tc_ct_zone *ct_zone) +{ + if (!refcount_dec_and_test(&ct_zone->ref)) + return; /* still in use */ + nf_flow_table_offload_del_cb(ct_zone->nf_ft, efx_tc_flow_block, ct_zone); + rhashtable_remove_fast(&efx->tc->ct_zone_ht, &ct_zone->linkage, + efx_tc_ct_zone_ht_params); + netif_dbg(efx, drv, efx->net_dev, "Removed ct_zone for %u\n", + ct_zone->zone); + kfree(ct_zone); +} diff --git a/drivers/net/ethernet/sfc/tc_conntrack.h b/drivers/net/ethernet/sfc/tc_conntrack.h new file mode 100644 index 000000000000..f1e5fb74a73f --- /dev/null +++ b/drivers/net/ethernet/sfc/tc_conntrack.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/**************************************************************************** + * Driver for Solarflare network controllers and boards + * Copyright 2023, Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +#ifndef EFX_TC_CONNTRACK_H +#define EFX_TC_CONNTRACK_H +#include "net_driver.h" + +#if IS_ENABLED(CONFIG_SFC_SRIOV) +#include +#include + +struct efx_tc_ct_zone { + u16 zone; + struct rhash_head linkage; + refcount_t ref; + struct nf_flowtable *nf_ft; + struct efx_nic *efx; +}; + +/* create/teardown hashtables */ +int efx_tc_init_conntrack(struct efx_nic *efx); +void efx_tc_fini_conntrack(struct efx_nic *efx); + +struct efx_tc_ct_zone *efx_tc_ct_register_zone(struct efx_nic *efx, u16 zone, + struct nf_flowtable *ct_ft); +void efx_tc_ct_unregister_zone(struct efx_nic *efx, + struct efx_tc_ct_zone *ct_zone); + +#endif /* CONFIG_SFC_SRIOV */ +#endif /* EFX_TC_CONNTRACK_H */ From patchwork Mon Aug 7 13:48:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: edward.cree@amd.com X-Patchwork-Id: 13344282 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C1DCF1118A for ; Mon, 7 Aug 2023 13:49:42 +0000 (UTC) Received: from NAM10-BN7-obe.outbound.protection.outlook.com (mail-bn7nam10on2060.outbound.protection.outlook.com [40.107.92.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E8C221722 for ; Mon, 7 Aug 2023 06:49:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=K4WhEEN49YT0nQ6z6sVAEx+6jhRh2qi/uXiTOMeHXqw7CAGB7oYRUfd4sKSBtdDswGuBVKSrNLJ7go5ENFvxxbDCG9BXpAiF7EcLJesUSGo8PAFqnFBEFLvDWY62W54fHYm+0SJSwF1wNvRN/E/cbx5/s5taRw/Ibt0kjZIBa6SmoOULCDPwHcmojzfSlYUADokkkRcF5+6zRhgkeejMOngIkPbsWEjXPA9ex8r9z6MG9hFv3PTmelckT0kDKeeiWgyr9PwVZJUlKMAUhWkfmvidORwqFAAq+wKawekHUx9O0gTPQ7meHiMqbOTzc9+4/s42qlHL4Wik9Wm9ECEBug== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=IqWV3Jn+qkhWwyG+/kOE+tz4lvuH52+TzjFiDuVFHiA=; b=hz5I2lxi61Oj5J2sYNbxXF0Y/4WgivA65pKbALx5ZFHu3Cw1lWiiQDIk7/HpL6Z277XImxdEyfFmb20eSlMuE6gntn6GRR4eUtOh7fAoFAFz6h1oZlmkHuTX9V00RUU9B5jiNp45fQHgj3TL+EednQEgsPFbQZ3OvrYrRZxqf0S6pcT65weYrW1B+uxpkOQAgMbqySwV8hDRYeeIwVwpsOfQI8lfsjS30wFj+kIUIcLFPPKfH2dW82unsnqqMvxU938h6AOW0+MaU4z60H8nBPi45MwfWtTyRZl+HOcvNeYr9qbx+lOPIDQ/mZmIpw4aoo1u5DMnIdMSC+d/ptdfqQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=davemloft.net smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=IqWV3Jn+qkhWwyG+/kOE+tz4lvuH52+TzjFiDuVFHiA=; b=aX91/BWlfSkgUICf+X1s/v1YLTrcFtBOhcA8B1Abmm0s5wT1ff9VY2wFWGtN991J1tWi7ktKSJh0C71doR2JrqOa1r9h9dzxiUjlp+YN9+EwS4vHon9W7FEUQwLSOP4rWfCrsT4v6ljuingYlACVC577RXIZbs7sBXIwsr461H4= Received: from BYAPR04CA0024.namprd04.prod.outlook.com (2603:10b6:a03:40::37) by MN6PR12MB8516.namprd12.prod.outlook.com (2603:10b6:208:46f::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6652.27; Mon, 7 Aug 2023 13:49:26 +0000 Received: from CO1PEPF000042AD.namprd03.prod.outlook.com (2603:10b6:a03:40:cafe::51) by BYAPR04CA0024.outlook.office365.com (2603:10b6:a03:40::37) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6652.27 via Frontend Transport; Mon, 7 Aug 2023 13:49:25 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by CO1PEPF000042AD.mail.protection.outlook.com (10.167.243.42) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6652.19 via Frontend Transport; Mon, 7 Aug 2023 13:49:24 +0000 Received: from SATLEXMB08.amd.com (10.181.40.132) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Mon, 7 Aug 2023 08:49:16 -0500 Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB08.amd.com (10.181.40.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Mon, 7 Aug 2023 06:49:16 -0700 Received: from xcbecree41x.xilinx.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27 via Frontend Transport; Mon, 7 Aug 2023 08:49:15 -0500 From: To: , , , , CC: Edward Cree , , , Pieter Jansen van Vuuren , Simon Horman Subject: [PATCH v2 net-next 3/7] sfc: functions to insert/remove conntrack entries to MAE hardware Date: Mon, 7 Aug 2023 14:48:07 +0100 Message-ID: <2d4f6577dcbb6a7c6377c98385e9fe8d0351b737.1691415479.git.ecree.xilinx@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PEPF000042AD:EE_|MN6PR12MB8516:EE_ X-MS-Office365-Filtering-Correlation-Id: f8012fac-bacf-4b40-edf7-08db974d1c8d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: TrgY7PEGKpR/B9iEpgVbeBN5BYHEP7/w+qwubJbaX0yb0bfWic1zsevQejSE5/Lv3Hki895UrZB7Ng9IPu9gGrb8a56wXZmE9h7c90x9SwGmv3DnARxOx2P/GG/UBfKvnP/4TkNb986Z863mGrNFU3B0fP/T9woyswKNaiX9hNBGJupRrv1v3DomnXTf8Vt+xZ8LunxQQcVsqe0XJBZ+BwSG/COaJAB708YR+FCpj4XVK0jKrBzwsVm09/rshDmYaj8sQzmB31MJZDAN/qmGXkLK+7uaGOIhdoZPRr4BC5aqsjiapHXOpFl680CRp5HhM3mpACXPxbaYBdq4xF0FUR7AdiN/WViB9Wk1TQlS05o9cnzbPN7NTQdNgdLXwFDpNE5Nc8I13NvltwJRqqCuWOO6NA4ijPQia79vlbH4DQ3nd93vxRLFQ6YkfRzhW3V01T6ojR1fYVnfHHp+eavMz4Q3M1nfJrmBDIPBFgLvqM0pvt2qfSQGmXDpFB+h0v0vsURxl1ZbMnuvfaiCOAxubBg0HRVw8KauRYv4jVExJ6MtXdASSfTRKWTRo6IXlHJr6XXX5XKgQJCduZG/lC8WYeIcQKH+kk8FQDkQEZ7xbDrzmLHpyZUho8st0rPAdB0z0pkZ0CiyBFQXzX7J7BANGEFiIZQmK5Qh3dsNDDDuS3H0bNoiYJYYTIxh3YWVuxbGr7wUbGXAk3sAk7+7XgtK5aX7hkW8+2C+96KL/0fBZHSsvr9wbz+Tskn/9NyxHDxWBkKJ6o+ROlLvW2KuITZgKw== X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:SATLEXMB04.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230028)(4636009)(396003)(346002)(39860400002)(376002)(136003)(451199021)(82310400008)(1800799003)(186006)(46966006)(40470700004)(36840700001)(40480700001)(40460700003)(9686003)(6666004)(478600001)(86362001)(82740400003)(55446002)(81166007)(26005)(36756003)(41300700001)(356005)(30864003)(316002)(5660300002)(8936002)(8676002)(54906003)(110136005)(4326008)(2906002)(2876002)(70206006)(70586007)(336012)(83380400001)(47076005)(36860700001)(426003)(36900700001);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Aug 2023 13:49:24.8677 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: f8012fac-bacf-4b40-edf7-08db974d1c8d X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CO1PEPF000042AD.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN6PR12MB8516 X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_SPF_HELO, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Edward Cree Translate from software struct efx_tc_ct_entry objects to the key and response bitstrings, and implement insertion and removal of these entries from the hardware table. Callers of these functions will be added in subsequent patches. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree --- drivers/net/ethernet/sfc/mae.c | 257 ++++++++++++++++++++++++ drivers/net/ethernet/sfc/mae.h | 3 + drivers/net/ethernet/sfc/tc_conntrack.h | 14 ++ 3 files changed, 274 insertions(+) diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index 33ae2c852b44..8ebf71a54bf9 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -16,6 +16,7 @@ #include "mcdi_pcol.h" #include "mcdi_pcol_mae.h" #include "tc_encap_actions.h" +#include "tc_conntrack.h" int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label) { @@ -1403,6 +1404,262 @@ int efx_mae_unregister_encap_match(struct efx_nic *efx, return 0; } +/* Populating is done by taking each byte of @value in turn and storing + * it in the appropriate bits of @row. @value must be big-endian; we + * convert it to little-endianness as we go. + */ +static int efx_mae_table_populate(struct efx_tc_table_field_fmt field, + __le32 *row, size_t row_bits, + void *value, size_t value_size) +{ + unsigned int i; + + /* For now only scheme 0 is supported for any field, so we check here + * (rather than, say, in calling code, which knows the semantics and + * could in principle encode for other schemes). + */ + if (field.scheme) + return -EOPNOTSUPP; + if (DIV_ROUND_UP(field.width, 8) != value_size) + return -EINVAL; + if (field.lbn + field.width > row_bits) + return -EINVAL; + for (i = 0; i < value_size; i++) { + unsigned int bn = field.lbn + i * 8; + unsigned int wn = bn / 32; + u64 v; + + v = ((u8 *)value)[value_size - i - 1]; + v <<= (bn % 32); + row[wn] |= cpu_to_le32(v & 0xffffffff); + if (wn * 32 < row_bits) + row[wn + 1] |= cpu_to_le32(v >> 32); + } + return 0; +} + +static int efx_mae_table_populate_bool(struct efx_tc_table_field_fmt field, + __le32 *row, size_t row_bits, bool value) +{ + u8 v = value ? 1 : 0; + + if (field.width != 1) + return -EINVAL; + return efx_mae_table_populate(field, row, row_bits, &v, 1); +} + +static int efx_mae_table_populate_ipv4(struct efx_tc_table_field_fmt field, + __le32 *row, size_t row_bits, __be32 value) +{ + /* IPv4 is placed in the first 4 bytes of an IPv6-sized field */ + struct in6_addr v = {}; + + if (field.width != 128) + return -EINVAL; + v.s6_addr32[0] = value; + return efx_mae_table_populate(field, row, row_bits, &v, sizeof(v)); +} + +static int efx_mae_table_populate_u24(struct efx_tc_table_field_fmt field, + __le32 *row, size_t row_bits, u32 value) +{ + __be32 v = cpu_to_be32(value); + + /* We adjust value_size here since just 3 bytes will be copied, and + * the pointer to the value is set discarding the first byte which is + * the most significant byte for a big-endian 4-bytes value. + */ + return efx_mae_table_populate(field, row, row_bits, ((void *)&v) + 1, + sizeof(v) - 1); +} + +#define _TABLE_POPULATE(dst, dw, _field, _value) ({ \ + typeof(_value) _v = _value; \ + \ + (_field.width == sizeof(_value) * 8) ? \ + efx_mae_table_populate(_field, dst, dw, &_v, \ + sizeof(_v)) : -EINVAL; \ +}) +#define TABLE_POPULATE_KEY_IPV4(dst, _table, _field, _value) \ + efx_mae_table_populate_ipv4(efx->tc->meta_##_table.desc.keys \ + [efx->tc->meta_##_table.keys._field##_idx],\ + dst, efx->tc->meta_##_table.desc.key_width,\ + _value) +#define TABLE_POPULATE_KEY(dst, _table, _field, _value) \ + _TABLE_POPULATE(dst, efx->tc->meta_##_table.desc.key_width, \ + efx->tc->meta_##_table.desc.keys \ + [efx->tc->meta_##_table.keys._field##_idx], \ + _value) + +#define TABLE_POPULATE_RESP_BOOL(dst, _table, _field, _value) \ + efx_mae_table_populate_bool(efx->tc->meta_##_table.desc.resps \ + [efx->tc->meta_##_table.resps._field##_idx],\ + dst, efx->tc->meta_##_table.desc.resp_width,\ + _value) +#define TABLE_POPULATE_RESP(dst, _table, _field, _value) \ + _TABLE_POPULATE(dst, efx->tc->meta_##_table.desc.resp_width, \ + efx->tc->meta_##_table.desc.resps \ + [efx->tc->meta_##_table.resps._field##_idx], \ + _value) + +#define TABLE_POPULATE_RESP_U24(dst, _table, _field, _value) \ + efx_mae_table_populate_u24(efx->tc->meta_##_table.desc.resps \ + [efx->tc->meta_##_table.resps._field##_idx],\ + dst, efx->tc->meta_##_table.desc.resp_width,\ + _value) + +static int efx_mae_populate_ct_key(struct efx_nic *efx, __le32 *key, size_t kw, + struct efx_tc_ct_entry *conn) +{ + bool ipv6 = conn->eth_proto == htons(ETH_P_IPV6); + int rc; + + rc = TABLE_POPULATE_KEY(key, ct, eth_proto, conn->eth_proto); + if (rc) + return rc; + rc = TABLE_POPULATE_KEY(key, ct, ip_proto, conn->ip_proto); + if (rc) + return rc; + if (ipv6) + rc = TABLE_POPULATE_KEY(key, ct, src_ip, conn->src_ip6); + else + rc = TABLE_POPULATE_KEY_IPV4(key, ct, src_ip, conn->src_ip); + if (rc) + return rc; + if (ipv6) + rc = TABLE_POPULATE_KEY(key, ct, dst_ip, conn->dst_ip6); + else + rc = TABLE_POPULATE_KEY_IPV4(key, ct, dst_ip, conn->dst_ip); + if (rc) + return rc; + rc = TABLE_POPULATE_KEY(key, ct, l4_sport, conn->l4_sport); + if (rc) + return rc; + rc = TABLE_POPULATE_KEY(key, ct, l4_dport, conn->l4_dport); + if (rc) + return rc; + return TABLE_POPULATE_KEY(key, ct, zone, cpu_to_be16(conn->zone->zone)); +} + +int efx_mae_insert_ct(struct efx_nic *efx, struct efx_tc_ct_entry *conn) +{ + bool ipv6 = conn->eth_proto == htons(ETH_P_IPV6); + __le32 *key = NULL, *resp = NULL; + size_t inlen, kw, rw; + efx_dword_t *inbuf; + int rc = -ENOMEM; + + /* Check table access is supported */ + if (!efx->tc->meta_ct.hooked) + return -EOPNOTSUPP; + + /* key/resp widths are in bits; convert to dwords for IN_LEN */ + kw = DIV_ROUND_UP(efx->tc->meta_ct.desc.key_width, 32); + rw = DIV_ROUND_UP(efx->tc->meta_ct.desc.resp_width, 32); + BUILD_BUG_ON(sizeof(__le32) != MC_CMD_TABLE_INSERT_IN_DATA_LEN); + inlen = MC_CMD_TABLE_INSERT_IN_LEN(kw + rw); + if (inlen > MC_CMD_TABLE_INSERT_IN_LENMAX_MCDI2) + return -E2BIG; + inbuf = kzalloc(inlen, GFP_KERNEL); + if (!inbuf) + return -ENOMEM; + + key = kcalloc(kw, sizeof(__le32), GFP_KERNEL); + if (!key) + goto out_free; + resp = kcalloc(rw, sizeof(__le32), GFP_KERNEL); + if (!resp) + goto out_free; + + rc = efx_mae_populate_ct_key(efx, key, kw, conn); + if (rc) + goto out_free; + + rc = TABLE_POPULATE_RESP_BOOL(resp, ct, dnat, conn->dnat); + if (rc) + goto out_free; + /* No support in hw for IPv6 NAT; field is only 32 bits */ + if (!ipv6) + rc = TABLE_POPULATE_RESP(resp, ct, nat_ip, conn->nat_ip); + if (rc) + goto out_free; + rc = TABLE_POPULATE_RESP(resp, ct, l4_natport, conn->l4_natport); + if (rc) + goto out_free; + rc = TABLE_POPULATE_RESP(resp, ct, mark, cpu_to_be32(conn->mark)); + if (rc) + goto out_free; + rc = TABLE_POPULATE_RESP_U24(resp, ct, counter_id, conn->cnt->fw_id); + if (rc) + goto out_free; + + MCDI_SET_DWORD(inbuf, TABLE_INSERT_IN_TABLE_ID, TABLE_ID_CONNTRACK_TABLE); + MCDI_SET_WORD(inbuf, TABLE_INSERT_IN_KEY_WIDTH, + efx->tc->meta_ct.desc.key_width); + /* MASK_WIDTH is zero as CT is a BCAM */ + MCDI_SET_WORD(inbuf, TABLE_INSERT_IN_RESP_WIDTH, + efx->tc->meta_ct.desc.resp_width); + memcpy(MCDI_PTR(inbuf, TABLE_INSERT_IN_DATA), key, kw * sizeof(__le32)); + memcpy(MCDI_PTR(inbuf, TABLE_INSERT_IN_DATA) + kw * sizeof(__le32), + resp, rw * sizeof(__le32)); + + BUILD_BUG_ON(MC_CMD_TABLE_INSERT_OUT_LEN); + + rc = efx_mcdi_rpc(efx, MC_CMD_TABLE_INSERT, inbuf, inlen, NULL, 0, NULL); + +out_free: + kfree(resp); + kfree(key); + kfree(inbuf); + return rc; +} + +int efx_mae_remove_ct(struct efx_nic *efx, struct efx_tc_ct_entry *conn) +{ + __le32 *key = NULL; + efx_dword_t *inbuf; + size_t inlen, kw; + int rc = -ENOMEM; + + /* Check table access is supported */ + if (!efx->tc->meta_ct.hooked) + return -EOPNOTSUPP; + + /* key width is in bits; convert to dwords for IN_LEN */ + kw = DIV_ROUND_UP(efx->tc->meta_ct.desc.key_width, 32); + BUILD_BUG_ON(sizeof(__le32) != MC_CMD_TABLE_DELETE_IN_DATA_LEN); + inlen = MC_CMD_TABLE_DELETE_IN_LEN(kw); + if (inlen > MC_CMD_TABLE_DELETE_IN_LENMAX_MCDI2) + return -E2BIG; + inbuf = kzalloc(inlen, GFP_KERNEL); + if (!inbuf) + return -ENOMEM; + + key = kcalloc(kw, sizeof(__le32), GFP_KERNEL); + if (!key) + goto out_free; + + rc = efx_mae_populate_ct_key(efx, key, kw, conn); + if (rc) + goto out_free; + + MCDI_SET_DWORD(inbuf, TABLE_DELETE_IN_TABLE_ID, TABLE_ID_CONNTRACK_TABLE); + MCDI_SET_WORD(inbuf, TABLE_DELETE_IN_KEY_WIDTH, + efx->tc->meta_ct.desc.key_width); + /* MASK_WIDTH is zero as CT is a BCAM */ + /* RESP_WIDTH is zero for DELETE */ + memcpy(MCDI_PTR(inbuf, TABLE_DELETE_IN_DATA), key, kw * sizeof(__le32)); + + BUILD_BUG_ON(MC_CMD_TABLE_DELETE_OUT_LEN); + + rc = efx_mcdi_rpc(efx, MC_CMD_TABLE_DELETE, inbuf, inlen, NULL, 0, NULL); + +out_free: + kfree(key); + kfree(inbuf); + return rc; +} + static int efx_mae_populate_match_criteria(MCDI_DECLARE_STRUCT_PTR(match_crit), const struct efx_tc_match *match) { diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h index afdf738254b2..24f29a4fc0e1 100644 --- a/drivers/net/ethernet/sfc/mae.h +++ b/drivers/net/ethernet/sfc/mae.h @@ -112,6 +112,9 @@ int efx_mae_register_encap_match(struct efx_nic *efx, struct efx_tc_encap_match *encap); int efx_mae_unregister_encap_match(struct efx_nic *efx, struct efx_tc_encap_match *encap); +struct efx_tc_ct_entry; /* see tc_conntrack.h */ +int efx_mae_insert_ct(struct efx_nic *efx, struct efx_tc_ct_entry *conn); +int efx_mae_remove_ct(struct efx_nic *efx, struct efx_tc_ct_entry *conn); int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match, u32 prio, u32 acts_id, u32 *id); diff --git a/drivers/net/ethernet/sfc/tc_conntrack.h b/drivers/net/ethernet/sfc/tc_conntrack.h index f1e5fb74a73f..a3e518344cbc 100644 --- a/drivers/net/ethernet/sfc/tc_conntrack.h +++ b/drivers/net/ethernet/sfc/tc_conntrack.h @@ -33,5 +33,19 @@ struct efx_tc_ct_zone *efx_tc_ct_register_zone(struct efx_nic *efx, u16 zone, void efx_tc_ct_unregister_zone(struct efx_nic *efx, struct efx_tc_ct_zone *ct_zone); +struct efx_tc_ct_entry { + unsigned long cookie; + struct rhash_head linkage; + __be16 eth_proto; + u8 ip_proto; + bool dnat; + __be32 src_ip, dst_ip, nat_ip; + struct in6_addr src_ip6, dst_ip6; + __be16 l4_sport, l4_dport, l4_natport; /* Ports (UDP, TCP) */ + struct efx_tc_ct_zone *zone; + u32 mark; + struct efx_tc_counter *cnt; +}; + #endif /* CONFIG_SFC_SRIOV */ #endif /* EFX_TC_CONNTRACK_H */ From patchwork Mon Aug 7 13:48:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: edward.cree@amd.com X-Patchwork-Id: 13344280 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7EACD1118A for ; Mon, 7 Aug 2023 13:49:39 +0000 (UTC) Received: from NAM02-DM3-obe.outbound.protection.outlook.com (mail-dm3nam02on2051.outbound.protection.outlook.com [40.107.95.51]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 767741986 for ; Mon, 7 Aug 2023 06:49:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=HkyaDDsQmCc5CmbIeMLzuUgnmBplmRxrt8qr0uB0ZAwQmGCb8MdByt7AQfI84JL98h+u2GmfVYxkny+/GmrYxYhGuWLQu/KynhK80SLPMvEmt2Qx/o1aL7d+NuZOgLk54y71gN4XwDzYFjMQPUR9uMDR2z4TILiZgHP+5z7jkFYzRzdFbcwkGRClLtDGoudc+2aKxWoRb3uPRqOGpIyRwadPgfWPmIK18UgURssNWJtD7bIZO7/MVrxa+xz8cEZwzGnd2VlvoRkUSgSsy97mgXrqpJIDF6rhuZ7JKymtlMiar754W45uDC2G1aUZ2KJDPDGBZvuSE1I26S8L/X0Fow== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Zu8G0d8tSwX/rsnk3H8nmzZYXRBFvNyVJrHl9sgi1/0=; b=fA/XNn70gaWp7VshyK2ew8lflm8GM3ha+M+9icOnifTgJth+BihlU/UsEQI789hyfQZFVPs+7sJx9XqeRl5Nch5HYgUI96iliWF/irokah5z3aAAMGtCGS+YdgHpX86NCOu5z2L3Ne1UHaM/9Y5mqmNLn17WQcm4PEFmZzFUeSKL78Baj9ib1nfbLUX231I83cKWfZNM5cPVM4yH3yefaR9UNwF2BP5VKeGqBKAber8mgXoSOWqTolXP0kMdDwppqulyBjOtWQ39jjysEfWK/E+WI9ZIyf8zeFbhGTFSICA0PVohP4ouHNC042A8U9LafTUIstaiKljhIzlzuzHCOg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=davemloft.net smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Zu8G0d8tSwX/rsnk3H8nmzZYXRBFvNyVJrHl9sgi1/0=; b=uRO+AsCiAci5dZbGwds0uK7xFBP25GiFRTnV0GApIlJb7z8WowlyMCQ0E1Hv8Bow1df9Jc1Fr9g4DuwY4S7dudYN++LTIzggLUFih/YIhp2pcBdkDslqzlRXymxh065hxzOVD1a5RG7ej10AcgBaFHUsaMq4p/A2oaFZf4WJfQg= Received: from CYZPR19CA0021.namprd19.prod.outlook.com (2603:10b6:930:8e::22) by BN9PR12MB5368.namprd12.prod.outlook.com (2603:10b6:408:105::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6652.27; Mon, 7 Aug 2023 13:49:17 +0000 Received: from CY4PEPF0000E9D8.namprd05.prod.outlook.com (2603:10b6:930:8e:cafe::35) by CYZPR19CA0021.outlook.office365.com (2603:10b6:930:8e::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6652.27 via Frontend Transport; Mon, 7 Aug 2023 13:49:20 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB03.amd.com; pr=C Received: from SATLEXMB03.amd.com (165.204.84.17) by CY4PEPF0000E9D8.mail.protection.outlook.com (10.167.241.83) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6652.19 via Frontend Transport; Mon, 7 Aug 2023 13:49:20 +0000 Received: from SATLEXMB05.amd.com (10.181.40.146) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Mon, 7 Aug 2023 08:49:18 -0500 Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB05.amd.com (10.181.40.146) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Mon, 7 Aug 2023 08:49:18 -0500 Received: from xcbecree41x.xilinx.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27 via Frontend Transport; Mon, 7 Aug 2023 08:49:16 -0500 From: To: , , , , CC: Edward Cree , , , Pieter Jansen van Vuuren , Simon Horman Subject: [PATCH v2 net-next 4/7] sfc: offload conntrack flow entries (match only) from CT zones Date: Mon, 7 Aug 2023 14:48:08 +0100 Message-ID: X-Mailer: git-send-email 2.27.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CY4PEPF0000E9D8:EE_|BN9PR12MB5368:EE_ X-MS-Office365-Filtering-Correlation-Id: 8120f9cd-cb4c-4227-ab82-08db974d19e0 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: iQrlJ8ABSFlMQAypfpJoq0yLVY+KomnDNB49Kqmvy0NsCbEdf/u/2x7rhXMFG46pxZ55KDT9r9K9lyUFjmoskpsTwMaUIBi1AdEozDr3WNnY4D7YXhAQeeqqJaT22brJUszgCHkTIhhM8mDOyB0iTPIiYIiByQBWqEu2G5gQGS5zRmAQ77kUiN1MeXOfNkOwd0ZQ3tVGpsIm5Q9j9scmz42N91DJJxXVSPemVc+Q+Di3O1J4viSOoriAef8uZHuCt10o3aycHWgwPr7YYFU5u3u2fvNr8RKQCbobCaHV5ImEDoG1eAQR4YpJxJ6i3BdIIWiVGFUWCewyVgWUIusO8mUoI63+t/YSGRmwrTLv3Y0u++YQOyHx1JP5ey4dCGfyYsgazjZI6Dc6WAGcUSJlhCM0J5TU+TIS8VtlJWo6Wm9fMxsOdpJbNdSv8pKq3NXwaqvcAZVKxg1LAY4jSWVW3O/9uQoS5GTYGO7GbJ406g5/pwBbot2+xof5D5LV7CDcD1hGyHzDjRRHmg/6qsqq5VxzbKL/IB4p9fJgKc/1HphNd2SQU5NcndxC4p/bc/TJkKYRlvuYMa5VxUcsYale5FmMzhs3MnQJCY+aqAuIXnq1S9XryWdkPDH2cJqvyJxcP+pZQFd158XPRH8qRwHYsuSTMWjZmNGldfPqm3EtG9o3LV4UcN9u1fpPqWfJ9B2BGxiNWuuTSxI2QDEIQLLhwtlvoAxUiWVcA1lsfblDCg31qPbnoQUlbDlUgWMHNjK+V3BKVGra5wvcFqqhGOCpwQ== X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:SATLEXMB03.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230028)(4636009)(396003)(136003)(346002)(376002)(39860400002)(451199021)(82310400008)(186006)(1800799003)(40470700004)(46966006)(36840700001)(40480700001)(336012)(40460700003)(36756003)(4326008)(9686003)(316002)(86362001)(81166007)(478600001)(55446002)(110136005)(54906003)(356005)(70206006)(6666004)(70586007)(82740400003)(41300700001)(26005)(426003)(8676002)(8936002)(47076005)(36860700001)(2876002)(2906002)(30864003)(83380400001)(5660300002)(36900700001);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Aug 2023 13:49:20.4393 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 8120f9cd-cb4c-4227-ab82-08db974d19e0 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB03.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CY4PEPF0000E9D8.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN9PR12MB5368 X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_SPF_HELO, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Edward Cree No handling yet for FLOW_ACTION_MANGLE (NAT or NAPT) actions. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree --- drivers/net/ethernet/sfc/tc.h | 4 +- drivers/net/ethernet/sfc/tc_conntrack.c | 417 +++++++++++++++++++++++- drivers/net/ethernet/sfc/tc_conntrack.h | 3 + drivers/net/ethernet/sfc/tc_counters.c | 8 +- drivers/net/ethernet/sfc/tc_counters.h | 4 + 5 files changed, 429 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index fc196eb897af..2aba9ca00618 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -18,12 +18,10 @@ #define IS_ALL_ONES(v) (!(typeof (v))~(v)) -#ifdef CONFIG_IPV6 static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr) { return !memchr_inv(addr, 0xff, sizeof(*addr)); } -#endif struct efx_tc_encap_action; /* see tc_encap_actions.h */ @@ -197,6 +195,7 @@ struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ * @encap_match_ht: Hashtable of TC encap matches * @match_action_ht: Hashtable of TC match-action rules * @ct_zone_ht: Hashtable of TC conntrack flowtable bindings + * @ct_ht: Hashtable of TC conntrack flow entries * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) * @meta_ct: MAE table layout for conntrack table * @reps_mport_id: MAE port allocated for representor RX @@ -230,6 +229,7 @@ struct efx_tc_state { struct rhashtable encap_match_ht; struct rhashtable match_action_ht; struct rhashtable ct_zone_ht; + struct rhashtable ct_ht; struct rhashtable neigh_ht; struct efx_tc_table_ct meta_ct; u32 reps_mport_id, reps_mport_vport_id; diff --git a/drivers/net/ethernet/sfc/tc_conntrack.c b/drivers/net/ethernet/sfc/tc_conntrack.c index d67302715ec3..6729b3796a8b 100644 --- a/drivers/net/ethernet/sfc/tc_conntrack.c +++ b/drivers/net/ethernet/sfc/tc_conntrack.c @@ -21,6 +21,12 @@ static const struct rhashtable_params efx_tc_ct_zone_ht_params = { .head_offset = offsetof(struct efx_tc_ct_zone, linkage), }; +static const struct rhashtable_params efx_tc_ct_ht_params = { + .key_len = offsetof(struct efx_tc_ct_entry, linkage), + .key_offset = 0, + .head_offset = offsetof(struct efx_tc_ct_entry, linkage), +}; + static void efx_tc_ct_zone_free(void *ptr, void *arg) { struct efx_tc_ct_zone *zone = ptr; @@ -34,24 +40,420 @@ static void efx_tc_ct_zone_free(void *ptr, void *arg) kfree(zone); } +static void efx_tc_ct_free(void *ptr, void *arg) +{ + struct efx_tc_ct_entry *conn = ptr; + struct efx_nic *efx = arg; + + netif_err(efx, drv, efx->net_dev, + "tc ct_entry %lx still present at teardown\n", + conn->cookie); + + /* We can release the counter, but we can't remove the CT itself + * from hardware because the table meta is already gone. + */ + efx_tc_flower_release_counter(efx, conn->cnt); + kfree(conn); +} + int efx_tc_init_conntrack(struct efx_nic *efx) { int rc; rc = rhashtable_init(&efx->tc->ct_zone_ht, &efx_tc_ct_zone_ht_params); if (rc < 0) - return rc; + goto fail_ct_zone_ht; + rc = rhashtable_init(&efx->tc->ct_ht, &efx_tc_ct_ht_params); + if (rc < 0) + goto fail_ct_ht; return 0; +fail_ct_ht: + rhashtable_destroy(&efx->tc->ct_zone_ht); +fail_ct_zone_ht: + return rc; } void efx_tc_fini_conntrack(struct efx_nic *efx) { rhashtable_free_and_destroy(&efx->tc->ct_zone_ht, efx_tc_ct_zone_free, NULL); + rhashtable_free_and_destroy(&efx->tc->ct_ht, efx_tc_ct_free, efx); +} + +#define EFX_NF_TCP_FLAG(flg) cpu_to_be16(be32_to_cpu(TCP_FLAG_##flg) >> 16) + +static int efx_tc_ct_parse_match(struct efx_nic *efx, struct flow_rule *fr, + struct efx_tc_ct_entry *conn) +{ + struct flow_dissector *dissector = fr->match.dissector; + unsigned char ipv = 0; + bool tcp = false; + + if (flow_rule_match_key(fr, FLOW_DISSECTOR_KEY_CONTROL)) { + struct flow_match_control fm; + + flow_rule_match_control(fr, &fm); + if (IS_ALL_ONES(fm.mask->addr_type)) + switch (fm.key->addr_type) { + case FLOW_DISSECTOR_KEY_IPV4_ADDRS: + ipv = 4; + break; + case FLOW_DISSECTOR_KEY_IPV6_ADDRS: + ipv = 6; + break; + default: + break; + } + } + + if (!ipv) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack missing ipv specification\n"); + return -EOPNOTSUPP; + } + + if (dissector->used_keys & + ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_TCP) | + BIT_ULL(FLOW_DISSECTOR_KEY_META))) { + netif_dbg(efx, drv, efx->net_dev, + "Unsupported conntrack keys %#llx\n", + dissector->used_keys); + return -EOPNOTSUPP; + } + + if (flow_rule_match_key(fr, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic fm; + + flow_rule_match_basic(fr, &fm); + if (!IS_ALL_ONES(fm.mask->n_proto)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack eth_proto is not exact-match; mask %04x\n", + ntohs(fm.mask->n_proto)); + return -EOPNOTSUPP; + } + conn->eth_proto = fm.key->n_proto; + if (conn->eth_proto != (ipv == 4 ? htons(ETH_P_IP) + : htons(ETH_P_IPV6))) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack eth_proto is not IPv%u, is %04x\n", + ipv, ntohs(conn->eth_proto)); + return -EOPNOTSUPP; + } + if (!IS_ALL_ONES(fm.mask->ip_proto)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ip_proto is not exact-match; mask %02x\n", + fm.mask->ip_proto); + return -EOPNOTSUPP; + } + conn->ip_proto = fm.key->ip_proto; + switch (conn->ip_proto) { + case IPPROTO_TCP: + tcp = true; + break; + case IPPROTO_UDP: + break; + default: + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ip_proto not TCP or UDP, is %02x\n", + conn->ip_proto); + return -EOPNOTSUPP; + } + } else { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack missing eth_proto, ip_proto\n"); + return -EOPNOTSUPP; + } + + if (ipv == 4 && flow_rule_match_key(fr, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { + struct flow_match_ipv4_addrs fm; + + flow_rule_match_ipv4_addrs(fr, &fm); + if (!IS_ALL_ONES(fm.mask->src)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ipv4.src is not exact-match; mask %08x\n", + ntohl(fm.mask->src)); + return -EOPNOTSUPP; + } + conn->src_ip = fm.key->src; + if (!IS_ALL_ONES(fm.mask->dst)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ipv4.dst is not exact-match; mask %08x\n", + ntohl(fm.mask->dst)); + return -EOPNOTSUPP; + } + conn->dst_ip = fm.key->dst; + } else if (ipv == 6 && flow_rule_match_key(fr, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) { + struct flow_match_ipv6_addrs fm; + + flow_rule_match_ipv6_addrs(fr, &fm); + if (!efx_ipv6_addr_all_ones(&fm.mask->src)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ipv6.src is not exact-match; mask %pI6\n", + &fm.mask->src); + return -EOPNOTSUPP; + } + conn->src_ip6 = fm.key->src; + if (!efx_ipv6_addr_all_ones(&fm.mask->dst)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ipv6.dst is not exact-match; mask %pI6\n", + &fm.mask->dst); + return -EOPNOTSUPP; + } + conn->dst_ip6 = fm.key->dst; + } else { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack missing IPv%u addrs\n", ipv); + return -EOPNOTSUPP; + } + + if (flow_rule_match_key(fr, FLOW_DISSECTOR_KEY_PORTS)) { + struct flow_match_ports fm; + + flow_rule_match_ports(fr, &fm); + if (!IS_ALL_ONES(fm.mask->src)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ports.src is not exact-match; mask %04x\n", + ntohs(fm.mask->src)); + return -EOPNOTSUPP; + } + conn->l4_sport = fm.key->src; + if (!IS_ALL_ONES(fm.mask->dst)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ports.dst is not exact-match; mask %04x\n", + ntohs(fm.mask->dst)); + return -EOPNOTSUPP; + } + conn->l4_dport = fm.key->dst; + } else { + netif_dbg(efx, drv, efx->net_dev, "Conntrack missing L4 ports\n"); + return -EOPNOTSUPP; + } + + if (flow_rule_match_key(fr, FLOW_DISSECTOR_KEY_TCP)) { + __be16 tcp_interesting_flags; + struct flow_match_tcp fm; + + if (!tcp) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack matching on TCP keys but ipproto is not tcp\n"); + return -EOPNOTSUPP; + } + flow_rule_match_tcp(fr, &fm); + tcp_interesting_flags = EFX_NF_TCP_FLAG(SYN) | + EFX_NF_TCP_FLAG(RST) | + EFX_NF_TCP_FLAG(FIN); + /* If any of the tcp_interesting_flags is set, we always + * inhibit CT lookup in LHS (so SW can update CT table). + */ + if (fm.key->flags & tcp_interesting_flags) { + netif_dbg(efx, drv, efx->net_dev, + "Unsupported conntrack tcp.flags %04x/%04x\n", + ntohs(fm.key->flags), ntohs(fm.mask->flags)); + return -EOPNOTSUPP; + } + /* Other TCP flags cannot be filtered at CT */ + if (fm.mask->flags & ~tcp_interesting_flags) { + netif_dbg(efx, drv, efx->net_dev, + "Unsupported conntrack tcp.flags %04x/%04x\n", + ntohs(fm.key->flags), ntohs(fm.mask->flags)); + return -EOPNOTSUPP; + } + } + + return 0; +} + +static int efx_tc_ct_replace(struct efx_tc_ct_zone *ct_zone, + struct flow_cls_offload *tc) +{ + struct flow_rule *fr = flow_cls_offload_flow_rule(tc); + struct efx_tc_ct_entry *conn, *old; + struct efx_nic *efx = ct_zone->efx; + const struct flow_action_entry *fa; + struct efx_tc_counter *cnt; + int rc, i; + + if (WARN_ON(!efx->tc)) + return -ENETDOWN; + if (WARN_ON(!efx->tc->up)) + return -ENETDOWN; + + conn = kzalloc(sizeof(*conn), GFP_USER); + if (!conn) + return -ENOMEM; + conn->cookie = tc->cookie; + old = rhashtable_lookup_get_insert_fast(&efx->tc->ct_ht, + &conn->linkage, + efx_tc_ct_ht_params); + if (old) { + netif_dbg(efx, drv, efx->net_dev, + "Already offloaded conntrack (cookie %lx)\n", tc->cookie); + rc = -EEXIST; + goto release; + } + + /* Parse match */ + conn->zone = ct_zone; + rc = efx_tc_ct_parse_match(efx, fr, conn); + if (rc) + goto release; + + /* Parse actions */ + flow_action_for_each(i, fa, &fr->action) { + switch (fa->id) { + case FLOW_ACTION_CT_METADATA: + conn->mark = fa->ct_metadata.mark; + if (memchr_inv(fa->ct_metadata.labels, 0, sizeof(fa->ct_metadata.labels))) { + netif_dbg(efx, drv, efx->net_dev, + "Setting CT label not supported\n"); + rc = -EOPNOTSUPP; + goto release; + } + break; + default: + netif_dbg(efx, drv, efx->net_dev, + "Unhandled action %u for conntrack\n", fa->id); + rc = -EOPNOTSUPP; + goto release; + } + } + + /* fill in defaults for unmangled values */ + conn->nat_ip = conn->dnat ? conn->dst_ip : conn->src_ip; + conn->l4_natport = conn->dnat ? conn->l4_dport : conn->l4_sport; + + cnt = efx_tc_flower_allocate_counter(efx, EFX_TC_COUNTER_TYPE_CT); + if (IS_ERR(cnt)) { + rc = PTR_ERR(cnt); + goto release; + } + conn->cnt = cnt; + + rc = efx_mae_insert_ct(efx, conn); + if (rc) { + netif_dbg(efx, drv, efx->net_dev, + "Failed to insert conntrack, %d\n", rc); + goto release; + } + mutex_lock(&ct_zone->mutex); + list_add_tail(&conn->list, &ct_zone->cts); + mutex_unlock(&ct_zone->mutex); + return 0; +release: + if (conn->cnt) + efx_tc_flower_release_counter(efx, conn->cnt); + if (!old) + rhashtable_remove_fast(&efx->tc->ct_ht, &conn->linkage, + efx_tc_ct_ht_params); + kfree(conn); + return rc; +} + +/* Caller must follow with efx_tc_ct_remove_finish() after RCU grace period! */ +static void efx_tc_ct_remove(struct efx_nic *efx, struct efx_tc_ct_entry *conn) +{ + int rc; + + /* Remove it from HW */ + rc = efx_mae_remove_ct(efx, conn); + /* Delete it from SW */ + rhashtable_remove_fast(&efx->tc->ct_ht, &conn->linkage, + efx_tc_ct_ht_params); + if (rc) { + netif_err(efx, drv, efx->net_dev, + "Failed to remove conntrack %lx from hw, rc %d\n", + conn->cookie, rc); + } else { + netif_dbg(efx, drv, efx->net_dev, "Removed conntrack %lx\n", + conn->cookie); + } +} + +static void efx_tc_ct_remove_finish(struct efx_nic *efx, struct efx_tc_ct_entry *conn) +{ + /* Remove related CT counter. This is delayed after the conn object we + * are working with has been successfully removed. This protects the + * counter from being used-after-free inside efx_tc_ct_stats. + */ + efx_tc_flower_release_counter(efx, conn->cnt); + kfree(conn); +} + +static int efx_tc_ct_destroy(struct efx_tc_ct_zone *ct_zone, + struct flow_cls_offload *tc) +{ + struct efx_nic *efx = ct_zone->efx; + struct efx_tc_ct_entry *conn; + + conn = rhashtable_lookup_fast(&efx->tc->ct_ht, &tc->cookie, + efx_tc_ct_ht_params); + if (!conn) { + netif_warn(efx, drv, efx->net_dev, + "Conntrack %lx not found to remove\n", tc->cookie); + return -ENOENT; + } + + mutex_lock(&ct_zone->mutex); + list_del(&conn->list); + efx_tc_ct_remove(efx, conn); + mutex_unlock(&ct_zone->mutex); + synchronize_rcu(); + efx_tc_ct_remove_finish(efx, conn); + return 0; +} + +static int efx_tc_ct_stats(struct efx_tc_ct_zone *ct_zone, + struct flow_cls_offload *tc) +{ + struct efx_nic *efx = ct_zone->efx; + struct efx_tc_ct_entry *conn; + struct efx_tc_counter *cnt; + + rcu_read_lock(); + conn = rhashtable_lookup_fast(&efx->tc->ct_ht, &tc->cookie, + efx_tc_ct_ht_params); + if (!conn) { + netif_warn(efx, drv, efx->net_dev, + "Conntrack %lx not found for stats\n", tc->cookie); + rcu_read_unlock(); + return -ENOENT; + } + + cnt = conn->cnt; + spin_lock_bh(&cnt->lock); + /* Report only last use */ + flow_stats_update(&tc->stats, 0, 0, 0, cnt->touched, + FLOW_ACTION_HW_STATS_DELAYED); + spin_unlock_bh(&cnt->lock); + rcu_read_unlock(); + + return 0; } static int efx_tc_flow_block(enum tc_setup_type type, void *type_data, void *cb_priv) { + struct flow_cls_offload *tcb = type_data; + struct efx_tc_ct_zone *ct_zone = cb_priv; + + if (type != TC_SETUP_CLSFLOWER) + return -EOPNOTSUPP; + + switch (tcb->command) { + case FLOW_CLS_REPLACE: + return efx_tc_ct_replace(ct_zone, tcb); + case FLOW_CLS_DESTROY: + return efx_tc_ct_destroy(ct_zone, tcb); + case FLOW_CLS_STATS: + return efx_tc_ct_stats(ct_zone, tcb); + default: + break; + }; + return -EOPNOTSUPP; } @@ -81,6 +483,8 @@ struct efx_tc_ct_zone *efx_tc_ct_register_zone(struct efx_nic *efx, u16 zone, } ct_zone->nf_ft = ct_ft; ct_zone->efx = efx; + INIT_LIST_HEAD(&ct_zone->cts); + mutex_init(&ct_zone->mutex); rc = nf_flow_table_offload_add_cb(ct_ft, efx_tc_flow_block, ct_zone); netif_dbg(efx, drv, efx->net_dev, "Adding new ct_zone for %u, rc %d\n", zone, rc); @@ -98,11 +502,22 @@ struct efx_tc_ct_zone *efx_tc_ct_register_zone(struct efx_nic *efx, u16 zone, void efx_tc_ct_unregister_zone(struct efx_nic *efx, struct efx_tc_ct_zone *ct_zone) { + struct efx_tc_ct_entry *conn, *next; + if (!refcount_dec_and_test(&ct_zone->ref)) return; /* still in use */ nf_flow_table_offload_del_cb(ct_zone->nf_ft, efx_tc_flow_block, ct_zone); rhashtable_remove_fast(&efx->tc->ct_zone_ht, &ct_zone->linkage, efx_tc_ct_zone_ht_params); + mutex_lock(&ct_zone->mutex); + list_for_each_entry(conn, &ct_zone->cts, list) + efx_tc_ct_remove(efx, conn); + synchronize_rcu(); + /* need to use _safe because efx_tc_ct_remove_finish() frees conn */ + list_for_each_entry_safe(conn, next, &ct_zone->cts, list) + efx_tc_ct_remove_finish(efx, conn); + mutex_unlock(&ct_zone->mutex); + mutex_destroy(&ct_zone->mutex); netif_dbg(efx, drv, efx->net_dev, "Removed ct_zone for %u\n", ct_zone->zone); kfree(ct_zone); diff --git a/drivers/net/ethernet/sfc/tc_conntrack.h b/drivers/net/ethernet/sfc/tc_conntrack.h index a3e518344cbc..ef5cf96c0649 100644 --- a/drivers/net/ethernet/sfc/tc_conntrack.h +++ b/drivers/net/ethernet/sfc/tc_conntrack.h @@ -22,6 +22,8 @@ struct efx_tc_ct_zone { refcount_t ref; struct nf_flowtable *nf_ft; struct efx_nic *efx; + struct mutex mutex; /* protects cts list */ + struct list_head cts; /* list of efx_tc_ct_entry in this zone */ }; /* create/teardown hashtables */ @@ -45,6 +47,7 @@ struct efx_tc_ct_entry { struct efx_tc_ct_zone *zone; u32 mark; struct efx_tc_counter *cnt; + struct list_head list; /* entry on zone->cts */ }; #endif /* CONFIG_SFC_SRIOV */ diff --git a/drivers/net/ethernet/sfc/tc_counters.c b/drivers/net/ethernet/sfc/tc_counters.c index 979f49058a0c..0fafb47ea082 100644 --- a/drivers/net/ethernet/sfc/tc_counters.c +++ b/drivers/net/ethernet/sfc/tc_counters.c @@ -129,8 +129,8 @@ static void efx_tc_counter_work(struct work_struct *work) /* Counter allocation */ -static struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx, - int type) +struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx, + int type) { struct efx_tc_counter *cnt; int rc, rc2; @@ -169,8 +169,8 @@ static struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx return ERR_PTR(rc > 0 ? -EIO : rc); } -static void efx_tc_flower_release_counter(struct efx_nic *efx, - struct efx_tc_counter *cnt) +void efx_tc_flower_release_counter(struct efx_nic *efx, + struct efx_tc_counter *cnt) { int rc; diff --git a/drivers/net/ethernet/sfc/tc_counters.h b/drivers/net/ethernet/sfc/tc_counters.h index 41e57f34b763..f18d71c13600 100644 --- a/drivers/net/ethernet/sfc/tc_counters.h +++ b/drivers/net/ethernet/sfc/tc_counters.h @@ -49,6 +49,10 @@ int efx_tc_init_counters(struct efx_nic *efx); void efx_tc_destroy_counters(struct efx_nic *efx); void efx_tc_fini_counters(struct efx_nic *efx); +struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx, + int type); +void efx_tc_flower_release_counter(struct efx_nic *efx, + struct efx_tc_counter *cnt); struct efx_tc_counter_index *efx_tc_flower_get_counter_index( struct efx_nic *efx, unsigned long cookie, enum efx_tc_counter_type type); From patchwork Mon Aug 7 13:48:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: edward.cree@amd.com X-Patchwork-Id: 13344283 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0B92411C8D for ; Mon, 7 Aug 2023 13:49:44 +0000 (UTC) Received: from NAM12-MW2-obe.outbound.protection.outlook.com (mail-mw2nam12on2080.outbound.protection.outlook.com [40.107.244.80]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4C52819BA for ; Mon, 7 Aug 2023 06:49:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Gzr2Pp5MxyEFjzQqeRMtfaZQ1dQ2Xat68cOfN6/zuMOG55uQaHW2jnZKwghCzwpvrJPTEGaCzauolns7AptxDd2OeIf1lfqVDXvv7VaZZmdiHF8z7/9xEahQ0le8kNpDJGbsiNlLLIejft7A0u/sJcXVJAVrSGKcLcmHZ2+iFRw3EG5PZT8vUBwTbRlIcPPvEaEiJ+qEI6B93UOUOsWW1pHcW6iaUnWYbDeMFWP9XDawYUMY0kvpT6gQ6JryxKvzU/rnKuf53tfz82Q8SXAAQWe3nFFIz9+LpO+eMfTqo88XDolqbWxVwu60wBCyFbUj3XpGzd12K66DfexprT7rsA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=ia02nXZp1sk/NbeDBe5ihV9VyGPXi/wfMPJ7ZM1DvwI=; b=lq8eqDJKyrdKHBzKyfy/x0D0TS597+7TbEVeU+bMO5Bnhx4bfvnVD2RuzsoZfv9aYkObIj5SPJjQdWdMAJeujV+dRwS+sMJZ5LMxdXmau96NyqAmldJgghoikymJNiJ4GHsWuwF9n+xAfyD1Igh/Kles3jnO04qjtvISekux0ERo6fzqLIcGuVtZh1y05k/Keu7W4eZP6SCrRSGkiSOiiwutI13TFNpr3ts5SkjEf+1laKAGiKEYpamVf9sQU+g0cTSmlVTGN3KQMQs+Nzkb9Nk5ZjrTLlmqAiDVEdkbA7/ATglJ1n1z6IuSjyDfF/DTshfirHHUHeub0Xl0+0liyA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=davemloft.net smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=ia02nXZp1sk/NbeDBe5ihV9VyGPXi/wfMPJ7ZM1DvwI=; b=v0a7VWKXIoDD7H8I0GAr2WRL/JYMYFbtCacH61LSlXysgXVVwtJ95j/0bp6YzgYKLaA6YDcarpahRqAGDPZD8sthj5/x62bBL6cQh72/iwiodNS7+BpMxikSq5FVCmvowHPug63NWuFRKWxAGnn984VS2pcZTY4GyqLkMs3Wyrs= Received: from SJ0PR05CA0121.namprd05.prod.outlook.com (2603:10b6:a03:33d::6) by IA0PR12MB8864.namprd12.prod.outlook.com (2603:10b6:208:485::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6652.22; Mon, 7 Aug 2023 13:49:25 +0000 Received: from CO1PEPF000042A7.namprd03.prod.outlook.com (2603:10b6:a03:33d:cafe::c8) by SJ0PR05CA0121.outlook.office365.com (2603:10b6:a03:33d::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6678.16 via Frontend Transport; Mon, 7 Aug 2023 13:49:25 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by CO1PEPF000042A7.mail.protection.outlook.com (10.167.243.36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6652.19 via Frontend Transport; Mon, 7 Aug 2023 13:49:24 +0000 Received: from SATLEXMB05.amd.com (10.181.40.146) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Mon, 7 Aug 2023 08:49:20 -0500 Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB05.amd.com (10.181.40.146) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Mon, 7 Aug 2023 08:49:19 -0500 Received: from xcbecree41x.xilinx.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27 via Frontend Transport; Mon, 7 Aug 2023 08:49:18 -0500 From: To: , , , , CC: Edward Cree , , , Pieter Jansen van Vuuren , Simon Horman Subject: [PATCH v2 net-next 5/7] sfc: handle non-zero chain_index on TC rules Date: Mon, 7 Aug 2023 14:48:09 +0100 Message-ID: <67666793a7db914023421e309553e0161821f7c7.1691415479.git.ecree.xilinx@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PEPF000042A7:EE_|IA0PR12MB8864:EE_ X-MS-Office365-Filtering-Correlation-Id: e2051dd7-1de0-458f-07d4-08db974d1c91 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: fobuF+fyNgCdoofz2ZeNGTiZCGKLp6QNdUEW1wdLw++/Kad3RGViMYA1ri9rv50j3rUuV/Hcr3eoFQmJLMnBgzdcUsvelbGgpQscu1EbBNu95gxGucmbF5ZUte81Zh4v+sl6lbn6O7r5dGv5BFccX/V6BrXSZeP2o5QCcfLIQ2efpXX3uSlSVTC3g40U9tpJ8w+55V2ZZC567mleOuBqnXo7g7wP061s5e79tVUHXVyef/4zkZ5gCW3ZNgrCyf2EQgLGI6d7H3v+0eev8WSCmDh7388sHqH3Qfhq/6vN070ZpZ5J80Ibsuz30eVNbwBcbvbByINGetUePz/u8Y+1Ap2UnpiuG0S7AKKHv3MmO5EL+zF2w2vcU/+c7Ug3os7HuQGQwto7tGVq8jlcZm3hqI/Ui+iPclIOu7HtpgjDeFQCjNgjm1RjHBuTfGE1kr5JgQ6KAdwoHdonOTvu53FOFFhQtIIYi3gMplmpdyXqXTld5f8yKNG5Ce8A0Iyeoo95DpRF1wMAWiaw01RcrjL48/uKzb+250kr6H/F5+RanEa4jdCWzaWgXM9bte3kINc1SeQpiP+F8MKEh47dds9la3849LDFQYANRGp5QyNUZYVD28sszptR+usAiMhiuCmvFpToWTQ08+inaoXeFNx68fM7/ztsqqjFjpBW4sqVvNG8FQJwOYZfoA8EP38h8f9rWimRB27m3JOhxbW006WZdPIw47A+f1n+ATILI1X8mLpgPgFjb0zsDop5KjEhuf3qjdwo9Gfex6MQ8X0nHut8BA== X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:SATLEXMB04.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230028)(4636009)(396003)(39860400002)(346002)(376002)(136003)(451199021)(186006)(1800799003)(82310400008)(40470700004)(46966006)(36840700001)(40480700001)(336012)(40460700003)(36756003)(4326008)(9686003)(316002)(86362001)(55446002)(82740400003)(110136005)(356005)(54906003)(70586007)(6666004)(70206006)(478600001)(81166007)(41300700001)(26005)(426003)(8676002)(8936002)(47076005)(36860700001)(2876002)(2906002)(30864003)(83380400001)(5660300002)(36900700001);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Aug 2023 13:49:24.9037 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: e2051dd7-1de0-458f-07d4-08db974d1c91 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CO1PEPF000042A7.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: IA0PR12MB8864 X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_SPF_HELO, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Edward Cree Map it to an 8-bit recirc_id for use by the hardware. Currently nothing in the driver is offloading 'goto chain' actions, so these rules cannot yet be hit. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree --- drivers/net/ethernet/sfc/tc.c | 169 ++++++++++++++++++++---- drivers/net/ethernet/sfc/tc.h | 15 ++- drivers/net/ethernet/sfc/tc_conntrack.c | 9 ++ drivers/net/ethernet/sfc/tc_conntrack.h | 3 +- 4 files changed, 170 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 44a6fc30b722..181636d07024 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -97,6 +97,12 @@ static const struct rhashtable_params efx_tc_match_action_ht_params = { .head_offset = offsetof(struct efx_tc_flow_rule, linkage), }; +static const struct rhashtable_params efx_tc_recirc_ht_params = { + .key_len = offsetof(struct efx_tc_recirc_id, linkage), + .key_offset = 0, + .head_offset = offsetof(struct efx_tc_recirc_id, linkage), +}; + static void efx_tc_free_action_set(struct efx_nic *efx, struct efx_tc_action_set *act, bool in_hw) { @@ -576,12 +582,65 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx, return rc; } +static struct efx_tc_recirc_id *efx_tc_get_recirc_id(struct efx_nic *efx, + u32 chain_index, + struct net_device *net_dev) +{ + struct efx_tc_recirc_id *rid, *old; + int rc; + + rid = kzalloc(sizeof(*rid), GFP_USER); + if (!rid) + return ERR_PTR(-ENOMEM); + rid->chain_index = chain_index; + /* We don't take a reference here, because it's implied - if there's + * a rule on the net_dev that's been offloaded to us, then the net_dev + * can't go away until the rule has been deoffloaded. + */ + rid->net_dev = net_dev; + old = rhashtable_lookup_get_insert_fast(&efx->tc->recirc_ht, + &rid->linkage, + efx_tc_recirc_ht_params); + if (old) { + /* don't need our new entry */ + kfree(rid); + if (!refcount_inc_not_zero(&old->ref)) + return ERR_PTR(-EAGAIN); + /* existing entry found */ + rid = old; + } else { + rc = ida_alloc_range(&efx->tc->recirc_ida, 1, U8_MAX, GFP_USER); + if (rc < 0) { + rhashtable_remove_fast(&efx->tc->recirc_ht, + &rid->linkage, + efx_tc_recirc_ht_params); + kfree(rid); + return ERR_PTR(rc); + } + rid->fw_id = rc; + refcount_set(&rid->ref, 1); + } + return rid; +} + +static void efx_tc_put_recirc_id(struct efx_nic *efx, struct efx_tc_recirc_id *rid) +{ + if (!refcount_dec_and_test(&rid->ref)) + return; /* still in use */ + rhashtable_remove_fast(&efx->tc->recirc_ht, &rid->linkage, + efx_tc_recirc_ht_params); + ida_free(&efx->tc->recirc_ida, rid->fw_id); + kfree(rid); +} + static void efx_tc_delete_rule(struct efx_nic *efx, struct efx_tc_flow_rule *rule) { efx_mae_delete_rule(efx, rule->fw_id); /* Release entries in subsidiary tables */ efx_tc_free_action_set_list(efx, &rule->acts, true); + if (rule->match.rid) + efx_tc_put_recirc_id(efx, rule->match.rid); if (rule->match.encap) efx_tc_flower_release_encap_match(efx, rule->match.encap); rule->fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL; @@ -685,8 +744,17 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, match.mask.ingress_port = ~0; if (tc->common.chain_index) { - NL_SET_ERR_MSG_MOD(extack, "No support for nonzero chain_index"); - return -EOPNOTSUPP; + struct efx_tc_recirc_id *rid; + + rid = efx_tc_get_recirc_id(efx, tc->common.chain_index, net_dev); + if (IS_ERR(rid)) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Failed to allocate a hardware recirculation ID for chain_index %u", + tc->common.chain_index); + return PTR_ERR(rid); + } + match.rid = rid; + match.value.recirc_id = rid->fw_id; } match.mask.recirc_id = 0xff; @@ -706,12 +774,13 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, if (!found) { /* We don't care. */ netif_dbg(efx, drv, efx->net_dev, "Ignoring foreign filter that doesn't egdev us\n"); - return -EOPNOTSUPP; + rc = -EOPNOTSUPP; + goto release; } rc = efx_mae_match_check_caps(efx, &match.mask, NULL); if (rc) - return rc; + goto release; if (efx_tc_match_is_encap(&match.mask)) { enum efx_encap_type type; @@ -720,7 +789,8 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, if (type == EFX_ENCAP_TYPE_NONE) { NL_SET_ERR_MSG_MOD(extack, "Egress encap match on unsupported tunnel device"); - return -EOPNOTSUPP; + rc = -EOPNOTSUPP; + goto release; } rc = efx_mae_check_encap_type_supported(efx, type); @@ -728,25 +798,26 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, NL_SET_ERR_MSG_FMT_MOD(extack, "Firmware reports no support for %s encap match", efx_tc_encap_type_name(type)); - return rc; + goto release; } rc = efx_tc_flower_record_encap_match(efx, &match, type, EFX_TC_EM_DIRECT, 0, 0, extack); if (rc) - return rc; + goto release; } else { /* This is not a tunnel decap rule, ignore it */ netif_dbg(efx, drv, efx->net_dev, "Ignoring foreign filter without encap match\n"); - return -EOPNOTSUPP; + rc = -EOPNOTSUPP; + goto release; } rule = kzalloc(sizeof(*rule), GFP_USER); if (!rule) { rc = -ENOMEM; - goto out_free; + goto release; } INIT_LIST_HEAD(&rule->acts.list); rule->cookie = tc->cookie; @@ -758,7 +829,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, "Ignoring already-offloaded rule (cookie %lx)\n", tc->cookie); rc = -EEXIST; - goto out_free; + goto release; } act = kzalloc(sizeof(*act), GFP_USER); @@ -916,15 +987,17 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, /* We failed to insert the rule, so free up any entries we created in * subsidiary tables. */ + if (match.rid) + efx_tc_put_recirc_id(efx, match.rid); if (act) efx_tc_free_action_set(efx, act, false); if (rule) { - rhashtable_remove_fast(&efx->tc->match_action_ht, - &rule->linkage, - efx_tc_match_action_ht_params); + if (!old) + rhashtable_remove_fast(&efx->tc->match_action_ht, + &rule->linkage, + efx_tc_match_action_ht_params); efx_tc_free_action_set_list(efx, &rule->acts, false); } -out_free: kfree(rule); if (match.encap) efx_tc_flower_release_encap_match(efx, match.encap); @@ -986,19 +1059,45 @@ static int efx_tc_flower_replace(struct efx_nic *efx, return -EOPNOTSUPP; } + /* chain_index 0 is always recirc_id 0 (and does not appear in recirc_ht). + * Conveniently, match.rid == NULL and match.value.recirc_id == 0 owing + * to the initial memset(), so we don't need to do anything in that case. + */ if (tc->common.chain_index) { - NL_SET_ERR_MSG_MOD(extack, "No support for nonzero chain_index"); - return -EOPNOTSUPP; + struct efx_tc_recirc_id *rid; + + /* Note regarding passed net_dev: + * VFreps and PF can share chain namespace, as they have + * distinct ingress_mports. So we don't need to burn an + * extra recirc_id if both use the same chain_index. + * (Strictly speaking, we could give each VFrep its own + * recirc_id namespace that doesn't take IDs away from the + * PF, but that would require a bunch of additional IDAs - + * one for each representor - and that's not likely to be + * the main cause of recirc_id exhaustion anyway.) + */ + rid = efx_tc_get_recirc_id(efx, tc->common.chain_index, + efx->net_dev); + if (IS_ERR(rid)) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Failed to allocate a hardware recirculation ID for chain_index %u", + tc->common.chain_index); + return PTR_ERR(rid); + } + match.rid = rid; + match.value.recirc_id = rid->fw_id; } match.mask.recirc_id = 0xff; rc = efx_mae_match_check_caps(efx, &match.mask, extack); if (rc) - return rc; + goto release; rule = kzalloc(sizeof(*rule), GFP_USER); - if (!rule) - return -ENOMEM; + if (!rule) { + rc = -ENOMEM; + goto release; + } INIT_LIST_HEAD(&rule->acts.list); rule->cookie = tc->cookie; old = rhashtable_lookup_get_insert_fast(&efx->tc->match_action_ht, @@ -1008,8 +1107,8 @@ static int efx_tc_flower_replace(struct efx_nic *efx, netif_dbg(efx, drv, efx->net_dev, "Already offloaded rule (cookie %lx)\n", tc->cookie); NL_SET_ERR_MSG_MOD(extack, "Rule already offloaded"); - kfree(rule); - return -EEXIST; + rc = -EEXIST; + goto release; } /* Parse actions */ @@ -1327,12 +1426,15 @@ static int efx_tc_flower_replace(struct efx_nic *efx, /* We failed to insert the rule, so free up any entries we created in * subsidiary tables. */ + if (match.rid) + efx_tc_put_recirc_id(efx, match.rid); if (act) efx_tc_free_action_set(efx, act, false); if (rule) { - rhashtable_remove_fast(&efx->tc->match_action_ht, - &rule->linkage, - efx_tc_match_action_ht_params); + if (!old) + rhashtable_remove_fast(&efx->tc->match_action_ht, + &rule->linkage, + efx_tc_match_action_ht_params); efx_tc_free_action_set_list(efx, &rule->acts, false); } kfree(rule); @@ -1702,6 +1804,16 @@ static void efx_tc_encap_match_free(void *ptr, void *__unused) kfree(encap); } +static void efx_tc_recirc_free(void *ptr, void *arg) +{ + struct efx_tc_recirc_id *rid = ptr; + struct efx_nic *efx = arg; + + WARN_ON(refcount_read(&rid->ref)); + ida_free(&efx->tc->recirc_ida, rid->fw_id); + kfree(rid); +} + static void efx_tc_flow_free(void *ptr, void *arg) { struct efx_tc_flow_rule *rule = ptr; @@ -1751,6 +1863,10 @@ int efx_init_struct_tc(struct efx_nic *efx) rc = efx_tc_init_conntrack(efx); if (rc < 0) goto fail_conntrack; + rc = rhashtable_init(&efx->tc->recirc_ht, &efx_tc_recirc_ht_params); + if (rc < 0) + goto fail_recirc_ht; + ida_init(&efx->tc->recirc_ida); efx->tc->reps_filter_uc = -1; efx->tc->reps_filter_mc = -1; INIT_LIST_HEAD(&efx->tc->dflt.pf.acts.list); @@ -1763,6 +1879,8 @@ int efx_init_struct_tc(struct efx_nic *efx) efx->tc->facts.reps.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL; efx->extra_channel_type[EFX_EXTRA_CHANNEL_TC] = &efx_tc_channel_type; return 0; +fail_recirc_ht: + efx_tc_destroy_conntrack(efx); fail_conntrack: rhashtable_destroy(&efx->tc->match_action_ht); fail_match_action_ht: @@ -1799,6 +1917,9 @@ void efx_fini_struct_tc(struct efx_nic *efx) rhashtable_free_and_destroy(&efx->tc->encap_match_ht, efx_tc_encap_match_free, NULL); efx_tc_fini_conntrack(efx); + rhashtable_free_and_destroy(&efx->tc->recirc_ht, efx_tc_recirc_free, efx); + WARN_ON(!ida_is_empty(&efx->tc->recirc_ida)); + ida_destroy(&efx->tc->recirc_ida); efx_tc_fini_counters(efx); efx_tc_fini_encap_actions(efx); mutex_unlock(&efx->tc->mutex); diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index 2aba9ca00618..af15020c8da7 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -45,7 +45,7 @@ struct efx_tc_action_set { struct efx_tc_match_fields { /* L1 */ u32 ingress_port; - u8 recirc_id; + u8 recirc_id; /* mapped from (u32) TC chain_index to smaller space */ /* L2 (inner when encap) */ __be16 eth_proto; __be16 vlan_tci[2], vlan_proto[2]; @@ -115,10 +115,19 @@ struct efx_tc_encap_match { struct efx_tc_encap_match *pseudo; /* Referenced pseudo EM if needed */ }; +struct efx_tc_recirc_id { + u32 chain_index; + struct net_device *net_dev; + struct rhash_head linkage; + refcount_t ref; + u8 fw_id; /* index allocated for use in the MAE */ +}; + struct efx_tc_match { struct efx_tc_match_fields value; struct efx_tc_match_fields mask; struct efx_tc_encap_match *encap; + struct efx_tc_recirc_id *rid; }; struct efx_tc_action_set_list { @@ -197,6 +206,8 @@ struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ * @ct_zone_ht: Hashtable of TC conntrack flowtable bindings * @ct_ht: Hashtable of TC conntrack flow entries * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) + * @recirc_ht: Hashtable of recirculation ID mappings (&struct efx_tc_recirc_id) + * @recirc_ida: Recirculation ID allocator * @meta_ct: MAE table layout for conntrack table * @reps_mport_id: MAE port allocated for representor RX * @reps_filter_uc: VNIC filter for representor unicast RX (promisc) @@ -231,6 +242,8 @@ struct efx_tc_state { struct rhashtable ct_zone_ht; struct rhashtable ct_ht; struct rhashtable neigh_ht; + struct rhashtable recirc_ht; + struct ida recirc_ida; struct efx_tc_table_ct meta_ct; u32 reps_mport_id, reps_mport_vport_id; s32 reps_filter_uc, reps_filter_mc; diff --git a/drivers/net/ethernet/sfc/tc_conntrack.c b/drivers/net/ethernet/sfc/tc_conntrack.c index 6729b3796a8b..54ed288543d0 100644 --- a/drivers/net/ethernet/sfc/tc_conntrack.c +++ b/drivers/net/ethernet/sfc/tc_conntrack.c @@ -73,6 +73,15 @@ int efx_tc_init_conntrack(struct efx_nic *efx) return rc; } +/* Only call this in init failure teardown. + * Normal exit should fini instead as there may be entries in the table. + */ +void efx_tc_destroy_conntrack(struct efx_nic *efx) +{ + rhashtable_destroy(&efx->tc->ct_ht); + rhashtable_destroy(&efx->tc->ct_zone_ht); +} + void efx_tc_fini_conntrack(struct efx_nic *efx) { rhashtable_free_and_destroy(&efx->tc->ct_zone_ht, efx_tc_ct_zone_free, NULL); diff --git a/drivers/net/ethernet/sfc/tc_conntrack.h b/drivers/net/ethernet/sfc/tc_conntrack.h index ef5cf96c0649..e75c8eb1965d 100644 --- a/drivers/net/ethernet/sfc/tc_conntrack.h +++ b/drivers/net/ethernet/sfc/tc_conntrack.h @@ -26,8 +26,9 @@ struct efx_tc_ct_zone { struct list_head cts; /* list of efx_tc_ct_entry in this zone */ }; -/* create/teardown hashtables */ +/* create/uncreate/teardown hashtables */ int efx_tc_init_conntrack(struct efx_nic *efx); +void efx_tc_destroy_conntrack(struct efx_nic *efx); void efx_tc_fini_conntrack(struct efx_nic *efx); struct efx_tc_ct_zone *efx_tc_ct_register_zone(struct efx_nic *efx, u16 zone, From patchwork Mon Aug 7 13:48:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: edward.cree@amd.com X-Patchwork-Id: 13344281 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AF8631118A for ; Mon, 7 Aug 2023 13:49:40 +0000 (UTC) Received: from NAM11-CO1-obe.outbound.protection.outlook.com (mail-co1nam11on2041.outbound.protection.outlook.com [40.107.220.41]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 41D1F1998 for ; Mon, 7 Aug 2023 06:49:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=CztAevHcN2uv1WI85wRtblhZhEJc8pQdI3X+qKFKIYMMOtspRiK/BCF3qCttfpHFpf1yitU/wbZ3PXNVFGnPWmdPZFihLSp5RBhD8fsJeiE9XK/Ln6PAnuJQTIsjSYb+90KTtXKKa8feMrhroHTatkTEq1cTWQaAK3z7BIlyjOY0DR3MYEoZ7ADlPjS39ae3UYS0yt2EK50Y8scCcbP8kBMx778KzPLbNp+kaFQZMnMWbyRyAMimABcdeBrrGGLxeok1aqYjwlkK/haoodoy0762fAOUiGDihUGe0lsbE5L5oKKcFa2663jc9AJ0OjHUblxoB2dJshrB+KutRp2Wfw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=JSic2QC/y1iRZ7xYGiB7kqzZdwh2hDF66VduSmgwJKY=; b=LqMjtVaalOxbAf7k5xauOZ4t9Mj/ztlJs4loleOrBB6NzPQSo1yCtU9sl5okahytbdl0JSbCMuAazHnbUwGfQTuK/hnEL8j3GY2gZV/o0JJnKX/xf5EsWaK9mzElWKSHXeCaKWlmU20O2hzOqVP7p866AihfBCcDmvyLaZP/PegbxZ0wk3n6S8zZJ4+ln7LglMzQzPZPqnNoLcgiGZ4bFXbKgV+s9BlPI5ksV4mFfY4e+iLQaALyQ7u720J4p1aHpxhQBFRulQJZWO5/5K3do7g6J6Ezxisl0vKnTF5P1fO4VRm2weNM+E/MzCIAOMZQYbSXb4SYA2jzM+en38uEow== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=davemloft.net smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=JSic2QC/y1iRZ7xYGiB7kqzZdwh2hDF66VduSmgwJKY=; b=m1O2i40bL7lui3iWYPrbiZPjjPyKZh748TQoviUqTAG0uVPeBbEdqrnwxei8eGQMcfGPu8rZx09GXB/b103/dlPLVfWFkc4y2JDOwrx6oJ5sNPdJe72qJysaSFC6xi0lZ9rb0EcOzCzA0e9MT7G3B9123s/e1jq1+dQ3ObCbP2g= Received: from CYXPR03CA0075.namprd03.prod.outlook.com (2603:10b6:930:d3::21) by MW4PR12MB6998.namprd12.prod.outlook.com (2603:10b6:303:20a::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6652.26; Mon, 7 Aug 2023 13:49:22 +0000 Received: from CY4PEPF0000E9D7.namprd05.prod.outlook.com (2603:10b6:930:d3:cafe::1f) by CYXPR03CA0075.outlook.office365.com (2603:10b6:930:d3::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6652.27 via Frontend Transport; Mon, 7 Aug 2023 13:49:22 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB03.amd.com; pr=C Received: from SATLEXMB03.amd.com (165.204.84.17) by CY4PEPF0000E9D7.mail.protection.outlook.com (10.167.241.78) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6652.19 via Frontend Transport; Mon, 7 Aug 2023 13:49:22 +0000 Received: from SATLEXMB05.amd.com (10.181.40.146) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Mon, 7 Aug 2023 08:49:21 -0500 Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB05.amd.com (10.181.40.146) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Mon, 7 Aug 2023 08:49:21 -0500 Received: from xcbecree41x.xilinx.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27 via Frontend Transport; Mon, 7 Aug 2023 08:49:20 -0500 From: To: , , , , CC: Edward Cree , , , Pieter Jansen van Vuuren , Simon Horman Subject: [PATCH v2 net-next 6/7] sfc: conntrack state matches in TC rules Date: Mon, 7 Aug 2023 14:48:10 +0100 Message-ID: <9c8e85dfdf0a339f55285ab586e83485e0acb005.1691415479.git.ecree.xilinx@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CY4PEPF0000E9D7:EE_|MW4PR12MB6998:EE_ X-MS-Office365-Filtering-Correlation-Id: de9de8b2-85c9-436b-bd7b-08db974d1af7 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: PW8PBocpG/xtT75eXkEsBsBGRXsC/X5VHGm2gr4E6/wSW+xEopatjQ5jD+ibIt1C/PDPQM/ue+fzfp0UxvIOUFyspOhEa2Ncfcm/yRc674Zo60QcNuPeyeFY4ryc3yZuROj3za7i8CUQ3XmVRnkh+/t2V4fvSin9BA5J9rIt89gjJP1DdTgZ1UQVwHX2yhX6HLOgfkEY3fl5kQzIl5VBFfgb3EWd1Ci+QNTl2wVNeaqBaQ2p/PDR0JIh/F5zVhLwQVA/XlCzQinUEYo8xr1bhV3GSq1SwHY93xIzQL6JtTXfokrczBzoypV13Ik/3d5dy5ZhC2XZMHJu/lXzHUpoKjUnGADEFcZZDEfX+PeOPswQ/ARvcac3nxUSmdbHLfVIKfelBcvk1nF9L5JuIXlh5chiwgsdv6nbYMRZug9vc+oBPewLtEGvBD0DpYJdmgcDDLttah0xWtxchwTXMgDxeBEE6xlgX6m0Zw8NYWCvc2RC9bhGdbSSGWcSMF0fjWgfJQtBd+q5NW+hv42SPCPgT+xox32J3G9LHgnu18lcjEqSsX5OoW2pJT0VfFZEWQ/jnd/4iG8VGW4mVY8anhQH1XE5k2d+2IBvFtWiyqlCQAXFbLEBPDF55+wpc60e6gOT6GpKJbs9vYhluI3zPldYmCGCffBP+wh0FFHg9NSDKM3DdJKIB1EnJZYkkYePip21owJcS2gvHAcjkcu4CsNN7whgRYs6r2stHRxPmb1/AQL+sZrSzEIhRIa4l9EvAsf3FYx6I5I17aCHw0BKfujTiQ== X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:SATLEXMB03.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230028)(4636009)(396003)(39860400002)(376002)(346002)(136003)(82310400008)(451199021)(1800799003)(186006)(46966006)(36840700001)(40470700004)(36860700001)(36756003)(86362001)(55446002)(83380400001)(81166007)(356005)(82740400003)(40460700003)(40480700001)(9686003)(6666004)(336012)(26005)(316002)(41300700001)(70206006)(4326008)(478600001)(54906003)(110136005)(2876002)(2906002)(5660300002)(426003)(47076005)(8936002)(8676002)(70586007)(36900700001);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Aug 2023 13:49:22.2682 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: de9de8b2-85c9-436b-bd7b-08db974d1af7 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB03.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CY4PEPF0000E9D7.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW4PR12MB6998 X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_SPF_HELO, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Edward Cree Parse ct_state trk/est, mark and zone out of flower keys, and plumb them through to the hardware, performing some minor translations. Nothing can actually hit them yet as we're not offloading any DO_CT actions. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree --- drivers/net/ethernet/sfc/mae.c | 33 +++++++++++++++-- drivers/net/ethernet/sfc/mcdi.h | 5 +++ drivers/net/ethernet/sfc/tc.c | 66 +++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/tc.h | 5 +++ 4 files changed, 105 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index 8ebf71a54bf9..1fa0958d5262 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -695,8 +695,13 @@ int efx_mae_match_check_caps(struct efx_nic *efx, CHECK(L4_SPORT, l4_sport) || CHECK(L4_DPORT, l4_dport) || CHECK(TCP_FLAGS, tcp_flags) || + CHECK_BIT(TCP_SYN_FIN_RST, tcp_syn_fin_rst) || CHECK_BIT(IS_IP_FRAG, ip_frag) || CHECK_BIT(IP_FIRST_FRAG, ip_firstfrag) || + CHECK_BIT(DO_CT, ct_state_trk) || + CHECK_BIT(CT_HIT, ct_state_est) || + CHECK(CT_MARK, ct_mark) || + CHECK(CT_DOMAIN, ct_zone) || CHECK(RECIRC_ID, recirc_id)) return rc; /* Matches on outer fields are done in a separate hardware table, @@ -1672,20 +1677,40 @@ static int efx_mae_populate_match_criteria(MCDI_DECLARE_STRUCT_PTR(match_crit), } MCDI_STRUCT_SET_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_MASK, match->mask.ingress_port); - EFX_POPULATE_DWORD_2(*_MCDI_STRUCT_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS), + EFX_POPULATE_DWORD_5(*_MCDI_STRUCT_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS), + MAE_FIELD_MASK_VALUE_PAIRS_V2_DO_CT, + match->value.ct_state_trk, + MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_HIT, + match->value.ct_state_est, MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_IP_FRAG, match->value.ip_frag, MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FIRST_FRAG, - match->value.ip_firstfrag); - EFX_POPULATE_DWORD_2(*_MCDI_STRUCT_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK), + match->value.ip_firstfrag, + MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_SYN_FIN_RST, + match->value.tcp_syn_fin_rst); + EFX_POPULATE_DWORD_5(*_MCDI_STRUCT_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK), + MAE_FIELD_MASK_VALUE_PAIRS_V2_DO_CT, + match->mask.ct_state_trk, + MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_HIT, + match->mask.ct_state_est, MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_IP_FRAG, match->mask.ip_frag, MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FIRST_FRAG, - match->mask.ip_firstfrag); + match->mask.ip_firstfrag, + MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_SYN_FIN_RST, + match->mask.tcp_syn_fin_rst); MCDI_STRUCT_SET_BYTE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID, match->value.recirc_id); MCDI_STRUCT_SET_BYTE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_MASK, match->mask.recirc_id); + MCDI_STRUCT_SET_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK, + match->value.ct_mark); + MCDI_STRUCT_SET_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_MASK, + match->mask.ct_mark); + MCDI_STRUCT_SET_WORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN, + match->value.ct_zone); + MCDI_STRUCT_SET_WORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_MASK, + match->mask.ct_zone); MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE, match->value.eth_proto); MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_MASK, diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 995a26686fd8..700d0252aebd 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -229,6 +229,11 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); BUILD_BUG_ON(MC_CMD_ ## _field ## _OFST & 1); \ *(__force __le16 *)MCDI_PTR(_buf, _field) = cpu_to_le16(_value);\ } while (0) +#define MCDI_STRUCT_SET_WORD(_buf, _field, _value) do { \ + BUILD_BUG_ON(_field ## _LEN != 2); \ + BUILD_BUG_ON(_field ## _OFST & 1); \ + *(__force __le16 *)MCDI_STRUCT_PTR(_buf, _field) = cpu_to_le16(_value);\ + } while (0) #define MCDI_WORD(_buf, _field) \ ((u16)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 2) + \ le16_to_cpu(*(__force const __le16 *)MCDI_PTR(_buf, _field))) diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 181636d07024..a9f4bfaacac3 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -222,6 +222,7 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx, BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP) | BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS) | BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_CT) | BIT_ULL(FLOW_DISSECTOR_KEY_TCP) | BIT_ULL(FLOW_DISSECTOR_KEY_IP))) { NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported flower keys %#llx", @@ -363,6 +364,31 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx, dissector->used_keys); return -EOPNOTSUPP; } + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CT)) { + struct flow_match_ct fm; + + flow_rule_match_ct(rule, &fm); + match->value.ct_state_trk = !!(fm.key->ct_state & TCA_FLOWER_KEY_CT_FLAGS_TRACKED); + match->mask.ct_state_trk = !!(fm.mask->ct_state & TCA_FLOWER_KEY_CT_FLAGS_TRACKED); + match->value.ct_state_est = !!(fm.key->ct_state & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED); + match->mask.ct_state_est = !!(fm.mask->ct_state & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED); + if (fm.mask->ct_state & ~(TCA_FLOWER_KEY_CT_FLAGS_TRACKED | + TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED)) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported ct_state match %#x", + fm.mask->ct_state); + return -EOPNOTSUPP; + } + match->value.ct_mark = fm.key->ct_mark; + match->mask.ct_mark = fm.mask->ct_mark; + match->value.ct_zone = fm.key->ct_zone; + match->mask.ct_zone = fm.mask->ct_zone; + + if (memchr_inv(fm.mask->ct_labels, 0, sizeof(fm.mask->ct_labels))) { + NL_SET_ERR_MSG_MOD(extack, "Matching on ct_label not supported"); + return -EOPNOTSUPP; + } + } return 0; } @@ -758,6 +784,26 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, } match.mask.recirc_id = 0xff; + /* AR table can't match on DO_CT (+trk). But a commonly used pattern is + * +trk+est, which is strictly implied by +est, so rewrite it to that. + */ + if (match.mask.ct_state_trk && match.value.ct_state_trk && + match.mask.ct_state_est && match.value.ct_state_est) + match.mask.ct_state_trk = 0; + /* Thanks to CT_TCP_FLAGS_INHIBIT, packets with interesting flags could + * match +trk-est (CT_HIT=0) despite being on an established connection. + * So make -est imply -tcp_syn_fin_rst match to ensure these packets + * still hit the software path. + */ + if (match.mask.ct_state_est && !match.value.ct_state_est) { + if (match.value.tcp_syn_fin_rst) { + /* Can't offload this combination */ + rc = -EOPNOTSUPP; + goto release; + } + match.mask.tcp_syn_fin_rst = true; + } + flow_action_for_each(i, fa, &fr->action) { switch (fa->id) { case FLOW_ACTION_REDIRECT: @@ -1089,6 +1135,26 @@ static int efx_tc_flower_replace(struct efx_nic *efx, } match.mask.recirc_id = 0xff; + /* AR table can't match on DO_CT (+trk). But a commonly used pattern is + * +trk+est, which is strictly implied by +est, so rewrite it to that. + */ + if (match.mask.ct_state_trk && match.value.ct_state_trk && + match.mask.ct_state_est && match.value.ct_state_est) + match.mask.ct_state_trk = 0; + /* Thanks to CT_TCP_FLAGS_INHIBIT, packets with interesting flags could + * match +trk-est (CT_HIT=0) despite being on an established connection. + * So make -est imply -tcp_syn_fin_rst match to ensure these packets + * still hit the software path. + */ + if (match.mask.ct_state_est && !match.value.ct_state_est) { + if (match.value.tcp_syn_fin_rst) { + /* Can't offload this combination */ + rc = -EOPNOTSUPP; + goto release; + } + match.mask.tcp_syn_fin_rst = true; + } + rc = efx_mae_match_check_caps(efx, &match.mask, extack); if (rc) goto release; diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index af15020c8da7..ce8e30743a3a 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -60,6 +60,7 @@ struct efx_tc_match_fields { /* L4 */ __be16 l4_sport, l4_dport; /* Ports (UDP, TCP) */ __be16 tcp_flags; + bool tcp_syn_fin_rst; /* true if ANY of SYN/FIN/RST are set */ /* Encap. The following are *outer* fields. Note that there are no * outer eth (L2) fields; this is because TC doesn't have them. */ @@ -68,6 +69,10 @@ struct efx_tc_match_fields { u8 enc_ip_tos, enc_ip_ttl; __be16 enc_sport, enc_dport; __be32 enc_keyid; /* e.g. VNI, VSID */ + /* Conntrack. */ + u16 ct_state_trk:1, ct_state_est:1; + u32 ct_mark; + u16 ct_zone; }; static inline bool efx_tc_match_is_encap(const struct efx_tc_match_fields *mask) From patchwork Mon Aug 7 13:48:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: edward.cree@amd.com X-Patchwork-Id: 13344284 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 40B8511C93 for ; Mon, 7 Aug 2023 13:49:43 +0000 (UTC) Received: from NAM10-MW2-obe.outbound.protection.outlook.com (mail-mw2nam10on2086.outbound.protection.outlook.com [40.107.94.86]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E429119B5 for ; Mon, 7 Aug 2023 06:49:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=i2psIFi1lr/mOJiNUGIR7pQrudY/TqQ1Mk//JBNTkzvoBp0QGVD5HH3wBxB/8vkj/WXaltUQjqCeIczZDNs/pM/HI9VzsAl2/QJDMt6KkW5xmJ5XkfKFi3GHFcwbwoTCCtmH3wx6sxEqui+PXbbK4tTEVvWJNYiP4JZ70a9YgirrkNLkAuqK9rY//VxUPyYSNyfVQLMr61XMC74QaCfUd07lE53jPZ7TlwXUK31tirn5os8f6N05KC7IZxzm6O4rorK/pL3Wqod01VIveoaF4izMcRHlNA4g2OezrV5JfWZcwd02CcycfigXi9UVEFfyBO8pOqtJQval+sq+Bc9mew== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=f7QZs87E/DEeiexnbnDG3QjpEVs+MsDBxgAxWtql91U=; b=f/Lj24lj0305OjOa9rebcvkZHabQqVhMo2AGgOzyzcN3J9I2EDClXuUTRZCfds1NN1AAfeS4iXUP7M2SqJlPZmCSZhoM+pL5y2OIR5njP5H88oPnEkuZ31QYa1fQcVIiUzNSdh9qt7k92xTuf6G3icYpAwsXHki2/xrcFKy5mh52hiq/yVkL6L7U3hhayK2E77baNbiG+lvtJr2GqW6GoQmBA80+OBxs5VzpuLB9yETFqsbE71nMTN1nrp2HBtSlc5PPBn2xeaY3ATBH6/l4zPXFbFHHspHNfPE9Pg6OsLSRUc/Qy6jHkOenGQULaIDeUOF+nKvc6gcEbA9NCmQ1rQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=davemloft.net smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=f7QZs87E/DEeiexnbnDG3QjpEVs+MsDBxgAxWtql91U=; b=Z6+dlq3lRuhwzpiqp/fRrP2pLaYwAnLzpb42nF+r0st/3ddJZVv6cM53fy0IeHrsgWMxFkSXuBppffxM4ycs24o2oUexMhz7ac/DIljp8Td3Nt3bqPwcJnnWD9GM4nkeR0YJu88CGSbwe9TTstwCbDQVUy1hFy1HgESNQ52XWOY= Received: from SJ0PR05CA0124.namprd05.prod.outlook.com (2603:10b6:a03:33d::9) by CY5PR12MB6382.namprd12.prod.outlook.com (2603:10b6:930:3e::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6652.26; Mon, 7 Aug 2023 13:49:23 +0000 Received: from CO1PEPF000042A7.namprd03.prod.outlook.com (2603:10b6:a03:33d:cafe::a1) by SJ0PR05CA0124.outlook.office365.com (2603:10b6:a03:33d::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6678.16 via Frontend Transport; Mon, 7 Aug 2023 13:49:25 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by CO1PEPF000042A7.mail.protection.outlook.com (10.167.243.36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6652.19 via Frontend Transport; Mon, 7 Aug 2023 13:49:25 +0000 Received: from SATLEXMB05.amd.com (10.181.40.146) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Mon, 7 Aug 2023 08:49:23 -0500 Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB05.amd.com (10.181.40.146) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Mon, 7 Aug 2023 08:49:22 -0500 Received: from xcbecree41x.xilinx.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27 via Frontend Transport; Mon, 7 Aug 2023 08:49:21 -0500 From: To: , , , , CC: Edward Cree , , , Pieter Jansen van Vuuren , Simon Horman Subject: [PATCH v2 net-next 7/7] sfc: offload left-hand side rules for conntrack Date: Mon, 7 Aug 2023 14:48:11 +0100 Message-ID: <20312c0c5950aa97a48a5a6a30ac294bec92c8e6.1691415479.git.ecree.xilinx@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PEPF000042A7:EE_|CY5PR12MB6382:EE_ X-MS-Office365-Filtering-Correlation-Id: eee63b80-f79d-4826-2925-08db974d1d14 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: fAJE1dIWQDcC/sjPqgPcdu+EO+JOfO6o4GoXxMvv9DMjJpyUFMiG1oYpnrMqLOohP0TGwpiswfOln+ZZOJWK+gE3HtzWQsu51XZb+IY7ij3xM/6gV8E+lECvv81A4dG4560RVW7VoQHOwfDtLdxsPlmH5kPTnr1Ff9Tyx3puYpoEoLJVEzw5Y+GiQs28bJfe+Hk6MMMrgtkXvykW+oPQjPPklKYAMBz/SHYytdfwMgOAXEWUj3zpmw3kRoKt7B884WxhX4ke/eBNLSWwP8PYgz0NVPkvChX1Y/GELIoydBt5yqruDHT3Y7yQYICfviz/AjUZ/Rrdj8zbGDnQWcHvi6qAekVloMbOXz7rp8/RSbA1pQ7aH5aylAsWQlghZmMRDEA1VPY09MXlXSY3ufUHpoJ0DdYCZQJYFpTb4pWQIUk9pH91YznAKcV2yHkaFxIpDtMJ7nw6tITDS+drK8vzVYUzNAdLw8tYI4WFMCWKeRA44IAVt2nFdx5RrWg+IVlwkXgAj0Eno3nexvCudQKePasSnsjhjFhzqouVPRybB8Q/FThYGBLRFK5SiEIfSS8gBmebZM5qnoPmmD9SQ0gBTTjzLQQDtmGmiwwZo4y1NssV2/CtUIL3Idr6+n2BgAlrDxXdRc0lhAVan3JrmQChfXYeVjk6K4yVEmLdXBNujKXnh8K6ErLosGpP4B/AAzIqY5buA9b43aprVbfG6UHE185m/5+oYU1ip5Wvj7ws2A6Rbq4kbix3GEU/ejljsKMJmJFBecG5lnd0Xk7gImRCyLVpD8pU4Cc+om8qUWwnxAI= X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:SATLEXMB04.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230028)(4636009)(396003)(376002)(136003)(346002)(39860400002)(451199021)(186006)(1800799003)(82310400008)(40470700004)(46966006)(36840700001)(40480700001)(336012)(40460700003)(36756003)(9686003)(4326008)(316002)(86362001)(81166007)(55446002)(478600001)(54906003)(110136005)(356005)(70206006)(6666004)(70586007)(82740400003)(41300700001)(26005)(426003)(8676002)(8936002)(47076005)(36860700001)(2876002)(2906002)(30864003)(83380400001)(5660300002)(36900700001)(309714004);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Aug 2023 13:49:25.7631 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: eee63b80-f79d-4826-2925-08db974d1d14 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CO1PEPF000042A7.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY5PR12MB6382 X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_SPF_HELO, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Edward Cree Handle the (comparatively) simple case of a -trk rule on an efx netdev (i.e. not a tunnel decap rule) with ct and goto chain actions. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree --- Changed in v2: * added break to pacify a clang implicit-fallthrough warning (nipa, Simon) --- drivers/net/ethernet/sfc/bitfield.h | 2 + drivers/net/ethernet/sfc/mae.c | 287 ++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/mae.h | 6 + drivers/net/ethernet/sfc/mcdi.h | 6 + drivers/net/ethernet/sfc/tc.c | 282 +++++++++++++++++++++++++++ drivers/net/ethernet/sfc/tc.h | 16 ++ 6 files changed, 599 insertions(+) diff --git a/drivers/net/ethernet/sfc/bitfield.h b/drivers/net/ethernet/sfc/bitfield.h index 1f981dfe4bdc..89665fc9b8d0 100644 --- a/drivers/net/ethernet/sfc/bitfield.h +++ b/drivers/net/ethernet/sfc/bitfield.h @@ -26,6 +26,8 @@ /* Lowest bit numbers and widths */ #define EFX_DUMMY_FIELD_LBN 0 #define EFX_DUMMY_FIELD_WIDTH 0 +#define EFX_BYTE_0_LBN 0 +#define EFX_BYTE_0_WIDTH 8 #define EFX_WORD_0_LBN 0 #define EFX_WORD_0_WIDTH 16 #define EFX_WORD_1_LBN 16 diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index 1fa0958d5262..3b8780c76b6e 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -727,6 +727,90 @@ int efx_mae_match_check_caps(struct efx_nic *efx, } return 0; } + +/* Checks for match fields not supported in LHS Outer Rules */ +#define UNSUPPORTED(_field) ({ \ + enum mask_type typ = classify_mask((const u8 *)&mask->_field, \ + sizeof(mask->_field)); \ + \ + if (typ != MASK_ZEROES) { \ + NL_SET_ERR_MSG_MOD(extack, "Unsupported match field " #_field);\ + rc = -EOPNOTSUPP; \ + } \ + rc; \ +}) +#define UNSUPPORTED_BIT(_field) ({ \ + if (mask->_field) { \ + NL_SET_ERR_MSG_MOD(extack, "Unsupported match field " #_field);\ + rc = -EOPNOTSUPP; \ + } \ + rc; \ +}) + +/* LHS rules are (normally) inserted in the Outer Rule table, which means + * they use ENC_ fields in hardware to match regular (not enc_) fields from + * &struct efx_tc_match_fields. + */ +int efx_mae_match_check_caps_lhs(struct efx_nic *efx, + const struct efx_tc_match_fields *mask, + struct netlink_ext_ack *extack) +{ + const u8 *supported_fields = efx->tc->caps->outer_rule_fields; + __be32 ingress_port = cpu_to_be32(mask->ingress_port); + enum mask_type ingress_port_mask_type; + int rc; + + /* Check for _PREFIX assumes big-endian, so we need to convert */ + ingress_port_mask_type = classify_mask((const u8 *)&ingress_port, + sizeof(ingress_port)); + rc = efx_mae_match_check_cap_typ(supported_fields[MAE_FIELD_INGRESS_PORT], + ingress_port_mask_type); + if (rc) { + NL_SET_ERR_MSG_FMT_MOD(extack, "No support for %s mask in field %s\n", + mask_type_name(ingress_port_mask_type), + "ingress_port"); + return rc; + } + if (CHECK(ENC_ETHER_TYPE, eth_proto) || + CHECK(ENC_VLAN0_TCI, vlan_tci[0]) || + CHECK(ENC_VLAN0_PROTO, vlan_proto[0]) || + CHECK(ENC_VLAN1_TCI, vlan_tci[1]) || + CHECK(ENC_VLAN1_PROTO, vlan_proto[1]) || + CHECK(ENC_ETH_SADDR, eth_saddr) || + CHECK(ENC_ETH_DADDR, eth_daddr) || + CHECK(ENC_IP_PROTO, ip_proto) || + CHECK(ENC_IP_TOS, ip_tos) || + CHECK(ENC_IP_TTL, ip_ttl) || + CHECK_BIT(ENC_IP_FRAG, ip_frag) || + UNSUPPORTED_BIT(ip_firstfrag) || + CHECK(ENC_SRC_IP4, src_ip) || + CHECK(ENC_DST_IP4, dst_ip) || +#ifdef CONFIG_IPV6 + CHECK(ENC_SRC_IP6, src_ip6) || + CHECK(ENC_DST_IP6, dst_ip6) || +#endif + CHECK(ENC_L4_SPORT, l4_sport) || + CHECK(ENC_L4_DPORT, l4_dport) || + UNSUPPORTED(tcp_flags) || + CHECK_BIT(TCP_SYN_FIN_RST, tcp_syn_fin_rst)) + return rc; + if (efx_tc_match_is_encap(mask)) { + /* can't happen; disallowed for local rules, translated + * for foreign rules. + */ + NL_SET_ERR_MSG_MOD(extack, "Unexpected encap match in LHS rule"); + return -EOPNOTSUPP; + } + if (UNSUPPORTED(enc_keyid) || + /* Can't filter on conntrack in LHS rules */ + UNSUPPORTED_BIT(ct_state_trk) || + UNSUPPORTED_BIT(ct_state_est) || + UNSUPPORTED(ct_mark) || + UNSUPPORTED(recirc_id)) + return rc; + return 0; +} +#undef UNSUPPORTED #undef CHECK_BIT #undef CHECK @@ -1409,6 +1493,209 @@ int efx_mae_unregister_encap_match(struct efx_nic *efx, return 0; } +static int efx_mae_populate_lhs_match_criteria(MCDI_DECLARE_STRUCT_PTR(match_crit), + const struct efx_tc_match *match) +{ + if (match->mask.ingress_port) { + if (~match->mask.ingress_port) + return -EOPNOTSUPP; + MCDI_STRUCT_SET_DWORD(match_crit, + MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR, + match->value.ingress_port); + } + MCDI_STRUCT_SET_DWORD(match_crit, MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_MASK, + match->mask.ingress_port); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE, + match->value.eth_proto); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_MASK, + match->mask.eth_proto); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE, + match->value.vlan_tci[0]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_MASK, + match->mask.vlan_tci[0]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE, + match->value.vlan_proto[0]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_MASK, + match->mask.vlan_proto[0]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE, + match->value.vlan_tci[1]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_MASK, + match->mask.vlan_tci[1]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE, + match->value.vlan_proto[1]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_MASK, + match->mask.vlan_proto[1]); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE), + match->value.eth_saddr, ETH_ALEN); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_MASK), + match->mask.eth_saddr, ETH_ALEN); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE), + match->value.eth_daddr, ETH_ALEN); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_MASK), + match->mask.eth_daddr, ETH_ALEN); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO, + match->value.ip_proto); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK, + match->mask.ip_proto); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TOS, + match->value.ip_tos); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_MASK, + match->mask.ip_tos); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TTL, + match->value.ip_ttl); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK, + match->mask.ip_ttl); + MCDI_STRUCT_POPULATE_BYTE_1(match_crit, + MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS, + MAE_ENC_FIELD_PAIRS_ENC_IP_FRAG, + match->value.ip_frag); + MCDI_STRUCT_POPULATE_BYTE_1(match_crit, + MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK, + MAE_ENC_FIELD_PAIRS_ENC_IP_FRAG_MASK, + match->mask.ip_frag); + MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE, + match->value.src_ip); + MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_MASK, + match->mask.src_ip); + MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE, + match->value.dst_ip); + MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_MASK, + match->mask.dst_ip); +#ifdef CONFIG_IPV6 + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE), + &match->value.src_ip6, sizeof(struct in6_addr)); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_MASK), + &match->mask.src_ip6, sizeof(struct in6_addr)); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE), + &match->value.dst_ip6, sizeof(struct in6_addr)); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_MASK), + &match->mask.dst_ip6, sizeof(struct in6_addr)); +#endif + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE, + match->value.l4_sport); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_MASK, + match->mask.l4_sport); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE, + match->value.l4_dport); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK, + match->mask.l4_dport); + /* No enc-keys in LHS rules. Caps check should have caught this; any + * enc-keys from an fLHS should have been translated to regular keys + * and any EM should be a pseudo (we're an OR so can't have a direct + * EM with another OR). + */ + if (WARN_ON_ONCE(match->encap && !match->encap->type)) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(match->mask.enc_src_ip)) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(match->mask.enc_dst_ip)) + return -EOPNOTSUPP; +#ifdef CONFIG_IPV6 + if (WARN_ON_ONCE(!ipv6_addr_any(&match->mask.enc_src_ip6))) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(!ipv6_addr_any(&match->mask.enc_dst_ip6))) + return -EOPNOTSUPP; +#endif + if (WARN_ON_ONCE(match->mask.enc_ip_tos)) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(match->mask.enc_ip_ttl)) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(match->mask.enc_sport)) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(match->mask.enc_dport)) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(match->mask.enc_keyid)) + return -EOPNOTSUPP; + return 0; +} + +static int efx_mae_insert_lhs_outer_rule(struct efx_nic *efx, + struct efx_tc_lhs_rule *rule, u32 prio) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_OUTER_RULE_INSERT_IN_LEN(MAE_ENC_FIELD_PAIRS_LEN)); + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN); + MCDI_DECLARE_STRUCT_PTR(match_crit); + const struct efx_tc_lhs_action *act; + size_t outlen; + int rc; + + MCDI_SET_DWORD(inbuf, MAE_OUTER_RULE_INSERT_IN_PRIO, prio); + /* match */ + match_crit = _MCDI_DWORD(inbuf, MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA); + rc = efx_mae_populate_lhs_match_criteria(match_crit, &rule->match); + if (rc) + return rc; + + /* action */ + act = &rule->lhs_act; + MCDI_SET_DWORD(inbuf, MAE_OUTER_RULE_INSERT_IN_ENCAP_TYPE, + MAE_MCDI_ENCAP_TYPE_NONE); + /* We always inhibit CT lookup on TCP_INTERESTING_FLAGS, since the + * SW path needs to process the packet to update the conntrack tables + * on connection establishment (SYN) or termination (FIN, RST). + */ + MCDI_POPULATE_DWORD_6(inbuf, MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL, + MAE_OUTER_RULE_INSERT_IN_DO_CT, !!act->zone, + MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT, 1, + MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN, + act->zone ? act->zone->zone : 0, + MAE_OUTER_RULE_INSERT_IN_CT_VNI_MODE, + MAE_CT_VNI_MODE_ZERO, + MAE_OUTER_RULE_INSERT_IN_DO_COUNT, !!act->count, + MAE_OUTER_RULE_INSERT_IN_RECIRC_ID, + act->rid ? act->rid->fw_id : 0); + if (act->count) + MCDI_SET_DWORD(inbuf, MAE_OUTER_RULE_INSERT_IN_COUNTER_ID, + act->count->cnt->fw_id); + rc = efx_mcdi_rpc(efx, MC_CMD_MAE_OUTER_RULE_INSERT, inbuf, + sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + if (outlen < sizeof(outbuf)) + return -EIO; + rule->fw_id = MCDI_DWORD(outbuf, MAE_OUTER_RULE_INSERT_OUT_OR_ID); + return 0; +} + +int efx_mae_insert_lhs_rule(struct efx_nic *efx, struct efx_tc_lhs_rule *rule, + u32 prio) +{ + return efx_mae_insert_lhs_outer_rule(efx, rule, prio); +} + +static int efx_mae_remove_lhs_outer_rule(struct efx_nic *efx, + struct efx_tc_lhs_rule *rule) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1)); + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1)); + size_t outlen; + int rc; + + MCDI_SET_DWORD(inbuf, MAE_OUTER_RULE_REMOVE_IN_OR_ID, rule->fw_id); + rc = efx_mcdi_rpc(efx, MC_CMD_MAE_OUTER_RULE_REMOVE, inbuf, + sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + if (outlen < sizeof(outbuf)) + return -EIO; + /* FW freed a different ID than we asked for, should also never happen. + * Warn because it means we've now got a different idea to the FW of + * what encap_mds exist, which could cause mayhem later. + */ + if (WARN_ON(MCDI_DWORD(outbuf, MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID) != rule->fw_id)) + return -EIO; + /* We're probably about to free @rule, but let's just make sure its + * fw_id is blatted so that it won't look valid if it leaks out. + */ + rule->fw_id = MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OUTER_RULE_ID_NULL; + return 0; +} + +int efx_mae_remove_lhs_rule(struct efx_nic *efx, struct efx_tc_lhs_rule *rule) +{ + return efx_mae_remove_lhs_outer_rule(efx, rule); +} + /* Populating is done by taking each byte of @value in turn and storing * it in the appropriate bits of @row. @value must be big-endian; we * convert it to little-endianness as we go. diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h index 24f29a4fc0e1..e88e80574f15 100644 --- a/drivers/net/ethernet/sfc/mae.h +++ b/drivers/net/ethernet/sfc/mae.h @@ -84,6 +84,9 @@ int efx_mae_get_caps(struct efx_nic *efx, struct mae_caps *caps); int efx_mae_match_check_caps(struct efx_nic *efx, const struct efx_tc_match_fields *mask, struct netlink_ext_ack *extack); +int efx_mae_match_check_caps_lhs(struct efx_nic *efx, + const struct efx_tc_match_fields *mask, + struct netlink_ext_ack *extack); int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6, u8 ip_tos_mask, __be16 udp_sport_mask, struct netlink_ext_ack *extack); @@ -112,6 +115,9 @@ int efx_mae_register_encap_match(struct efx_nic *efx, struct efx_tc_encap_match *encap); int efx_mae_unregister_encap_match(struct efx_nic *efx, struct efx_tc_encap_match *encap); +int efx_mae_insert_lhs_rule(struct efx_nic *efx, struct efx_tc_lhs_rule *rule, + u32 prio); +int efx_mae_remove_lhs_rule(struct efx_nic *efx, struct efx_tc_lhs_rule *rule); struct efx_tc_ct_entry; /* see tc_conntrack.h */ int efx_mae_insert_ct(struct efx_nic *efx, struct efx_tc_ct_entry *conn); int efx_mae_remove_ct(struct efx_nic *efx, struct efx_tc_ct_entry *conn); diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 700d0252aebd..ea612c619874 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -218,6 +218,12 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); BUILD_BUG_ON(_field ## _LEN != 1); \ *(u8 *)MCDI_STRUCT_PTR(_buf, _field) = _value; \ } while (0) +#define MCDI_STRUCT_POPULATE_BYTE_1(_buf, _field, _name, _value) do { \ + efx_dword_t _temp; \ + EFX_POPULATE_DWORD_1(_temp, _name, _value); \ + MCDI_STRUCT_SET_BYTE(_buf, _field, \ + EFX_DWORD_FIELD(_temp, EFX_BYTE_0)); \ + } while (0) #define MCDI_BYTE(_buf, _field) \ ((void)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 1), \ *MCDI_PTR(_buf, _field)) diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index a9f4bfaacac3..246657222958 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "tc.h" #include "tc_bindings.h" #include "tc_encap_actions.h" @@ -97,6 +98,12 @@ static const struct rhashtable_params efx_tc_match_action_ht_params = { .head_offset = offsetof(struct efx_tc_flow_rule, linkage), }; +static const struct rhashtable_params efx_tc_lhs_rule_ht_params = { + .key_len = sizeof(unsigned long), + .key_offset = offsetof(struct efx_tc_lhs_rule, cookie), + .head_offset = offsetof(struct efx_tc_lhs_rule, linkage), +}; + static const struct rhashtable_params efx_tc_recirc_ht_params = { .key_len = offsetof(struct efx_tc_recirc_id, linkage), .key_offset = 0, @@ -736,6 +743,163 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act, } } +/** + * DOC: TC conntrack sequences + * + * The MAE hardware can handle at most two rounds of action rule matching, + * consequently we support conntrack through the notion of a "left-hand side + * rule". This is a rule which typically contains only the actions "ct" and + * "goto chain N", and corresponds to one or more "right-hand side rules" in + * chain N, which typically match on +trk+est, and may perform ct(nat) actions. + * RHS rules go in the Action Rule table as normal but with a nonzero recirc_id + * (the hardware equivalent of chain_index), while LHS rules may go in either + * the Action Rule or the Outer Rule table, the latter being preferred for + * performance reasons, and set both DO_CT and a recirc_id in their response. + * + * Besides the RHS rules, there are often also similar rules matching on + * +trk+new which perform the ct(commit) action. These are not offloaded. + */ + +static bool efx_tc_rule_is_lhs_rule(struct flow_rule *fr, + struct efx_tc_match *match) +{ + const struct flow_action_entry *fa; + int i; + + flow_action_for_each(i, fa, &fr->action) { + switch (fa->id) { + case FLOW_ACTION_GOTO: + return true; + case FLOW_ACTION_CT: + /* If rule is -trk, or doesn't mention trk at all, then + * a CT action implies a conntrack lookup (hence it's an + * LHS rule). If rule is +trk, then a CT action could + * just be ct(nat) or even ct(commit) (though the latter + * can't be offloaded). + */ + if (!match->mask.ct_state_trk || !match->value.ct_state_trk) + return true; + break; + default: + break; + } + } + return false; +} + +static int efx_tc_flower_handle_lhs_actions(struct efx_nic *efx, + struct flow_cls_offload *tc, + struct flow_rule *fr, + struct net_device *net_dev, + struct efx_tc_lhs_rule *rule) + +{ + struct netlink_ext_ack *extack = tc->common.extack; + struct efx_tc_lhs_action *act = &rule->lhs_act; + const struct flow_action_entry *fa; + bool pipe = true; + int i; + + flow_action_for_each(i, fa, &fr->action) { + struct efx_tc_ct_zone *ct_zone; + struct efx_tc_recirc_id *rid; + + if (!pipe) { + /* more actions after a non-pipe action */ + NL_SET_ERR_MSG_MOD(extack, "Action follows non-pipe action"); + return -EINVAL; + } + switch (fa->id) { + case FLOW_ACTION_GOTO: + if (!fa->chain_index) { + NL_SET_ERR_MSG_MOD(extack, "Can't goto chain 0, no looping in hw"); + return -EOPNOTSUPP; + } + rid = efx_tc_get_recirc_id(efx, fa->chain_index, + net_dev); + if (IS_ERR(rid)) { + NL_SET_ERR_MSG_MOD(extack, "Failed to allocate a hardware recirculation ID for this chain_index"); + return PTR_ERR(rid); + } + act->rid = rid; + if (fa->hw_stats) { + struct efx_tc_counter_index *cnt; + + if (!(fa->hw_stats & FLOW_ACTION_HW_STATS_DELAYED)) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "hw_stats_type %u not supported (only 'delayed')", + fa->hw_stats); + return -EOPNOTSUPP; + } + cnt = efx_tc_flower_get_counter_index(efx, tc->cookie, + EFX_TC_COUNTER_TYPE_OR); + if (IS_ERR(cnt)) { + NL_SET_ERR_MSG_MOD(extack, "Failed to obtain a counter"); + return PTR_ERR(cnt); + } + WARN_ON(act->count); /* can't happen */ + act->count = cnt; + } + pipe = false; + break; + case FLOW_ACTION_CT: + if (act->zone) { + NL_SET_ERR_MSG_MOD(extack, "Can't offload multiple ct actions"); + return -EOPNOTSUPP; + } + if (fa->ct.action & (TCA_CT_ACT_COMMIT | + TCA_CT_ACT_FORCE)) { + NL_SET_ERR_MSG_MOD(extack, "Can't offload ct commit/force"); + return -EOPNOTSUPP; + } + if (fa->ct.action & TCA_CT_ACT_CLEAR) { + NL_SET_ERR_MSG_MOD(extack, "Can't clear ct in LHS rule"); + return -EOPNOTSUPP; + } + if (fa->ct.action & (TCA_CT_ACT_NAT | + TCA_CT_ACT_NAT_SRC | + TCA_CT_ACT_NAT_DST)) { + NL_SET_ERR_MSG_MOD(extack, "Can't perform NAT in LHS rule - packet isn't conntracked yet"); + return -EOPNOTSUPP; + } + if (fa->ct.action) { + NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled ct.action %u for LHS rule\n", + fa->ct.action); + return -EOPNOTSUPP; + } + ct_zone = efx_tc_ct_register_zone(efx, fa->ct.zone, + fa->ct.flow_table); + if (IS_ERR(ct_zone)) { + NL_SET_ERR_MSG_MOD(extack, "Failed to register for CT updates"); + return PTR_ERR(ct_zone); + } + act->zone = ct_zone; + break; + default: + NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled action %u for LHS rule\n", + fa->id); + return -EOPNOTSUPP; + } + } + + if (pipe) { + NL_SET_ERR_MSG_MOD(extack, "Missing goto chain in LHS rule"); + return -EOPNOTSUPP; + } + return 0; +} + +static void efx_tc_flower_release_lhs_actions(struct efx_nic *efx, + struct efx_tc_lhs_action *act) +{ + if (act->rid) + efx_tc_put_recirc_id(efx, act->rid); + if (act->zone) + efx_tc_ct_unregister_zone(efx, act->zone); + if (act->count) + efx_tc_flower_put_counter_index(efx, act->count); +} + static int efx_tc_flower_replace_foreign(struct efx_nic *efx, struct net_device *net_dev, struct flow_cls_offload *tc) @@ -1050,6 +1214,78 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, return rc; } +static int efx_tc_flower_replace_lhs(struct efx_nic *efx, + struct flow_cls_offload *tc, + struct flow_rule *fr, + struct efx_tc_match *match, + struct efx_rep *efv, + struct net_device *net_dev) +{ + struct netlink_ext_ack *extack = tc->common.extack; + struct efx_tc_lhs_rule *rule, *old; + int rc; + + if (tc->common.chain_index) { + NL_SET_ERR_MSG_MOD(extack, "LHS rule only allowed in chain 0"); + return -EOPNOTSUPP; + } + + if (match->mask.ct_state_trk && match->value.ct_state_trk) { + NL_SET_ERR_MSG_MOD(extack, "LHS rule can never match +trk"); + return -EOPNOTSUPP; + } + /* LHS rules are always -trk, so we don't need to match on that */ + match->mask.ct_state_trk = 0; + match->value.ct_state_trk = 0; + + rc = efx_mae_match_check_caps_lhs(efx, &match->mask, extack); + if (rc) + return rc; + + rule = kzalloc(sizeof(*rule), GFP_USER); + if (!rule) + return -ENOMEM; + rule->cookie = tc->cookie; + old = rhashtable_lookup_get_insert_fast(&efx->tc->lhs_rule_ht, + &rule->linkage, + efx_tc_lhs_rule_ht_params); + if (old) { + netif_dbg(efx, drv, efx->net_dev, + "Already offloaded rule (cookie %lx)\n", tc->cookie); + rc = -EEXIST; + NL_SET_ERR_MSG_MOD(extack, "Rule already offloaded"); + goto release; + } + + /* Parse actions */ + /* See note in efx_tc_flower_replace() regarding passed net_dev + * (used for efx_tc_get_recirc_id()). + */ + rc = efx_tc_flower_handle_lhs_actions(efx, tc, fr, efx->net_dev, rule); + if (rc) + goto release; + + rule->match = *match; + + rc = efx_mae_insert_lhs_rule(efx, rule, EFX_TC_PRIO_TC); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "Failed to insert rule in hw"); + goto release; + } + netif_dbg(efx, drv, efx->net_dev, + "Successfully parsed lhs rule (cookie %lx)\n", + tc->cookie); + return 0; + +release: + efx_tc_flower_release_lhs_actions(efx, &rule->lhs_act); + if (!old) + rhashtable_remove_fast(&efx->tc->lhs_rule_ht, &rule->linkage, + efx_tc_lhs_rule_ht_params); + kfree(rule); + return rc; +} + static int efx_tc_flower_replace(struct efx_nic *efx, struct net_device *net_dev, struct flow_cls_offload *tc, @@ -1105,6 +1341,10 @@ static int efx_tc_flower_replace(struct efx_nic *efx, return -EOPNOTSUPP; } + if (efx_tc_rule_is_lhs_rule(fr, &match)) + return efx_tc_flower_replace_lhs(efx, tc, fr, &match, efv, + net_dev); + /* chain_index 0 is always recirc_id 0 (and does not appear in recirc_ht). * Conveniently, match.rid == NULL and match.value.recirc_id == 0 owing * to the initial memset(), so we don't need to do anything in that case. @@ -1512,8 +1752,26 @@ static int efx_tc_flower_destroy(struct efx_nic *efx, struct flow_cls_offload *tc) { struct netlink_ext_ack *extack = tc->common.extack; + struct efx_tc_lhs_rule *lhs_rule; struct efx_tc_flow_rule *rule; + lhs_rule = rhashtable_lookup_fast(&efx->tc->lhs_rule_ht, &tc->cookie, + efx_tc_lhs_rule_ht_params); + if (lhs_rule) { + /* Remove it from HW */ + efx_mae_remove_lhs_rule(efx, lhs_rule); + /* Delete it from SW */ + efx_tc_flower_release_lhs_actions(efx, &lhs_rule->lhs_act); + rhashtable_remove_fast(&efx->tc->lhs_rule_ht, &lhs_rule->linkage, + efx_tc_lhs_rule_ht_params); + if (lhs_rule->match.encap) + efx_tc_flower_release_encap_match(efx, lhs_rule->match.encap); + netif_dbg(efx, drv, efx->net_dev, "Removed (lhs) filter %lx\n", + lhs_rule->cookie); + kfree(lhs_rule); + return 0; + } + rule = rhashtable_lookup_fast(&efx->tc->match_action_ht, &tc->cookie, efx_tc_match_action_ht_params); if (!rule) { @@ -1880,6 +2138,24 @@ static void efx_tc_recirc_free(void *ptr, void *arg) kfree(rid); } +static void efx_tc_lhs_free(void *ptr, void *arg) +{ + struct efx_tc_lhs_rule *rule = ptr; + struct efx_nic *efx = arg; + + netif_err(efx, drv, efx->net_dev, + "tc lhs_rule %lx still present at teardown, removing\n", + rule->cookie); + + if (rule->lhs_act.zone) + efx_tc_ct_unregister_zone(efx, rule->lhs_act.zone); + if (rule->lhs_act.count) + efx_tc_flower_put_counter_index(efx, rule->lhs_act.count); + efx_mae_remove_lhs_rule(efx, rule); + + kfree(rule); +} + static void efx_tc_flow_free(void *ptr, void *arg) { struct efx_tc_flow_rule *rule = ptr; @@ -1926,6 +2202,9 @@ int efx_init_struct_tc(struct efx_nic *efx) rc = rhashtable_init(&efx->tc->match_action_ht, &efx_tc_match_action_ht_params); if (rc < 0) goto fail_match_action_ht; + rc = rhashtable_init(&efx->tc->lhs_rule_ht, &efx_tc_lhs_rule_ht_params); + if (rc < 0) + goto fail_lhs_rule_ht; rc = efx_tc_init_conntrack(efx); if (rc < 0) goto fail_conntrack; @@ -1948,6 +2227,8 @@ int efx_init_struct_tc(struct efx_nic *efx) fail_recirc_ht: efx_tc_destroy_conntrack(efx); fail_conntrack: + rhashtable_destroy(&efx->tc->lhs_rule_ht); +fail_lhs_rule_ht: rhashtable_destroy(&efx->tc->match_action_ht); fail_match_action_ht: rhashtable_destroy(&efx->tc->encap_match_ht); @@ -1978,6 +2259,7 @@ void efx_fini_struct_tc(struct efx_nic *efx) MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL); EFX_WARN_ON_PARANOID(efx->tc->facts.reps.fw_id != MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL); + rhashtable_free_and_destroy(&efx->tc->lhs_rule_ht, efx_tc_lhs_free, efx); rhashtable_free_and_destroy(&efx->tc->match_action_ht, efx_tc_flow_free, efx); rhashtable_free_and_destroy(&efx->tc->encap_match_ht, diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index ce8e30743a3a..40d2c803fca8 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -140,6 +140,12 @@ struct efx_tc_action_set_list { u32 fw_id; }; +struct efx_tc_lhs_action { + struct efx_tc_recirc_id *rid; + struct efx_tc_ct_zone *zone; + struct efx_tc_counter_index *count; +}; + struct efx_tc_flow_rule { unsigned long cookie; struct rhash_head linkage; @@ -149,6 +155,14 @@ struct efx_tc_flow_rule { u32 fw_id; }; +struct efx_tc_lhs_rule { + unsigned long cookie; + struct efx_tc_match match; + struct efx_tc_lhs_action lhs_act; + struct rhash_head linkage; + u32 fw_id; +}; + enum efx_tc_rule_prios { EFX_TC_PRIO_TC, /* Rule inserted by TC */ EFX_TC_PRIO_DFLT, /* Default switch rule; one of efx_tc_default_rules */ @@ -208,6 +222,7 @@ struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ * @encap_ht: Hashtable of TC encap actions * @encap_match_ht: Hashtable of TC encap matches * @match_action_ht: Hashtable of TC match-action rules + * @lhs_rule_ht: Hashtable of TC left-hand (act ct & goto chain) rules * @ct_zone_ht: Hashtable of TC conntrack flowtable bindings * @ct_ht: Hashtable of TC conntrack flow entries * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) @@ -244,6 +259,7 @@ struct efx_tc_state { struct rhashtable encap_ht; struct rhashtable encap_match_ht; struct rhashtable match_action_ht; + struct rhashtable lhs_rule_ht; struct rhashtable ct_zone_ht; struct rhashtable ct_ht; struct rhashtable neigh_ht;