From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id A5B7C440F2; Tue, 28 May 2024 10:11:32 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 8ED0B40DDB; Tue, 28 May 2024 10:10:48 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) by mails.dpdk.org (Postfix) with ESMTP id 7AEEB40A84 for ; Tue, 28 May 2024 10:10:45 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1716883845; x=1748419845; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=pxy0CCIYYy3KcjpKZYc0B9S++xOrO4w4IRmcAc5gYys=; b=Q+rDgc5G0BTqkiH/zjYZq+8rwIURpvSNz8sEktKuK20wPeUgZWA2nI7W C3a55W/mV8zmuYpxzp1JGGWywvtobPyP9WLAWGE65z3sdSY8EUcji6bmU l2fepLloG6m3i0Et4mE9tLy1yRajU6pMJPn1Hlh/o+FQ8bHEeS+9Zr/GR LRhaGhpCva5iMTZMPjltszJplnLuaU6xziEAJohvkKqjN9Snn9PFAs0zR 3nmpJnTLfCOiSXn69o8gm/dz9h8mTUhY/XdK1bXoFM3O0/2OP+P3zkHDA E6HCcmLMimPsOnHzIz2DW75set78YO1+bOaDWKAClxSKN0X619pteRkp6 A==; X-CSE-ConnectionGUID: tbH7g7mFTvSmAyagNswEiQ== X-CSE-MsgGUID: L/MqS+tYQq6qkA2zM5It8A== X-IronPort-AV: E=McAfee;i="6600,9927,11085"; a="16161935" X-IronPort-AV: E=Sophos;i="6.08,194,1712646000"; d="scan'208";a="16161935" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 May 2024 01:10:45 -0700 X-CSE-ConnectionGUID: CIMmeoziTAmCZJ9yHtCpvA== X-CSE-MsgGUID: T4O2YKmvRLOTOGhT1AbwSQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,194,1712646000"; d="scan'208";a="66197710" Received: from unknown (HELO npf-hyd-clx-03..) ([10.145.170.182]) by fmviesa001.fm.intel.com with ESMTP; 28 May 2024 01:10:43 -0700 From: Soumyadeep Hore To: yuying.zhang@intel.com, jingjing.wu@intel.com Cc: dev@dpdk.org Subject: [PATCH 09/25] common/idpf: add flex array support to virtchnl2 structures Date: Tue, 28 May 2024 07:28:39 +0000 Message-ID: <20240528072839.867100-10-soumyadeep.hore@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240528072839.867100-1-soumyadeep.hore@intel.com> References: <20240528072839.867100-1-soumyadeep.hore@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org The current virtchnl header uses 1-sized array to address the dynamic size of the virtchnl structure. For example in the following structure, the size of the struct depends on the 'num_chunks' and we use 'chunks[1]' to dereference each chunk information. struct virtchnl2_queue_reg_chunks { __le16 num_chunks; u8 pad[6]; struct virtchnl2_queue_reg_chunk chunks[1]; }; With the internal Linux upstream feedback that is received on IDPF driver and also some references available online, it is discouraged to use 1-sized array fields in the structures, especially in the new Linux drivers that are going to be upstreamed. Instead, it is recommended to use flex array fields for the dynamic sized structures. The problem with this approach is that, C++ doesn't have support for flex array fields and it might be a problem for Windows driver. This patch introduces flex array support for the dynamic sized structures wrapped with 'FLEX_ARRAY_SUPPORT' flag and should be defined only if the flex array fields are supported. Also there is a special case in virtchnl2_get_ptype_info and where the struct has nested flex arrays which is not supported. To support the flex arrays and not break the message format, the top level flex array field is removed and the sender/receiver is expected to parse the message accordingly. The above reasoning applies for virtchnl2_add_queue_groups as well but the struct is modified a bit by removing virtchnl2_queue_groups structure to better support the flex array. virtchnl2_vc_validate_vf_msg function is refactored to consider the cases where CP/driver supports or doesn't support the flex array. Signed-off-by: Soumyadeep Hore --- drivers/common/idpf/base/virtchnl2.h | 600 ++++++++++++++++----------- 1 file changed, 352 insertions(+), 248 deletions(-) diff --git a/drivers/common/idpf/base/virtchnl2.h b/drivers/common/idpf/base/virtchnl2.h index 45e77bbb94..355e2e3038 100644 --- a/drivers/common/idpf/base/virtchnl2.h +++ b/drivers/common/idpf/base/virtchnl2.h @@ -63,9 +63,19 @@ enum virtchnl2_status { * This macro is used to generate compilation errors if a structure * is not exactly the correct length. */ -#define VIRTCHNL2_CHECK_STRUCT_LEN(n, X) \ - static_assert((n) == sizeof(struct X), \ +#define VIRTCHNL2_CHECK_STRUCT_LEN(n, X) \ + static_assert((n) == sizeof(struct X), \ "Structure length does not match with the expected value") +#ifdef FLEX_ARRAY_SUPPORT +#define VIRTCHNL2_CHECK_STRUCT_VAR_LEN(n, X, T) \ + static_assert((n) == struct_size_t(struct X, T, 1),\ + "Structure length with flex array does not match with the expected value") +#else +#define VIRTCHNL2_CHECK_STRUCT_VAR_LEN(n, X, T) \ + VIRTCHNL2_CHECK_STRUCT_LEN(n, X) + +#define STRUCT_VAR_LEN 1 +#endif /* FLEX_ARRAY_SUPPORT */ /** * New major set of opcodes introduced and so leaving room for @@ -270,6 +280,43 @@ enum virtchnl2_cap_other { VIRTCHNL2_CAP_OEM = BIT_ULL(63), }; +/** + * enum virtchnl2_action_types - Available actions for sideband flow steering + * @VIRTCHNL2_ACTION_DROP: Drop the packet + * @VIRTCHNL2_ACTION_PASSTHRU: Forward the packet to the next classifier/stage + * @VIRTCHNL2_ACTION_QUEUE: Forward the packet to a receive queue + * @VIRTCHNL2_ACTION_Q_GROUP: Forward the packet to a receive queue group + * @VIRTCHNL2_ACTION_MARK: Mark the packet with specific marker value + * @VIRTCHNL2_ACTION_COUNT: Increment the corresponding counter + */ + +enum virtchnl2_action_types { + VIRTCHNL2_ACTION_DROP = BIT(0), + VIRTCHNL2_ACTION_PASSTHRU = BIT(1), + VIRTCHNL2_ACTION_QUEUE = BIT(2), + VIRTCHNL2_ACTION_Q_GROUP = BIT(3), + VIRTCHNL2_ACTION_MARK = BIT(4), + VIRTCHNL2_ACTION_COUNT = BIT(5), +}; + +/* Flow type capabilities for Flow Steering and Receive-Side Scaling */ +enum virtchnl2_flow_types { + VIRTCHNL2_FLOW_IPV4_TCP = BIT(0), + VIRTCHNL2_FLOW_IPV4_UDP = BIT(1), + VIRTCHNL2_FLOW_IPV4_SCTP = BIT(2), + VIRTCHNL2_FLOW_IPV4_OTHER = BIT(3), + VIRTCHNL2_FLOW_IPV6_TCP = BIT(4), + VIRTCHNL2_FLOW_IPV6_UDP = BIT(5), + VIRTCHNL2_FLOW_IPV6_SCTP = BIT(6), + VIRTCHNL2_FLOW_IPV6_OTHER = BIT(7), + VIRTCHNL2_FLOW_IPV4_AH = BIT(8), + VIRTCHNL2_FLOW_IPV4_ESP = BIT(9), + VIRTCHNL2_FLOW_IPV4_AH_ESP = BIT(10), + VIRTCHNL2_FLOW_IPV6_AH = BIT(11), + VIRTCHNL2_FLOW_IPV6_ESP = BIT(12), + VIRTCHNL2_FLOW_IPV6_AH_ESP = BIT(13), +}; + /** * enum virtchnl2_txq_sched_mode - Transmit Queue Scheduling Modes * @VIRTCHNL2_TXQ_SCHED_MODE_QUEUE: Queue mode is the legacy mode i.e. inorder @@ -711,21 +758,26 @@ VIRTCHNL2_CHECK_STRUCT_LEN(32, virtchnl2_queue_reg_chunk); struct virtchnl2_queue_reg_chunks { __le16 num_chunks; u8 pad[6]; - struct virtchnl2_queue_reg_chunk chunks[1]; + struct virtchnl2_queue_reg_chunk chunks[STRUCT_VAR_LEN]; }; -VIRTCHNL2_CHECK_STRUCT_LEN(40, virtchnl2_queue_reg_chunks); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(40, virtchnl2_queue_reg_chunks, chunks); /** * enum virtchnl2_vport_flags - Vport flags * @VIRTCHNL2_VPORT_UPLINK_PORT: Uplink port flag - * @VIRTCHNL2_VPORT_INLINE_FLOW_STEER_ENA: Inline flow steering enable flag + * @VIRTCHNL2_VPORT_INLINE_FLOW_STEER: Inline flow steering enabled + * @VIRTCHNL2_VPORT_INLINE_FLOW_STEER_RXQ: Inline flow steering enabled + * with explicit Rx queue action + * @VIRTCHNL2_VPORT_SIDEBAND_FLOW_STEER: Sideband flow steering enabled #ifdef NOT_FOR_UPSTREAM * @VIRTCHNL2_VPORT_PORT2PORT_PORT: Port2port port flag #endif */ enum virtchnl2_vport_flags { VIRTCHNL2_VPORT_UPLINK_PORT = BIT(0), - VIRTCHNL2_VPORT_INLINE_FLOW_STEER_ENA = BIT(1), + VIRTCHNL2_VPORT_INLINE_FLOW_STEER = BIT(1), + VIRTCHNL2_VPORT_INLINE_FLOW_STEER_RXQ = BIT(2), + VIRTCHNL2_VPORT_SIDEBAND_FLOW_STEER = BIT(3), #ifdef NOT_FOR_UPSTREAM VIRTCHNL2_VPORT_PORT2PORT_PORT = BIT(15), #endif /* NOT_FOR_UPSTREAM */ @@ -757,6 +809,14 @@ enum virtchnl2_vport_flags { * @rx_desc_ids: See enum virtchnl2_rx_desc_id_bitmasks * @tx_desc_ids: See enum virtchnl2_tx_desc_ids * @reserved: Reserved bytes and cannot be used + * @inline_flow_types: Bit mask of supported inline-flow-steering + * flow types (See enum virtchnl2_flow_types) + * @sideband_flow_types: Bit mask of supported sideband-flow-steering + * flow types (See enum virtchnl2_flow_types) + * @sideband_flow_actions: Bit mask of supported action types + * for sideband flow steering (See enum virtchnl2_action_types) + * @flow_steer_max_rules: Max rules allowed for inline and sideband + * flow steering combined * @rss_algorithm: RSS algorithm * @rss_key_size: RSS key size * @rss_lut_size: RSS LUT size @@ -790,7 +850,11 @@ struct virtchnl2_create_vport { __le16 vport_flags; __le64 rx_desc_ids; __le64 tx_desc_ids; - u8 reserved[72]; + u8 reserved[48]; + __le64 inline_flow_types; + __le64 sideband_flow_types; + __le32 sideband_flow_actions; + __le32 flow_steer_max_rules; __le32 rss_algorithm; __le16 rss_key_size; __le16 rss_lut_size; @@ -798,7 +862,7 @@ struct virtchnl2_create_vport { u8 pad[20]; struct virtchnl2_queue_reg_chunks chunks; }; -VIRTCHNL2_CHECK_STRUCT_LEN(192, virtchnl2_create_vport); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(192, virtchnl2_create_vport, chunks.chunks); /** * struct virtchnl2_vport - Vport identifier information @@ -880,9 +944,9 @@ struct virtchnl2_config_tx_queues { __le32 vport_id; __le16 num_qinfo; u8 pad[10]; - struct virtchnl2_txq_info qinfo[1]; + struct virtchnl2_txq_info qinfo[STRUCT_VAR_LEN]; }; -VIRTCHNL2_CHECK_STRUCT_LEN(72, virtchnl2_config_tx_queues); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(72, virtchnl2_config_tx_queues, qinfo); /** * struct virtchnl2_rxq_info - Receive queue config info @@ -959,9 +1023,9 @@ struct virtchnl2_config_rx_queues { __le32 vport_id; __le16 num_qinfo; u8 pad[18]; - struct virtchnl2_rxq_info qinfo[1]; + struct virtchnl2_rxq_info qinfo[STRUCT_VAR_LEN]; }; -VIRTCHNL2_CHECK_STRUCT_LEN(112, virtchnl2_config_rx_queues); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(112, virtchnl2_config_rx_queues, qinfo); /** * struct virtchnl2_add_queues - Data for VIRTCHNL2_OP_ADD_QUEUES @@ -990,15 +1054,15 @@ struct virtchnl2_add_queues { u8 pad[4]; struct virtchnl2_queue_reg_chunks chunks; }; -VIRTCHNL2_CHECK_STRUCT_LEN(56, virtchnl2_add_queues); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(56, virtchnl2_add_queues, chunks.chunks); /* Queue Groups Extension */ /** * struct virtchnl2_rx_queue_group_info - RX queue group info - * @rss_lut_size: IN/OUT, user can ask to update rss_lut size originally - * allocated by CreateVport command. New size will be returned - * if allocation succeeded, otherwise original rss_size from - * CreateVport will be returned. + * @rss_lut_size: User can ask to update rss_lut size originally allocated by + * CreateVport command. New size will be returned if allocation + * succeeded, otherwise original rss_size from CreateVport + * will be returned. * @pad: Padding for future extensions */ struct virtchnl2_rx_queue_group_info { @@ -1025,7 +1089,7 @@ VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_rx_queue_group_info); * @cir_pad: Future extension purpose for CIR only * @pad2: Padding for future extensions */ -struct virtchnl2_tx_queue_group_info { /* IN */ +struct virtchnl2_tx_queue_group_info { u8 tx_tc; u8 priority; u8 is_sp; @@ -1056,19 +1120,17 @@ VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_queue_group_id); /** * struct virtchnl2_queue_group_info - Queue group info * @qg_id: Queue group ID - * @num_tx_q: Number of TX queues - * @num_tx_complq: Number of completion queues - * @num_rx_q: Number of RX queues - * @num_rx_bufq: Number of RX buffer queues + * @num_tx_q: Number of TX queues requested + * @num_tx_complq: Number of completion queues requested + * @num_rx_q: Number of RX queues requested + * @num_rx_bufq: Number of RX buffer queues requested * @tx_q_grp_info: TX queue group info * @rx_q_grp_info: RX queue group info * @pad: Padding for future extensions - * @chunks: Queue register chunks + * @chunks: Queue register chunks from CP */ struct virtchnl2_queue_group_info { - /* IN */ struct virtchnl2_queue_group_id qg_id; - /* IN, Number of queue of different types in the group. */ __le16 num_tx_q; __le16 num_tx_complq; __le16 num_rx_q; @@ -1077,53 +1139,56 @@ struct virtchnl2_queue_group_info { struct virtchnl2_tx_queue_group_info tx_q_grp_info; struct virtchnl2_rx_queue_group_info rx_q_grp_info; u8 pad[40]; - struct virtchnl2_queue_reg_chunks chunks; /* OUT */ -}; -VIRTCHNL2_CHECK_STRUCT_LEN(120, virtchnl2_queue_group_info); - -/** - * struct virtchnl2_queue_groups - Queue groups list - * @num_queue_groups: Total number of queue groups - * @pad: Padding for future extensions - * @groups: Array of queue group info - */ -struct virtchnl2_queue_groups { - __le16 num_queue_groups; - u8 pad[6]; - struct virtchnl2_queue_group_info groups[1]; + struct virtchnl2_queue_reg_chunks chunks; }; -VIRTCHNL2_CHECK_STRUCT_LEN(128, virtchnl2_queue_groups); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(120, virtchnl2_queue_group_info, chunks.chunks); /** * struct virtchnl2_add_queue_groups - Add queue groups - * @vport_id: IN, vport_id to add queue group to, same as allocated by + * @vport_id: Vport_id to add queue group to, same as allocated by * CreateVport. NA for mailbox and other types not assigned to vport. + * @num_queue_groups: Total number of queue groups * @pad: Padding for future extensions - * @qg_info: IN/OUT. List of all the queue groups +#ifndef FLEX_ARRAY_SUPPORT + * @groups: List of all the queue group info structures +#endif * * PF sends this message to request additional transmit/receive queue groups * beyond the ones that were assigned via CREATE_VPORT request. * virtchnl2_add_queue_groups structure is used to specify the number of each * type of queues. CP responds with the same structure with the actual number of - * groups and queues assigned followed by num_queue_groups and num_chunks of - * virtchnl2_queue_groups and virtchnl2_queue_chunk structures. + * groups and queues assigned followed by num_queue_groups and groups of + * virtchnl2_queue_group_info and virtchnl2_queue_chunk structures. +#ifdef FLEX_ARRAY_SUPPORT + * (Note: There is no specific field for the queue group info but are added at + * the end of the add queue groups message. Receiver of this message is expected + * to extract the queue group info accordingly. Reason for doing this is because + * compiler doesn't allow nested flexible array fields). +#endif * * Associated with VIRTCHNL2_OP_ADD_QUEUE_GROUPS. */ struct virtchnl2_add_queue_groups { __le32 vport_id; - u8 pad[4]; - struct virtchnl2_queue_groups qg_info; + __le16 num_queue_groups; + u8 pad[10]; +#ifndef FLEX_ARRAY_SUPPORT + struct virtchnl2_queue_group_info groups[STRUCT_VAR_LEN]; +#endif /* !FLEX_ARRAY_SUPPORT */ }; +#ifndef FLEX_ARRAY_SUPPORT VIRTCHNL2_CHECK_STRUCT_LEN(136, virtchnl2_add_queue_groups); +#else +VIRTCHNL2_CHECK_STRUCT_LEN(16, virtchnl2_add_queue_groups); +#endif /* !FLEX_ARRAY_SUPPORT */ /** * struct virtchnl2_delete_queue_groups - Delete queue groups - * @vport_id: IN, vport_id to delete queue group from, same as allocated by + * @vport_id: Vport ID to delete queue group from, same as allocated by * CreateVport. - * @num_queue_groups: IN/OUT, Defines number of groups provided + * @num_queue_groups: Defines number of groups provided * @pad: Padding - * @qg_ids: IN, IDs & types of Queue Groups to delete + * @qg_ids: IDs & types of Queue Groups to delete * * PF sends this message to delete queue groups. * PF sends virtchnl2_delete_queue_groups struct to specify the queue groups @@ -1137,9 +1202,9 @@ struct virtchnl2_delete_queue_groups { __le16 num_queue_groups; u8 pad[2]; - struct virtchnl2_queue_group_id qg_ids[1]; + struct virtchnl2_queue_group_id qg_ids[STRUCT_VAR_LEN]; }; -VIRTCHNL2_CHECK_STRUCT_LEN(16, virtchnl2_delete_queue_groups); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(16, virtchnl2_delete_queue_groups, qg_ids); /** * struct virtchnl2_vector_chunk - Structure to specify a chunk of contiguous @@ -1197,9 +1262,9 @@ struct virtchnl2_vector_chunks { __le16 num_vchunks; u8 pad[14]; - struct virtchnl2_vector_chunk vchunks[1]; + struct virtchnl2_vector_chunk vchunks[STRUCT_VAR_LEN]; }; -VIRTCHNL2_CHECK_STRUCT_LEN(48, virtchnl2_vector_chunks); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(48, virtchnl2_vector_chunks, vchunks); /** * struct virtchnl2_alloc_vectors - Vector allocation info @@ -1221,7 +1286,7 @@ struct virtchnl2_alloc_vectors { struct virtchnl2_vector_chunks vchunks; }; -VIRTCHNL2_CHECK_STRUCT_LEN(64, virtchnl2_alloc_vectors); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(64, virtchnl2_alloc_vectors, vchunks.vchunks); /** * struct virtchnl2_rss_lut - RSS LUT info @@ -1243,9 +1308,9 @@ struct virtchnl2_rss_lut { __le16 lut_entries_start; __le16 lut_entries; u8 pad[4]; - __le32 lut[1]; + __le32 lut[STRUCT_VAR_LEN]; }; -VIRTCHNL2_CHECK_STRUCT_LEN(16, virtchnl2_rss_lut); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(16, virtchnl2_rss_lut, lut); /** * struct virtchnl2_rss_hash - RSS hash info @@ -1388,9 +1453,9 @@ struct virtchnl2_ptype { u8 ptype_id_8; u8 proto_id_count; __le16 pad; - __le16 proto_id[1]; + __le16 proto_id[STRUCT_VAR_LEN]; }; -VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_ptype); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(8, virtchnl2_ptype, proto_id); /** * struct virtchnl2_get_ptype_info - Packet type info @@ -1404,11 +1469,13 @@ VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_ptype); * descriptor, it is 256 (8-bit ptype). Send this message to the CP by * populating the 'start_ptype_id' and the 'num_ptypes'. CP responds with the * 'start_ptype_id', 'num_ptypes', and the array of ptype (virtchnl2_ptype) that - * are added at the end of the 'virtchnl2_get_ptype_info' message (Note: There - * is no specific field for the ptypes but are added at the end of the - * ptype info message. PF/VF is expected to extract the ptypes accordingly. + * are added at the end of the 'virtchnl2_get_ptype_info' message. +#ifdef FLEX_ARRAY_SUPPORT + * (Note: There is no specific field for the ptypes but are added at the end of + * the ptype info message. PF/VF is expected to extract the ptypes accordingly. * Reason for doing this is because compiler doesn't allow nested flexible * array fields). +#endif * * If all the ptypes don't fit into one mailbox buffer, CP splits the * ptype info into multiple messages, where each message will have its own @@ -1426,10 +1493,15 @@ struct virtchnl2_get_ptype_info { __le16 start_ptype_id; __le16 num_ptypes; __le32 pad; - - struct virtchnl2_ptype ptype[1]; +#ifndef FLEX_ARRAY_SUPPORT + struct virtchnl2_ptype ptype[STRUCT_VAR_LEN]; +#endif /* !FLEX_ARRAY_SUPPORT */ }; +#ifndef FLEX_ARRAY_SUPPORT VIRTCHNL2_CHECK_STRUCT_LEN(16, virtchnl2_get_ptype_info); +#else +VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_get_ptype_info); +#endif /* !FLEX_ARRAY_SUPPORT */ /** * struct virtchnl2_vport_stats - Vport statistics @@ -1597,7 +1669,11 @@ struct virtchnl2_rss_key { __le16 key_len; u8 pad; +#ifdef FLEX_ARRAY_SUPPORT + DECLARE_FLEX_ARRAY(u8, key); +#else u8 key[1]; +#endif /* FLEX_ARRAY_SUPPORT */ }; VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_rss_key); @@ -1624,9 +1700,9 @@ VIRTCHNL2_CHECK_STRUCT_LEN(16, virtchnl2_queue_chunk); struct virtchnl2_queue_chunks { __le16 num_chunks; u8 pad[6]; - struct virtchnl2_queue_chunk chunks[1]; + struct virtchnl2_queue_chunk chunks[STRUCT_VAR_LEN]; }; -VIRTCHNL2_CHECK_STRUCT_LEN(24, virtchnl2_queue_chunks); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(24, virtchnl2_queue_chunks, chunks); /** * struct virtchnl2_del_ena_dis_queues - Enable/disable queues info @@ -1648,7 +1724,7 @@ struct virtchnl2_del_ena_dis_queues { struct virtchnl2_queue_chunks chunks; }; -VIRTCHNL2_CHECK_STRUCT_LEN(32, virtchnl2_del_ena_dis_queues); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(32, virtchnl2_del_ena_dis_queues, chunks.chunks); /** * struct virtchnl2_queue_vector - Queue to vector mapping @@ -1693,9 +1769,9 @@ struct virtchnl2_queue_vector_maps { __le16 num_qv_maps; u8 pad[10]; - struct virtchnl2_queue_vector qv_maps[1]; + struct virtchnl2_queue_vector qv_maps[STRUCT_VAR_LEN]; }; -VIRTCHNL2_CHECK_STRUCT_LEN(40, virtchnl2_queue_vector_maps); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(40, virtchnl2_queue_vector_maps, qv_maps); /** * struct virtchnl2_loopback - Loopback info @@ -1752,9 +1828,9 @@ struct virtchnl2_mac_addr_list { __le16 num_mac_addr; u8 pad[2]; - struct virtchnl2_mac_addr mac_addr_list[1]; + struct virtchnl2_mac_addr mac_addr_list[STRUCT_VAR_LEN]; }; -VIRTCHNL2_CHECK_STRUCT_LEN(16, virtchnl2_mac_addr_list); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(16, virtchnl2_mac_addr_list, mac_addr_list); /** * struct virtchnl2_promisc_info - Promiscuous type information @@ -1848,9 +1924,10 @@ struct virtchnl2_ptp_tx_tstamp { __le16 num_latches; __le16 latch_size; u8 pad[4]; - struct virtchnl2_ptp_tx_tstamp_entry ptp_tx_tstamp_entries[1]; + struct virtchnl2_ptp_tx_tstamp_entry ptp_tx_tstamp_entries[STRUCT_VAR_LEN]; }; -VIRTCHNL2_CHECK_STRUCT_LEN(24, virtchnl2_ptp_tx_tstamp); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(24, virtchnl2_ptp_tx_tstamp, + ptp_tx_tstamp_entries); /** * struct virtchnl2_get_ptp_caps - Get PTP capabilities @@ -1875,7 +1952,8 @@ struct virtchnl2_get_ptp_caps { struct virtchnl2_ptp_device_clock_control device_clock_control; struct virtchnl2_ptp_tx_tstamp tx_tstamp; }; -VIRTCHNL2_CHECK_STRUCT_LEN(88, virtchnl2_get_ptp_caps); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(88, virtchnl2_get_ptp_caps, + tx_tstamp.ptp_tx_tstamp_entries); /** * struct virtchnl2_ptp_tx_tstamp_latch - Structure that describes tx tstamp @@ -1911,10 +1989,10 @@ struct virtchnl2_ptp_tx_tstamp_latches { __le16 num_latches; __le16 latch_size; u8 pad[4]; - struct virtchnl2_ptp_tx_tstamp_latch tstamp_latches[1]; + struct virtchnl2_ptp_tx_tstamp_latch tstamp_latches[STRUCT_VAR_LEN]; }; - -VIRTCHNL2_CHECK_STRUCT_LEN(24, virtchnl2_ptp_tx_tstamp_latches); +VIRTCHNL2_CHECK_STRUCT_VAR_LEN(24, virtchnl2_ptp_tx_tstamp_latches, + tstamp_latches); static inline const char *virtchnl2_op_str(__le32 v_opcode) { @@ -2002,12 +2080,31 @@ static inline const char *virtchnl2_op_str(__le32 v_opcode) * Validate msg format against struct for each opcode. */ static inline int -virtchnl2_vc_validate_vf_msg(__rte_unused struct virtchnl2_version_info *ver, u32 v_opcode, +virtchnl2_vc_validate_vf_msg(struct virtchnl2_version_info *ver, u32 v_opcode, u8 *msg, __le16 msglen) { bool err_msg_format = false; +#ifdef FLEX_ARRAY_SUPPORT + bool is_flex_array = true; +#else + bool is_flex_array = false; +#endif /* !FLEX_ARRAY_SUPPORT */ __le32 valid_len = 0; - + __le32 num_chunks; + __le32 num_qgrps; + + /* It is possible that the FLEX_ARRAY_SUPPORT flag is not defined + * by all the users of virtchnl2 header file. Let's take an example + * where the driver doesn't support flex array and CP does. In this + * case, the size of the VIRTCHNL2_OP_CREATE_VPORT message sent from + * the driver would be 192 bytes because of the 1-sized array in the + * virtchnl2_create_vport structure whereas the message size expected + * by the CP would be 160 bytes (as the driver doesn't send any chunk + * information on create vport). This means, both 160 and 192 byte + * message length are valid. The math for the message size check of the + * opcodes consider the said scenarios for the flex array supported + * structures. + */ /* Validate message length */ switch (v_opcode) { case VIRTCHNL2_OP_VERSION: @@ -2017,19 +2114,21 @@ virtchnl2_vc_validate_vf_msg(__rte_unused struct virtchnl2_version_info *ver, u3 valid_len = sizeof(struct virtchnl2_get_capabilities); break; case VIRTCHNL2_OP_CREATE_VPORT: - valid_len = sizeof(struct virtchnl2_create_vport); - if (msglen >= valid_len) { - struct virtchnl2_create_vport *cvport = - (struct virtchnl2_create_vport *)msg; + num_chunks = ((struct virtchnl2_create_vport *)msg)->chunks.num_chunks; + valid_len = struct_size_t(struct virtchnl2_create_vport, + chunks.chunks, num_chunks); - if (cvport->chunks.num_chunks == 0) { - /* Zero chunks is allowed as input */ - break; - } + if (!is_flex_array) + /* Remove the additional chunk included in the + * struct_size_t calculation in case of no flex array + * support, due to the 1-sized array. + */ + valid_len -= sizeof(struct virtchnl2_queue_reg_chunk); + + /* Zero chunks is allowed as input */ + if (!num_chunks && msglen > valid_len) + valid_len += sizeof(struct virtchnl2_queue_reg_chunk); - valid_len += (cvport->chunks.num_chunks - 1) * - sizeof(struct virtchnl2_queue_reg_chunk); - } break; case VIRTCHNL2_OP_NON_FLEX_CREATE_ADI: valid_len = sizeof(struct virtchnl2_non_flex_create_adi); @@ -2061,183 +2160,165 @@ virtchnl2_vc_validate_vf_msg(__rte_unused struct virtchnl2_version_info *ver, u3 valid_len = sizeof(struct virtchnl2_vport); break; case VIRTCHNL2_OP_CONFIG_TX_QUEUES: - valid_len = sizeof(struct virtchnl2_config_tx_queues); - if (msglen >= valid_len) { - struct virtchnl2_config_tx_queues *ctq = - (struct virtchnl2_config_tx_queues *)msg; - if (ctq->num_qinfo == 0) { - err_msg_format = true; - break; - } - valid_len += (ctq->num_qinfo - 1) * - sizeof(struct virtchnl2_txq_info); + num_chunks = ((struct virtchnl2_config_tx_queues *)msg)->num_qinfo; + if (!num_chunks) { + err_msg_format = true; + break; } + + valid_len = struct_size_t(struct virtchnl2_config_tx_queues, + qinfo, num_chunks); + if (!is_flex_array) + valid_len -= sizeof(struct virtchnl2_txq_info); + break; case VIRTCHNL2_OP_CONFIG_RX_QUEUES: - valid_len = sizeof(struct virtchnl2_config_rx_queues); - if (msglen >= valid_len) { - struct virtchnl2_config_rx_queues *crq = - (struct virtchnl2_config_rx_queues *)msg; - if (crq->num_qinfo == 0) { - err_msg_format = true; - break; - } - valid_len += (crq->num_qinfo - 1) * - sizeof(struct virtchnl2_rxq_info); + num_chunks = ((struct virtchnl2_config_rx_queues *)msg)->num_qinfo; + if (!num_chunks) { + err_msg_format = true; + break; } + + valid_len = struct_size_t(struct virtchnl2_config_rx_queues, + qinfo, num_chunks); + if (!is_flex_array) + valid_len -= sizeof(struct virtchnl2_rxq_info); + break; case VIRTCHNL2_OP_ADD_QUEUES: - valid_len = sizeof(struct virtchnl2_add_queues); - if (msglen >= valid_len) { - struct virtchnl2_add_queues *add_q = - (struct virtchnl2_add_queues *)msg; + num_chunks = ((struct virtchnl2_add_queues *)msg)->chunks.num_chunks; + valid_len = struct_size_t(struct virtchnl2_add_queues, + chunks.chunks, num_chunks); + if (!is_flex_array) + valid_len -= sizeof(struct virtchnl2_queue_reg_chunk); - if (add_q->chunks.num_chunks == 0) { - /* Zero chunks is allowed as input */ - break; - } + /* Zero chunks is allowed as input */ + if (!num_chunks && msglen > valid_len) + valid_len += sizeof(struct virtchnl2_queue_reg_chunk); - valid_len += (add_q->chunks.num_chunks - 1) * - sizeof(struct virtchnl2_queue_reg_chunk); - } break; case VIRTCHNL2_OP_ENABLE_QUEUES: case VIRTCHNL2_OP_DISABLE_QUEUES: case VIRTCHNL2_OP_DEL_QUEUES: - valid_len = sizeof(struct virtchnl2_del_ena_dis_queues); - if (msglen >= valid_len) { - struct virtchnl2_del_ena_dis_queues *qs = - (struct virtchnl2_del_ena_dis_queues *)msg; - if (qs->chunks.num_chunks == 0 || - qs->chunks.num_chunks > VIRTCHNL2_OP_DEL_ENABLE_DISABLE_QUEUES_MAX) { - err_msg_format = true; - break; - } - valid_len += (qs->chunks.num_chunks - 1) * - sizeof(struct virtchnl2_queue_chunk); + num_chunks = ((struct virtchnl2_del_ena_dis_queues *)msg)->chunks.num_chunks; + if (!num_chunks || + num_chunks > VIRTCHNL2_OP_DEL_ENABLE_DISABLE_QUEUES_MAX) { + err_msg_format = true; + break; } + + valid_len = struct_size_t(struct virtchnl2_del_ena_dis_queues, + chunks.chunks, num_chunks); + if (!is_flex_array) + valid_len -= sizeof(struct virtchnl2_queue_chunk); + break; case VIRTCHNL2_OP_ADD_QUEUE_GROUPS: + num_qgrps = ((struct virtchnl2_add_queue_groups *)msg)->num_queue_groups; + if (!num_qgrps) { + err_msg_format = true; + break; + } + + /* valid_len is also used as an offset to find the array of + * virtchnl2_queue_group_info structures + */ valid_len = sizeof(struct virtchnl2_add_queue_groups); - if (msglen != valid_len) { - __le64 offset; - __le32 i; - struct virtchnl2_add_queue_groups *add_queue_grp = - (struct virtchnl2_add_queue_groups *)msg; - struct virtchnl2_queue_groups *groups = &(add_queue_grp->qg_info); - struct virtchnl2_queue_group_info *grp_info; - __le32 chunk_size = sizeof(struct virtchnl2_queue_reg_chunk); - __le32 group_size = sizeof(struct virtchnl2_queue_group_info); - __le32 total_chunks_size; - - if (groups->num_queue_groups == 0) { - err_msg_format = true; - break; - } - valid_len += (groups->num_queue_groups - 1) * - sizeof(struct virtchnl2_queue_group_info); - offset = (u8 *)(&groups->groups[0]) - (u8 *)groups; - - for (i = 0; i < groups->num_queue_groups; i++) { - grp_info = (struct virtchnl2_queue_group_info *) - ((u8 *)groups + offset); - if (grp_info->chunks.num_chunks == 0) { - offset += group_size; - continue; - } - total_chunks_size = (grp_info->chunks.num_chunks - 1) * chunk_size; - offset += group_size + total_chunks_size; - valid_len += total_chunks_size; - } + if (!is_flex_array) + valid_len -= sizeof(struct virtchnl2_queue_group_info); + + while (num_qgrps--) { + struct virtchnl2_queue_group_info *qgrp_info; + + qgrp_info = (struct virtchnl2_queue_group_info *) + ((u8 *)msg + valid_len); + num_chunks = qgrp_info->chunks.num_chunks; + + valid_len += struct_size_t(struct virtchnl2_queue_group_info, + chunks.chunks, num_chunks); + if (!is_flex_array) + valid_len -= sizeof(struct virtchnl2_queue_reg_chunk); } + break; case VIRTCHNL2_OP_DEL_QUEUE_GROUPS: - valid_len = sizeof(struct virtchnl2_delete_queue_groups); - if (msglen != valid_len) { - struct virtchnl2_delete_queue_groups *del_queue_grp = - (struct virtchnl2_delete_queue_groups *)msg; + num_qgrps = ((struct virtchnl2_delete_queue_groups *)msg)->num_queue_groups; + if (!num_qgrps) { + err_msg_format = true; + break; + } - if (del_queue_grp->num_queue_groups == 0) { - err_msg_format = true; - break; - } + valid_len = struct_size_t(struct virtchnl2_delete_queue_groups, + qg_ids, num_qgrps); + if (!is_flex_array) + valid_len -= sizeof(struct virtchnl2_queue_group_id); - valid_len += (del_queue_grp->num_queue_groups - 1) * - sizeof(struct virtchnl2_queue_group_id); - } break; case VIRTCHNL2_OP_MAP_QUEUE_VECTOR: case VIRTCHNL2_OP_UNMAP_QUEUE_VECTOR: - valid_len = sizeof(struct virtchnl2_queue_vector_maps); - if (msglen >= valid_len) { - struct virtchnl2_queue_vector_maps *v_qp = - (struct virtchnl2_queue_vector_maps *)msg; - if (v_qp->num_qv_maps == 0 || - v_qp->num_qv_maps > VIRTCHNL2_OP_MAP_UNMAP_QUEUE_VECTOR_MAX) { - err_msg_format = true; - break; - } - valid_len += (v_qp->num_qv_maps - 1) * - sizeof(struct virtchnl2_queue_vector); + num_chunks = ((struct virtchnl2_queue_vector_maps *)msg)->num_qv_maps; + if (!num_chunks || + num_chunks > VIRTCHNL2_OP_MAP_UNMAP_QUEUE_VECTOR_MAX) { + err_msg_format = true; + break; } + + valid_len = struct_size_t(struct virtchnl2_queue_vector_maps, + qv_maps, num_chunks); + if (!is_flex_array) + valid_len -= sizeof(struct virtchnl2_queue_vector); + break; case VIRTCHNL2_OP_ALLOC_VECTORS: - valid_len = sizeof(struct virtchnl2_alloc_vectors); - if (msglen >= valid_len) { - struct virtchnl2_alloc_vectors *v_av = - (struct virtchnl2_alloc_vectors *)msg; + num_chunks = ((struct virtchnl2_alloc_vectors *)msg)->vchunks.num_vchunks; + valid_len = struct_size_t(struct virtchnl2_alloc_vectors, + vchunks.vchunks, num_chunks); + if (!is_flex_array) + valid_len -= sizeof(struct virtchnl2_vector_chunk); - if (v_av->vchunks.num_vchunks == 0) { - /* Zero chunks is allowed as input */ - break; - } + /* Zero chunks is allowed as input */ + if (!num_chunks && msglen > valid_len) + valid_len += sizeof(struct virtchnl2_vector_chunk); - valid_len += (v_av->vchunks.num_vchunks - 1) * - sizeof(struct virtchnl2_vector_chunk); - } break; case VIRTCHNL2_OP_DEALLOC_VECTORS: - valid_len = sizeof(struct virtchnl2_vector_chunks); - if (msglen >= valid_len) { - struct virtchnl2_vector_chunks *v_chunks = - (struct virtchnl2_vector_chunks *)msg; - if (v_chunks->num_vchunks == 0) { - err_msg_format = true; - break; - } - valid_len += (v_chunks->num_vchunks - 1) * - sizeof(struct virtchnl2_vector_chunk); + num_chunks = ((struct virtchnl2_vector_chunks *)msg)->num_vchunks; + if (!num_chunks) { + err_msg_format = true; + break; } + + valid_len = struct_size_t(struct virtchnl2_vector_chunks, + vchunks, num_chunks); + if (!is_flex_array) + valid_len -= sizeof(struct virtchnl2_vector_chunk); + break; case VIRTCHNL2_OP_GET_RSS_KEY: case VIRTCHNL2_OP_SET_RSS_KEY: - valid_len = sizeof(struct virtchnl2_rss_key); - if (msglen >= valid_len) { - struct virtchnl2_rss_key *vrk = - (struct virtchnl2_rss_key *)msg; + num_chunks = ((struct virtchnl2_rss_key *)msg)->key_len; + valid_len = struct_size_t(struct virtchnl2_rss_key, + key, num_chunks); + if (!is_flex_array) + valid_len -= sizeof(u8); - if (vrk->key_len == 0) { - /* Zero length is allowed as input */ - break; - } + /* Zero entries is allowed as input */ + if (!num_chunks && msglen > valid_len) + valid_len += sizeof(u8); - valid_len += vrk->key_len - 1; - } break; case VIRTCHNL2_OP_GET_RSS_LUT: case VIRTCHNL2_OP_SET_RSS_LUT: - valid_len = sizeof(struct virtchnl2_rss_lut); - if (msglen >= valid_len) { - struct virtchnl2_rss_lut *vrl = - (struct virtchnl2_rss_lut *)msg; + num_chunks = ((struct virtchnl2_rss_lut *)msg)->lut_entries; + valid_len = struct_size_t(struct virtchnl2_rss_lut, + lut, num_chunks); + if (!is_flex_array) + valid_len -= sizeof(__le32); - if (vrl->lut_entries == 0) { - /* Zero entries is allowed as input */ - break; - } + /* Zero entries is allowed as input */ + if (!num_chunks && msglen > valid_len) + valid_len += sizeof(__le32); - valid_len += (vrl->lut_entries - 1) * sizeof(vrl->lut); - } break; case VIRTCHNL2_OP_GET_RSS_HASH: case VIRTCHNL2_OP_SET_RSS_HASH: @@ -2257,37 +2338,60 @@ virtchnl2_vc_validate_vf_msg(__rte_unused struct virtchnl2_version_info *ver, u3 break; case VIRTCHNL2_OP_RESET_VF: break; - case VIRTCHNL2_OP_GET_PTP_CAPS: - valid_len = sizeof(struct virtchnl2_get_ptp_caps); - - if (msglen > valid_len) { - struct virtchnl2_get_ptp_caps *ptp_caps = - (struct virtchnl2_get_ptp_caps *)msg; +#ifdef VIRTCHNL2_EDT_SUPPORT + case VIRTCHNL2_OP_GET_EDT_CAPS: + valid_len = sizeof(struct virtchnl2_edt_caps); + break; +#endif /* VIRTCHNL2_EDT_SUPPORT */ +#ifdef NOT_FOR_UPSTREAM + case VIRTCHNL2_OP_GET_OEM_CAPS: + valid_len = sizeof(struct virtchnl2_oem_caps); + break; +#endif /* NOT_FOR_UPSTREAM */ +#ifdef VIRTCHNL2_IWARP + case VIRTCHNL2_OP_RDMA: + /* These messages are opaque to us and will be validated in + * the RDMA client code. We just need to check for nonzero + * length. The firmware will enforce max length restrictions. + */ + if (msglen) + valid_len = msglen; + else + err_msg_format = true; + break; + case VIRTCHNL2_OP_RELEASE_RDMA_IRQ_MAP: + break; + case VIRTCHNL2_OP_CONFIG_RDMA_IRQ_MAP: + num_chunks = ((struct virtchnl2_rdma_qvlist_info *)msg)->num_vectors; + if (!num_chunks || + num_chunks > VIRTCHNL2_OP_CONFIG_RDMA_IRQ_MAP_MAX) { + err_msg_format = true; + break; + } - if (ptp_caps->tx_tstamp.num_latches == 0) { - err_msg_format = true; - break; - } + valid_len = struct_size_t(struct virtchnl2_rdma_qvlist_info, + qv_info, num_chunks); + if (!is_flex_array) + valid_len -= sizeof(struct virtchnl2_rdma_qv_info); - valid_len += ((ptp_caps->tx_tstamp.num_latches - 1) * - sizeof(struct virtchnl2_ptp_tx_tstamp_entry)); - } + break; +#endif /* VIRTCHNL2_IWARP */ + case VIRTCHNL2_OP_GET_PTP_CAPS: + valid_len = sizeof(struct virtchnl2_get_ptp_caps); break; case VIRTCHNL2_OP_GET_PTP_TX_TSTAMP_LATCHES: valid_len = sizeof(struct virtchnl2_ptp_tx_tstamp_latches); + num_chunks = ((struct virtchnl2_ptp_tx_tstamp_latches *)msg)->num_latches; + if (!num_chunks) { + err_msg_format = true; + break; + } - if (msglen > valid_len) { - struct virtchnl2_ptp_tx_tstamp_latches *tx_tstamp_latches = - (struct virtchnl2_ptp_tx_tstamp_latches *)msg; - - if (tx_tstamp_latches->num_latches == 0) { - err_msg_format = true; - break; - } + valid_len = struct_size_t(struct virtchnl2_ptp_tx_tstamp_latches, + tstamp_latches, num_chunks); + if (!is_flex_array) + valid_len -= sizeof(struct virtchnl2_ptp_tx_tstamp_latch); - valid_len += ((tx_tstamp_latches->num_latches - 1) * - sizeof(struct virtchnl2_ptp_tx_tstamp_latch)); - } break; /* These are always errors coming from the VF */ case VIRTCHNL2_OP_EVENT: -- 2.43.0