From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 87B61C46CD2 for ; Wed, 24 Jan 2024 21:35:26 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 40AA140181; Wed, 24 Jan 2024 21:35:26 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 40AA140181 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osuosl.org; s=default; t=1706132126; bh=wPwtOzXUIVESNUzQzMTPPyc5bmP5gjEVG8SX17p82lo=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: Cc:From; b=z5BAtA/E8Z1Uebrva0kAsSInZYMv8CtN5ECWHjnZeEVYwxogQ2SmjJf256HqvsTVg 9ENQmOjA32I1McjlwOyp6NxBPuqDATPBByLgumrK1MZjOFnCcd28LGrrkyuoRwoZLP p25Fa7a89rhOStWjx/sDZ2LgXijWMJu6LT99iBNlr80xZNunnQb+TZUVv8L1JIg/Es H8Tft/z1Pn8ko1M06vVfPLkNvZ4cxgDBAVGg2CypVq1B+bHyrGd1zAVz1fT0gxPO1H TUAu4KewzJRTfuUfC7q9rroLTg5RJOpe6fzTnm9oqDhWrJ/MG31xzAYYRL7Nk6o8vf z7ysTojl5Ws4g== X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id IsPB8yIc2t1Z; Wed, 24 Jan 2024 21:35:25 +0000 (UTC) Received: from ash.osuosl.org (ash.osuosl.org [140.211.166.34]) by smtp2.osuosl.org (Postfix) with ESMTP id B4DDE4035D; Wed, 24 Jan 2024 21:35:24 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org B4DDE4035D Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by ash.osuosl.org (Postfix) with ESMTP id 07BA31BF3BF for ; Wed, 24 Jan 2024 21:35:24 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id DF8C060D90 for ; Wed, 24 Jan 2024 21:35:23 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org DF8C060D90 X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id FEa1oCnJvoHA for ; Wed, 24 Jan 2024 21:35:23 +0000 (UTC) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) by smtp3.osuosl.org (Postfix) with ESMTPS id DFC6560D6B for ; Wed, 24 Jan 2024 21:35:22 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org DFC6560D6B X-IronPort-AV: E=McAfee;i="6600,9927,10962"; a="8745836" X-IronPort-AV: E=Sophos;i="6.05,216,1701158400"; d="scan'208";a="8745836" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Jan 2024 13:35:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10962"; a="909788438" X-IronPort-AV: E=Sophos;i="6.05,216,1701158400"; d="scan'208";a="909788438" Received: from irvmail002.ir.intel.com ([10.43.11.120]) by orsmga004.jf.intel.com with ESMTP; 24 Jan 2024 13:35:19 -0800 Received: from lplachno-mobl.ger.corp.intel.com (lplachno-mobl.ger.corp.intel.com [10.246.2.62]) by irvmail002.ir.intel.com (Postfix) with ESMTP id DB0E09A4B8; Wed, 24 Jan 2024 15:21:47 +0000 (GMT) From: Lukasz Plachno To: intel-wired-lan@lists.osuosl.org Date: Wed, 24 Jan 2024 16:21:41 +0100 Message-Id: <20240124152141.15077-3-lukasz.plachno@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240124152141.15077-1-lukasz.plachno@intel.com> References: <20240124152141.15077-1-lukasz.plachno@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1706132123; x=1737668123; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Y8yaL0M7jbtEtD6gEjD1CTj/BxjXD/spE7WBg4M2UMY=; b=CmUkZN3eHtyopra+sasMKQ3zYFYMHWaEsm9RXAuZNYt89YijupXspgf9 KJ8AzAybwOebrO+p9/pD4ohvS2Fflflaoi3+8Y2IbhDMbKmEbg0pyKihP KONeHSrZe+acuPgpuLGYBHtY5Dfqv/yUitBlxvWYBw2bnkiHCdXT938xq C+5uqp31/mo05IvkuUh9UOH88UzpD84zrS/1KWAfKn6bcp8n39vM+7Bno HauhT1O6WK7ro4XCudVEoA4PvMpGHIjxQ9dhtDVQVplmBmPCWWxz/x58T HdMTtl97rK75Mgv6pi45gFgv4r8cl73riLEm1pUVKm5OLmPu6+T6RrWJl g==; X-Mailman-Original-Authentication-Results: smtp3.osuosl.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=CmUkZN3e Subject: [Intel-wired-lan] [PATCH iwl-next v4 2/2] ice: Implement 'flow-type ether' rules X-BeenThere: intel-wired-lan@osuosl.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel Wired Ethernet Linux Kernel Driver Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: brett.creeley@amd.com, Przemek Kitszel , Mateusz Pacuszka , Jakub Buchocki , Lukasz Plachno , horms@kernel.org, netdev@vger.kernel.org Errors-To: intel-wired-lan-bounces@osuosl.org Sender: "Intel-wired-lan" From: Jakub Buchocki Add support for 'flow-type ether' Flow Director rules via ethtool. Rules not containing masks are processed by the Flow Director, and support the following set of input parameters in all combinations: src, dst, proto, vlan-etype, vlan, action. It is possible to specify address mask in ethtool parameters but only 00:00:00:00:00 and FF:FF:FF:FF:FF are valid. The same applies to proto, vlan-etype and vlan masks: only 0x0000 and 0xffff masks are valid. Signed-off-by: Jakub Buchocki Co-developed-by: Mateusz Pacuszka Signed-off-by: Mateusz Pacuszka Reviewed-by: Przemek Kitszel Signed-off-by: Lukasz Plachno --- .../net/ethernet/intel/ice/ice_ethtool_fdir.c | 140 +++++++++++++++++- drivers/net/ethernet/intel/ice/ice_fdir.c | 27 ++++ drivers/net/ethernet/intel/ice/ice_fdir.h | 11 ++ drivers/net/ethernet/intel/ice/ice_type.h | 1 + 4 files changed, 178 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c index 9a1a04f5f146..d6fadc65a7a6 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c @@ -41,6 +41,8 @@ static struct in6_addr zero_ipv6_addr_mask = { static int ice_fltr_to_ethtool_flow(enum ice_fltr_ptype flow) { switch (flow) { + case ICE_FLTR_PTYPE_NONF_ETH: + return ETHER_FLOW; case ICE_FLTR_PTYPE_NONF_IPV4_TCP: return TCP_V4_FLOW; case ICE_FLTR_PTYPE_NONF_IPV4_UDP: @@ -72,6 +74,8 @@ static int ice_fltr_to_ethtool_flow(enum ice_fltr_ptype flow) static enum ice_fltr_ptype ice_ethtool_flow_to_fltr(int eth) { switch (eth) { + case ETHER_FLOW: + return ICE_FLTR_PTYPE_NONF_ETH; case TCP_V4_FLOW: return ICE_FLTR_PTYPE_NONF_IPV4_TCP; case UDP_V4_FLOW: @@ -137,6 +141,15 @@ int ice_get_ethtool_fdir_entry(struct ice_hw *hw, struct ethtool_rxnfc *cmd) memset(&fsp->m_ext, 0, sizeof(fsp->m_ext)); switch (fsp->flow_type) { + case ETHER_FLOW: + fsp->h_u.ether_spec.h_proto = rule->eth.type; + fsp->m_u.ether_spec.h_proto = rule->eth_mask.type; + ether_addr_copy(fsp->h_u.ether_spec.h_dest, rule->eth.dst); + ether_addr_copy(fsp->m_u.ether_spec.h_dest, rule->eth_mask.dst); + ether_addr_copy(fsp->h_u.ether_spec.h_source, rule->eth.src); + ether_addr_copy(fsp->m_u.ether_spec.h_source, + rule->eth_mask.src); + break; case IPV4_USER_FLOW: fsp->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4; fsp->h_u.usr_ip4_spec.proto = 0; @@ -1193,6 +1206,111 @@ ice_set_fdir_ip6_usr_seg(struct ice_flow_seg_info *seg, return 0; } +/** + * ice_fdir_vlan_valid - validate VLAN data for Flow Director rule + * @fsp: pointer to ethtool Rx flow specification + * + * Return: true if vlan data is valid, false otherwise + */ +static bool ice_fdir_vlan_valid(struct ethtool_rx_flow_spec *fsp) +{ + if (fsp->m_ext.vlan_etype && !eth_type_vlan(fsp->h_ext.vlan_etype)) + return false; + + if (fsp->m_ext.vlan_tci && + ntohs(fsp->h_ext.vlan_tci) >= VLAN_N_VID) + return false; + + return true; +} + +/** + * ice_set_ether_flow_seg + * @seg: flow segment for programming + * @eth_spec: mask data from ethtool + * + * Return: 0 on success and errno in case of error. + */ +static int ice_set_ether_flow_seg(struct device *dev, + struct ice_flow_seg_info *seg, + struct ethhdr *eth_spec) +{ + ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_ETH); + + /* empty rules are not valid */ + if (is_zero_ether_addr(eth_spec->h_source) && + is_zero_ether_addr(eth_spec->h_dest) && + !eth_spec->h_proto) + return -EINVAL; + + /* Ethertype */ + if (eth_spec->h_proto == htons(0xFFFF)) { + ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_ETH_TYPE, + ICE_FLOW_FLD_OFF_INVAL, + ICE_FLOW_FLD_OFF_INVAL, + ICE_FLOW_FLD_OFF_INVAL, false); + } else if (eth_spec->h_proto) { + dev_warn(dev, "Only 0x0000 or 0xffff proto mask is allowed for flow-type ether"); + return -EOPNOTSUPP; + } + + /* Source MAC address */ + if (is_broadcast_ether_addr(eth_spec->h_source)) + ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_ETH_SA, + ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, + ICE_FLOW_FLD_OFF_INVAL, false); + else if (!is_zero_ether_addr(eth_spec->h_source)) + goto err_mask; + + /* Destination MAC address */ + if (is_broadcast_ether_addr(eth_spec->h_dest)) + ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_ETH_DA, + ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, + ICE_FLOW_FLD_OFF_INVAL, false); + else if (!is_zero_ether_addr(eth_spec->h_dest)) + goto err_mask; + + return 0; + +err_mask: + dev_warn(dev, "Only 00:00:00:00:00:00 or ff:ff:ff:ff:ff:ff MAC address mask is allowed for flow-type ether"); + return -EOPNOTSUPP; +} + +/** + * ice_set_fdir_vlan_seg + * @seg: flow segment for programming + * @ext_masks: masks for additional RX flow fields + */ +static int +ice_set_fdir_vlan_seg(struct ice_flow_seg_info *seg, + struct ethtool_flow_ext *ext_masks) +{ + ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_VLAN); + + if (ext_masks->vlan_etype) { + if (ext_masks->vlan_etype != htons(0xFFFF)) + return -EOPNOTSUPP; + + ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_S_VLAN, + ICE_FLOW_FLD_OFF_INVAL, + ICE_FLOW_FLD_OFF_INVAL, + ICE_FLOW_FLD_OFF_INVAL, false); + } + + if (ext_masks->vlan_tci) { + if (ext_masks->vlan_tci != htons(0xFFFF)) + return -EOPNOTSUPP; + + ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_C_VLAN, + ICE_FLOW_FLD_OFF_INVAL, + ICE_FLOW_FLD_OFF_INVAL, + ICE_FLOW_FLD_OFF_INVAL, false); + } + + return 0; +} + /** * ice_cfg_fdir_xtrct_seq - Configure extraction sequence for the given filter * @pf: PF structure @@ -1209,7 +1327,7 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp, struct device *dev = ice_pf_to_dev(pf); enum ice_fltr_ptype fltr_idx; struct ice_hw *hw = &pf->hw; - bool perfect_filter; + bool perfect_filter = false; int ret; seg = devm_kzalloc(dev, sizeof(*seg), GFP_KERNEL); @@ -1262,6 +1380,16 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp, ret = ice_set_fdir_ip6_usr_seg(seg, &fsp->m_u.usr_ip6_spec, &perfect_filter); break; + case ETHER_FLOW: + ret = ice_set_ether_flow_seg(dev, seg, &fsp->m_u.ether_spec); + if (!ret && (fsp->m_ext.vlan_etype || fsp->m_ext.vlan_tci)) { + if (!ice_fdir_vlan_valid(fsp)) { + ret = -EINVAL; + break; + } + ret = ice_set_fdir_vlan_seg(seg, &fsp->m_ext); + } + break; default: ret = -EINVAL; } @@ -1823,6 +1951,16 @@ ice_set_fdir_input_set(struct ice_vsi *vsi, struct ethtool_rx_flow_spec *fsp, input->mask.v6.tc = fsp->m_u.usr_ip6_spec.tclass; input->mask.v6.proto = fsp->m_u.usr_ip6_spec.l4_proto; break; + case ETHER_FLOW: + ether_addr_copy(input->eth.dst, fsp->h_u.ether_spec.h_dest); + ether_addr_copy(input->eth.src, fsp->h_u.ether_spec.h_source); + ether_addr_copy(input->eth_mask.dst, + fsp->m_u.ether_spec.h_dest); + ether_addr_copy(input->eth_mask.src, + fsp->m_u.ether_spec.h_source); + input->eth.type = fsp->h_u.ether_spec.h_proto; + input->eth_mask.type = fsp->m_u.ether_spec.h_proto; + break; default: /* not doing un-parsed flow types */ return -EINVAL; diff --git a/drivers/net/ethernet/intel/ice/ice_fdir.c b/drivers/net/ethernet/intel/ice/ice_fdir.c index 1f7b26f38818..5fe0bad00fd7 100644 --- a/drivers/net/ethernet/intel/ice/ice_fdir.c +++ b/drivers/net/ethernet/intel/ice/ice_fdir.c @@ -4,6 +4,8 @@ #include "ice_common.h" /* These are training packet headers used to program flow director filters. */ +static const u8 ice_fdir_eth_pkt[22] = {0}; + static const u8 ice_fdir_tcpv4_pkt[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, @@ -416,6 +418,11 @@ static const u8 ice_fdir_ip6_tun_pkt[] = { /* Flow Director no-op training packet table */ static const struct ice_fdir_base_pkt ice_fdir_pkt[] = { + { + ICE_FLTR_PTYPE_NONF_ETH, + sizeof(ice_fdir_eth_pkt), ice_fdir_eth_pkt, + sizeof(ice_fdir_eth_pkt), ice_fdir_eth_pkt, + }, { ICE_FLTR_PTYPE_NONF_IPV4_TCP, sizeof(ice_fdir_tcpv4_pkt), ice_fdir_tcpv4_pkt, @@ -914,6 +921,22 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input, * perspective. The input from user is from Rx filter perspective. */ switch (flow) { + case ICE_FLTR_PTYPE_NONF_ETH: + ice_pkt_insert_mac_addr(loc, input->eth.dst); + ice_pkt_insert_mac_addr(loc + ETH_ALEN, input->eth.src); + if (input->ext_data.vlan_tag || + input->ext_data.vlan_type) { + ice_pkt_insert_u16(loc, ICE_ETH_TYPE_F_OFFSET, + input->ext_data.vlan_type); + ice_pkt_insert_u16(loc, ICE_ETH_VLAN_TCI_OFFSET, + input->ext_data.vlan_tag); + ice_pkt_insert_u16(loc, ICE_ETH_TYPE_VLAN_OFFSET, + input->eth.type); + } else { + ice_pkt_insert_u16(loc, ICE_ETH_TYPE_F_OFFSET, + input->eth.type); + } + break; case ICE_FLTR_PTYPE_NONF_IPV4_TCP: ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET, input->ip.v4.src_ip); @@ -1201,6 +1224,10 @@ ice_fdir_comp_rules(struct ice_fdir_fltr *a, struct ice_fdir_fltr *b) * same flow_type. */ switch (flow_type) { + case ICE_FLTR_PTYPE_NONF_ETH: + if (!memcmp(&a->eth, &b->eth, sizeof(a->eth))) + return true; + break; case ICE_FLTR_PTYPE_NONF_IPV4_TCP: case ICE_FLTR_PTYPE_NONF_IPV4_UDP: case ICE_FLTR_PTYPE_NONF_IPV4_SCTP: diff --git a/drivers/net/ethernet/intel/ice/ice_fdir.h b/drivers/net/ethernet/intel/ice/ice_fdir.h index 1b9b84490689..0c90865a36c5 100644 --- a/drivers/net/ethernet/intel/ice/ice_fdir.h +++ b/drivers/net/ethernet/intel/ice/ice_fdir.h @@ -8,6 +8,9 @@ #define ICE_FDIR_MAX_RAW_PKT_SIZE (512 + ICE_FDIR_TUN_PKT_OFF) /* macros for offsets into packets for flow director programming */ +#define ICE_ETH_TYPE_F_OFFSET 12 +#define ICE_ETH_VLAN_TCI_OFFSET 14 +#define ICE_ETH_TYPE_VLAN_OFFSET 16 #define ICE_IPV4_SRC_ADDR_OFFSET 26 #define ICE_IPV4_DST_ADDR_OFFSET 30 #define ICE_IPV4_TCP_SRC_PORT_OFFSET 34 @@ -97,6 +100,12 @@ struct ice_rx_flow_userdef { u16 flex_fltr; }; +struct ice_fdir_eth { + u8 dst[ETH_ALEN]; + u8 src[ETH_ALEN]; + __be16 type; +}; + struct ice_fdir_v4 { __be32 dst_ip; __be32 src_ip; @@ -159,6 +168,8 @@ struct ice_fdir_fltr { struct list_head fltr_node; enum ice_fltr_ptype flow_type; + struct ice_fdir_eth eth, eth_mask; + union { struct ice_fdir_v4 v4; struct ice_fdir_v6 v6; diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index 6df7c4487ad0..391e48d2bb92 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -203,6 +203,7 @@ struct ice_phy_info { enum ice_fltr_ptype { /* NONE - used for undef/error */ ICE_FLTR_PTYPE_NONF_NONE = 0, + ICE_FLTR_PTYPE_NONF_ETH, ICE_FLTR_PTYPE_NONF_IPV4_UDP, ICE_FLTR_PTYPE_NONF_IPV4_TCP, ICE_FLTR_PTYPE_NONF_IPV4_SCTP, -- 2.34.1