From nobody Wed Dec 17 05:49:26 2025 Received: from mail-yb1-f202.google.com (mail-yb1-f202.google.com [209.85.219.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B16E885950 for ; Tue, 7 May 2024 23:00:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715122825; cv=none; b=nP3IKUtSZ+IaL9toLxrHeidI17mRFJe9Qa49nUMGXkMbZ3bbrrJ62M2tren+wSftLJ3qcW5IqDf7W5mc4/AcLz1p7TdJfBd9Z13XScDL5/AkbXkgNZVSorhrFeP4znBx+YG53zKuKdm+c2FNlBqQNoApSQEW3nNwwFKPBPK2qrY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715122825; c=relaxed/simple; bh=s/dVkIkUpEFDuGji+Sn4Br+tvktQk5DrZvLWBha5wH0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=WxgJmHtvPnKIGWpJiPrc2X6DA+qkdowmgFerZhJU2RyjaW2JXhXBGk1DUlq36Nz2iHM/mMjR2Hr/Fpo5PcNU3u4NAWQ6Y2NSxFfJJ1XfM2DUv1KWq2s39+OXD8xXedniVvsYTYn4Vf8wbWcn/960Q5Uk3Iq7umzF4/7NXhCzw7w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ziweixiao.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=muTyqvL6; arc=none smtp.client-ip=209.85.219.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ziweixiao.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="muTyqvL6" Received: by mail-yb1-f202.google.com with SMTP id 3f1490d57ef6-de615257412so7389358276.0 for ; Tue, 07 May 2024 16:00:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1715122823; x=1715727623; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=0RjaB4t+jqoB/u9GU06wWmu2KYLJOP55f0UnNOqajSk=; b=muTyqvL6RLEpAHD4vpHiQxrYLa3LXGTrHJl0wpumFspI36Mbuqo6awNPevPlKqXmkd cjz/LvyIKMBsyNRq1TevwuNJ9rMJCVV9hdQXH2RzQEJN5aSGnX15DkKlqGbd8n237+Ns xqC0wigxGJJ7Q2u5tVM51h7HeCcJsjCLeuNlPDQN1YNweYPxiwArNbNjculIO+3a4xaJ 2U6cY8SzsVQTBZkIiSVYr1liDRXakuM2/oJhO8L5jwJGrpNXyCyfNmPnIBO7kkX7GVe5 NFKxu8s1Gn/NNqYOkyvTaWOAzms1H+B9GNveqRYl+YPTOYF4cdY6gZMP5P+lGLpK+1sg MOBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715122823; x=1715727623; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=0RjaB4t+jqoB/u9GU06wWmu2KYLJOP55f0UnNOqajSk=; b=XKVE2+6DiPOWv2gEQzPimDi4jRNQi6ntPMkFysQWUCrUCdYeVAEFP4GYYizgK7LfKT a2v78H9o1q59VlXiSEMHjHKW2Ue6zEbqbD9couSNk1YLL60Y+isiCeys2P/dWx/LNteQ d7GW+l7mCW9lwNRAA5ziVtPQQeu3qcOtlci+ZLTI1Vygg/bCj6OFoSsYU6wRTePqohhS Lmd9X9UmT2Q1CdXRco9ewnGQkFo7Lq2KnoatAsYHSWyMttLorfqeIR6AkfTeXgVnqUqq Q4oVmh4t7tZuJkpP1NA1yMHblNXz1aMuvJ5VWeqV5WWTU1ZP6inDgBvfiLbDS6/2Oq/Y DkOg== X-Forwarded-Encrypted: i=1; AJvYcCVY2A3q9on+p8qZOtk1E0E904V4Ni0eSXdN8QeqH3IvRgWYqVDxcBBJey7muF8Qv8uA4uNKTn2bGgoZIJbHzMHxyVW0/DMcS7tEB0CS X-Gm-Message-State: AOJu0YzA4ObFmUCG8L12RkHNixSloegTDa8xM1CDhvKfaCDqovrxNbC+ KRmCdYiIZ0DTYzMm24UZKeukWFQ0lBasRtd+L6cN77I0bt/qg1fJ65FXXBOHf4dapVFNkdrLAZ+ Mq0DuEe7zk7acaA== X-Google-Smtp-Source: AGHT+IHeHwpUsMz3naPYvRlDkGuNZZCEn9CqAnc0Smm5DESeStqFj91Zn/11qRtNpmoue13EExJCmpgR2BPwxrE= X-Received: from ziwei-gti.c.googlers.com ([fda3:e722:ac3:cc00:20:ed76:c0a8:9b0]) (user=ziweixiao job=sendgmr) by 2002:a05:6902:1881:b0:de5:250a:f1e7 with SMTP id 3f1490d57ef6-debb9e397e4mr313067276.8.1715122822767; Tue, 07 May 2024 16:00:22 -0700 (PDT) Date: Tue, 7 May 2024 22:59:41 +0000 In-Reply-To: <20240507225945.1408516-1-ziweixiao@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240507225945.1408516-1-ziweixiao@google.com> X-Mailer: git-send-email 2.45.0.rc1.225.g2a3ae87e7f-goog Message-ID: <20240507225945.1408516-2-ziweixiao@google.com> Subject: [PATCH net-next 1/5] gve: Add adminq mutex lock From: Ziwei Xiao To: netdev@vger.kernel.org Cc: jeroendb@google.com, pkaligineedi@google.com, shailend@google.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, willemb@google.com, hramamurthy@google.com, rushilg@google.com, ziweixiao@google.com, jfraker@google.com, linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" We were depending on the rtnl_lock to make sure there is only one adminq command running at a time. But some commands may take too long to hold the rtnl_lock, such as the upcoming flow steering operations. For such situations, it can temporarily drop the rtnl_lock, and replace it for these operations with a new adminq lock, which can ensure the adminq command execution to be thread-safe. Signed-off-by: Ziwei Xiao Reviewed-by: Praveen Kaligineedi Reviewed-by: Harshitha Ramamurthy Reviewed-by: Willem de Bruijn --- drivers/net/ethernet/google/gve/gve.h | 1 + drivers/net/ethernet/google/gve/gve_adminq.c | 22 +++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/g= oogle/gve/gve.h index ae1e21c9b0a5..ca7fce17f2c0 100644 --- a/drivers/net/ethernet/google/gve/gve.h +++ b/drivers/net/ethernet/google/gve/gve.h @@ -724,6 +724,7 @@ struct gve_priv { union gve_adminq_command *adminq; dma_addr_t adminq_bus_addr; struct dma_pool *adminq_pool; + struct mutex adminq_lock; /* Protects adminq command execution */ u32 adminq_mask; /* masks prod_cnt to adminq size */ u32 adminq_prod_cnt; /* free-running count of AQ cmds executed */ u32 adminq_cmd_fail; /* free-running count of AQ cmds failed */ diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/eth= ernet/google/gve/gve_adminq.c index 3df8243680d9..2c3ec5c3b114 100644 --- a/drivers/net/ethernet/google/gve/gve_adminq.c +++ b/drivers/net/ethernet/google/gve/gve_adminq.c @@ -284,6 +284,7 @@ int gve_adminq_alloc(struct device *dev, struct gve_pri= v *priv) &priv->reg_bar0->adminq_base_address_lo); iowrite32be(GVE_DRIVER_STATUS_RUN_MASK, &priv->reg_bar0->driver_status); } + mutex_init(&priv->adminq_lock); gve_set_admin_queue_ok(priv); return 0; } @@ -511,28 +512,29 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv, return 0; } =20 -/* This function is not threadsafe - the caller is responsible for any - * necessary locks. - * The caller is also responsible for making sure there are no commands - * waiting to be executed. - */ static int gve_adminq_execute_cmd(struct gve_priv *priv, union gve_adminq_command *cmd_orig) { u32 tail, head; int err; =20 + mutex_lock(&priv->adminq_lock); tail =3D ioread32be(&priv->reg_bar0->adminq_event_counter); head =3D priv->adminq_prod_cnt; - if (tail !=3D head) - // This is not a valid path - return -EINVAL; + if (tail !=3D head) { + err =3D -EINVAL; + goto out; + } =20 err =3D gve_adminq_issue_cmd(priv, cmd_orig); if (err) - return err; + goto out; =20 - return gve_adminq_kick_and_wait(priv); + err =3D gve_adminq_kick_and_wait(priv); + +out: + mutex_unlock(&priv->adminq_lock); + return err; } =20 /* The device specifies that the management vector can either be the first= irq --=20 2.45.0.rc1.225.g2a3ae87e7f-goog From nobody Wed Dec 17 05:49:26 2025 Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F2C8885C5E for ; Tue, 7 May 2024 23:00:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715122834; cv=none; b=QWyMunsqdpS3LiZ2RZ1vVbcKifoO1kTxQ6W6TSrL0BqTBZNRHRqAQ4OXIivWfMsLBwu1oivcrJ0aRlfk0SgezUH2lK7xz7r0Jv/jXgjMnX2o2DB3Fy/+6pm5QtdM2EjdF2E07VbYfE+QfJSg0wE4CYS3JsAcjwvaomDTYPDzDdY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715122834; c=relaxed/simple; bh=4GCwDhq0fPItr6iYwK0LdmqEMJVYlgfpwBJg6tQSq7c=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=oV/f4833pP5YXXhVaD+SEk26+ZfYNe0ndO2sNhvbKfOub/A3tnnmdARHUK5RraXTk0oCxmWUOZQsXSPqCXMumKyIwF2liLGfEIcbtliCnfsHz5IaeUGqbrbc/lH/BEWzbnGfgTYL3mHvzMRtXGQnApd9vseZ8ydGjvyAjHd/DA0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ziweixiao.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=OxyJ8Fzq; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ziweixiao.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="OxyJ8Fzq" Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-61beaa137acso66163877b3.1 for ; Tue, 07 May 2024 16:00:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1715122832; x=1715727632; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=ErWdw272D2abXD7knyfrLRMhZXYPy233zUsfO32sbtE=; b=OxyJ8FzqKY5riQ9pEU7EsEVZjoOcO7KEhP/cRbmegkxxGqxA32vUhMc7XDtyCprOu4 mZB4hRYYUjXKI74ZYJEoCVZtqrz3CH/35MSux2JJJgFHEzHxmBUzluxrRAD8Yah0PA+m itoq/0s7RmxhJK4xPUHzCqIlzcF0ZJ6TIOZEJyOxKY7WsaLE9uQyPB7d5u3IPjwdG7p6 Pbx45qx2KlkkXUqi88iXDag3UHDy0d67ce/ckVpL9z1BLEx2bLkvLbUs4GQ97wy5snw8 jZ2YGhL8VfhkmBUggcRUg94KI4MUR0bgaljgkY2IieFiQuHg62lgADwVOzuuv7oupsjw KlQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715122832; x=1715727632; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ErWdw272D2abXD7knyfrLRMhZXYPy233zUsfO32sbtE=; b=OPa8cH5RYTVHLeKwH05q7e//F/KRCefp+YPOYbP2FwxANT56dQVlvcfncB1XqDbxZE fHfmqlFzdjnD3hIY8EdAx0ofCbt+GFHantMOcAYYLEAJ4eGDjAA49esjyorzBidO72yp a18FrDRhuW+e8bh9kdDE6oxYhFQIafQ2bOeZgdEuWzYZzb2LxpRP7BRyoDU3tlQ7JLaF 5mbhBSjWb33SERjDPL2GtsYGhZmU4gw5FJKuxwbh5DZCYufu9gyP33QY8sVhYINwp7Ca Qnjka8TwgP43lXN2SNvS4i1Iy8jFuDxXsAVPqMhORg0t/yzEt5C2U6WQf2kSA6rd9dc+ zIdA== X-Forwarded-Encrypted: i=1; AJvYcCU1H3GR/i+5mi0mUWSXhmptpWriy7GiyQAW0V9/O2RoTin4qAAp8ROd3/wVqujAMphrOeGLW2mcAvu8dL7MQjT2UTi9/jyyYBAhk+99 X-Gm-Message-State: AOJu0Yw4HWDMidoR9i0joPlcN/N/0s9DdSYFNMk7GCJXERLZ2b+SeXqY 2+2Fnmx34yy+3EY734iqkjzmcR3Ia3+RItRnacCM2xk1HDU5xLrLJurPdgCfgYhWHH1F2lNY7Rg POjUbT2yzh15JAw== X-Google-Smtp-Source: AGHT+IEggfQhoLsdVcLfNYlFhswJseZ60oKy2nS2WXx4mrxJPjXzGjrzNT06tYAu70qlMFjDc+7qBXDMHdN3Af4= X-Received: from ziwei-gti.c.googlers.com ([fda3:e722:ac3:cc00:20:ed76:c0a8:9b0]) (user=ziweixiao job=sendgmr) by 2002:a0d:cb09:0:b0:61b:982:4da0 with SMTP id 00721157ae682-6208582b694mr2513617b3.0.1715122831995; Tue, 07 May 2024 16:00:31 -0700 (PDT) Date: Tue, 7 May 2024 22:59:42 +0000 In-Reply-To: <20240507225945.1408516-1-ziweixiao@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240507225945.1408516-1-ziweixiao@google.com> X-Mailer: git-send-email 2.45.0.rc1.225.g2a3ae87e7f-goog Message-ID: <20240507225945.1408516-3-ziweixiao@google.com> Subject: [PATCH net-next 2/5] gve: Add adminq extended command From: Ziwei Xiao To: netdev@vger.kernel.org Cc: jeroendb@google.com, pkaligineedi@google.com, shailend@google.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, willemb@google.com, hramamurthy@google.com, rushilg@google.com, ziweixiao@google.com, jfraker@google.com, linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Jeroen de Borst The adminq command is limited to 64 bytes per entry and it's 56 bytes for the command itself at maximum. To support larger commands, we need to dma_alloc a separate memory to put the command in that memory and send the dma memory address instead of the actual command. This change introduces an extended adminq command to wrap the real command with the inner opcode and the allocated dma memory address specified. Once the device receives it, it can get the real command from the given dma memory address. As designed with the device, all the extended commands will use inner opcode larger than 0xFF. Signed-off-by: Jeroen de Borst Co-developed-by: Ziwei Xiao Signed-off-by: Ziwei Xiao Reviewed-by: Praveen Kaligineedi Reviewed-by: Harshitha Ramamurthy Reviewed-by: Willem de Bruijn --- drivers/net/ethernet/google/gve/gve_adminq.c | 31 ++++++++++++++++++++ drivers/net/ethernet/google/gve/gve_adminq.h | 12 ++++++++ 2 files changed, 43 insertions(+) diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/eth= ernet/google/gve/gve_adminq.c index 2c3ec5c3b114..514641b3ccc7 100644 --- a/drivers/net/ethernet/google/gve/gve_adminq.c +++ b/drivers/net/ethernet/google/gve/gve_adminq.c @@ -461,6 +461,8 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv, =20 memcpy(cmd, cmd_orig, sizeof(*cmd_orig)); opcode =3D be32_to_cpu(READ_ONCE(cmd->opcode)); + if (opcode =3D=3D GVE_ADMINQ_EXTENDED_COMMAND) + opcode =3D be32_to_cpu(cmd->extended_command.inner_opcode); =20 switch (opcode) { case GVE_ADMINQ_DESCRIBE_DEVICE: @@ -537,6 +539,35 @@ static int gve_adminq_execute_cmd(struct gve_priv *pri= v, return err; } =20 +static int gve_adminq_execute_extended_cmd(struct gve_priv *priv, u32 opco= de, + size_t cmd_size, void *cmd_orig) +{ + union gve_adminq_command cmd; + dma_addr_t inner_cmd_bus; + void *inner_cmd; + int err; + + inner_cmd =3D dma_alloc_coherent(&priv->pdev->dev, cmd_size, + &inner_cmd_bus, GFP_KERNEL); + if (!inner_cmd) + return -ENOMEM; + + memcpy(inner_cmd, cmd_orig, cmd_size); + + memset(&cmd, 0, sizeof(cmd)); + cmd.opcode =3D cpu_to_be32(GVE_ADMINQ_EXTENDED_COMMAND); + cmd.extended_command =3D (struct gve_adminq_extended_command) { + .inner_opcode =3D cpu_to_be32(opcode), + .inner_length =3D cpu_to_be32(cmd_size), + .inner_command_addr =3D cpu_to_be64(inner_cmd_bus), + }; + + err =3D gve_adminq_execute_cmd(priv, &cmd); + + dma_free_coherent(&priv->pdev->dev, cmd_size, inner_cmd, inner_cmd_bus); + return err; +} + /* The device specifies that the management vector can either be the first= irq * or the last irq. ntfy_blk_msix_base_idx indicates the first irq assigne= d to * the ntfy blks. It if is 0 then the management vector is last, if it is = 1 then diff --git a/drivers/net/ethernet/google/gve/gve_adminq.h b/drivers/net/eth= ernet/google/gve/gve_adminq.h index e64f0dbe744d..e0370ace8397 100644 --- a/drivers/net/ethernet/google/gve/gve_adminq.h +++ b/drivers/net/ethernet/google/gve/gve_adminq.h @@ -25,6 +25,9 @@ enum gve_adminq_opcodes { GVE_ADMINQ_REPORT_LINK_SPEED =3D 0xD, GVE_ADMINQ_GET_PTYPE_MAP =3D 0xE, GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY =3D 0xF, + + /* For commands that are larger than 56 bytes */ + GVE_ADMINQ_EXTENDED_COMMAND =3D 0xFF, }; =20 /* Admin queue status codes */ @@ -208,6 +211,14 @@ enum gve_driver_capbility { #define GVE_DRIVER_CAPABILITY_FLAGS3 0x0 #define GVE_DRIVER_CAPABILITY_FLAGS4 0x0 =20 +struct gve_adminq_extended_command { + __be32 inner_opcode; + __be32 inner_length; + __be64 inner_command_addr; +}; + +static_assert(sizeof(struct gve_adminq_extended_command) =3D=3D 16); + struct gve_driver_info { u8 os_type; /* 0x01 =3D Linux */ u8 driver_major; @@ -432,6 +443,7 @@ union gve_adminq_command { struct gve_adminq_get_ptype_map get_ptype_map; struct gve_adminq_verify_driver_compatibility verify_driver_compatibility; + struct gve_adminq_extended_command extended_command; }; }; u8 reserved[64]; --=20 2.45.0.rc1.225.g2a3ae87e7f-goog From nobody Wed Dec 17 05:49:26 2025 Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7F84F137C42 for ; Tue, 7 May 2024 23:00:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715122841; cv=none; b=qXWTjfGWeK4rNsoDoOuVuNg8GcSpPKB3pLR3q1cf2zSyxOCC5ciUhTpv6tfT9dnh/GV+jCx/8OLS+Cm5yvUETQtq0KtBm82IeV80vuwEvlCkH1nQGitQjmQ0AN2OalRcIzsmLG4Ejp15qzkls56549CB5DRLDmMzfnNI6vR6qWk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715122841; c=relaxed/simple; bh=KeZsDpfjg4fkDLKYyRjiHJ3K9hAB8B5iQZNvvFpcmuY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=urmp4fXyG/lrVfUBIBKUdJs0MhRtSXIafnMEeoB+GhUeLOWFCEVtiFA7OWYri6Bd5kumnUW+43Przz9WaoDgc/lhuqzqXm2345LQnsWi0wjXkUEHTvsvHVKVVkKeIdqMvbK31qjJkk5h1lEhGP4zlvFUF8cxLVyo8c810ND4NxQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ziweixiao.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=apkpJ7bh; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ziweixiao.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="apkpJ7bh" Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-61be452c62bso62513897b3.2 for ; Tue, 07 May 2024 16:00:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1715122838; x=1715727638; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=NXnPdU94aA87037a+0BxFlWOvSqs9PYhPyi24QbUuRY=; b=apkpJ7bhPGzkY87rVcN/lpNo1rNhlVA19qkVxWiptsph7CFq/Yk5EE/wfLTEIYNMkh Uf/0qekupgT0JTENSpXxdcC+QICCjQ1ciuicPO8N3Hw4Rg1rKQdbxfAtx3RmaPtgRk+S Fh1gVTNPp2Lq+7G9Hr3IVRkaH5dkmfLxzzAPNupKNAVMtLq2miHwJakAWQd6tDXLfdaN QIQsVqRounpnKoTxSOYARHgtd191pJdu+qK3Pqjxl4iDecNFJ+zNpgy8+TBRrGElS/4u AasBLxY7bkAGb2m7h/RJj+JH3Ji0jq5gaIncdX6PpScf4Rj6TRsWgYKXorE1otY8jYnZ JRiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715122838; x=1715727638; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=NXnPdU94aA87037a+0BxFlWOvSqs9PYhPyi24QbUuRY=; b=RIaECL7gpcJ5sjQbaJ1e/rNL1rsdPhNZ1IGTYKSPaRgkT0vLErwNNFeknzpB4xEp0+ 0V41u8ISem3q2MHd2Ki5Roqef6CbKTv6a3kIXZbfiLThcRBUZ4C141fVRqkntIFaElRh f3w0Sec1Kz64arIDRrWJKto/oujU+vWtJSw33N/q3BYh5hGqGmWD0NDryFl1HX5Mc8lH TypPAgG7qbDW+7ZJ7hP7Q/FG0dR733OwZwrfuRm098FL+fVHDXaalAsBrjoYmOVu7Wuq LxV+3iOD5aRDPbEwdMstzA0J7mJoJGOBMnESm4FoRtORWl7hTTyb2/fJQrfgrerezChi qwhw== X-Forwarded-Encrypted: i=1; AJvYcCWwT0uFJH0Jbc+EpYnulWfF5zTTfq8juYE+thvqs9AYbHIQpa54S8kku5H228X47w38R4y+xe08/Nvdn/6MR7gBEu51q1w/1ofR4uMy X-Gm-Message-State: AOJu0YwA/5LX1ls6eewpFX1A8Ks9IrOglABJoXFZZN9ou8/A+7oegshf ujeBlQ2g+zDFIr1AUptO5pi+xL1/vhyLnxs3FK0wJOewzMP9cf+pxGzlUUvq1Zz73HyauByRt9C 3seUlQtCqTjFmQg== X-Google-Smtp-Source: AGHT+IGzCKQ58FIDrrek79xK7RMi6FEGG6enmakGDSgrqxx2MG5LqtgQktPivYcc2rX+1V0P7Y4exlKxHcHmtEM= X-Received: from ziwei-gti.c.googlers.com ([fda3:e722:ac3:cc00:20:ed76:c0a8:9b0]) (user=ziweixiao job=sendgmr) by 2002:a81:4e83:0:b0:61b:1d66:61c4 with SMTP id 00721157ae682-62085c83b68mr2735537b3.10.1715122838443; Tue, 07 May 2024 16:00:38 -0700 (PDT) Date: Tue, 7 May 2024 22:59:43 +0000 In-Reply-To: <20240507225945.1408516-1-ziweixiao@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240507225945.1408516-1-ziweixiao@google.com> X-Mailer: git-send-email 2.45.0.rc1.225.g2a3ae87e7f-goog Message-ID: <20240507225945.1408516-4-ziweixiao@google.com> Subject: [PATCH net-next 3/5] gve: Add flow steering device option From: Ziwei Xiao To: netdev@vger.kernel.org Cc: jeroendb@google.com, pkaligineedi@google.com, shailend@google.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, willemb@google.com, hramamurthy@google.com, rushilg@google.com, ziweixiao@google.com, jfraker@google.com, linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Jeroen de Borst Add a new device option to signal to the driver that the device supports flow steering. This device option also carries the maximum number of flow steering rules that the device can store. Signed-off-by: Jeroen de Borst Co-developed-by: Ziwei Xiao Signed-off-by: Ziwei Xiao Reviewed-by: Praveen Kaligineedi Reviewed-by: Harshitha Ramamurthy Reviewed-by: Willem de Bruijn --- drivers/net/ethernet/google/gve/gve.h | 2 + drivers/net/ethernet/google/gve/gve_adminq.c | 42 ++++++++++++++++++-- drivers/net/ethernet/google/gve/gve_adminq.h | 11 +++++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/g= oogle/gve/gve.h index ca7fce17f2c0..58213c15e084 100644 --- a/drivers/net/ethernet/google/gve/gve.h +++ b/drivers/net/ethernet/google/gve/gve.h @@ -786,6 +786,8 @@ struct gve_priv { =20 u16 header_buf_size; /* device configured, header-split supported if non-= zero */ bool header_split_enabled; /* True if the header split is enabled by the = user */ + + u32 max_flow_rules; }; =20 enum gve_service_task_flags_bit { diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/eth= ernet/google/gve/gve_adminq.c index 514641b3ccc7..85d0d742ad21 100644 --- a/drivers/net/ethernet/google/gve/gve_adminq.c +++ b/drivers/net/ethernet/google/gve/gve_adminq.c @@ -44,6 +44,7 @@ void gve_parse_device_option(struct gve_priv *priv, struct gve_device_option_jumbo_frames **dev_op_jumbo_frames, struct gve_device_option_dqo_qpl **dev_op_dqo_qpl, struct gve_device_option_buffer_sizes **dev_op_buffer_sizes, + struct gve_device_option_flow_steering **dev_op_flow_steering, struct gve_device_option_modify_ring **dev_op_modify_ring) { u32 req_feat_mask =3D be32_to_cpu(option->required_features_mask); @@ -189,6 +190,23 @@ void gve_parse_device_option(struct gve_priv *priv, if (option_length =3D=3D GVE_DEVICE_OPTION_NO_MIN_RING_SIZE) priv->default_min_ring_size =3D true; break; + case GVE_DEV_OPT_ID_FLOW_STEERING: + if (option_length < sizeof(**dev_op_flow_steering) || + req_feat_mask !=3D GVE_DEV_OPT_REQ_FEAT_MASK_FLOW_STEERING) { + dev_warn(&priv->pdev->dev, GVE_DEVICE_OPTION_ERROR_FMT, + "Flow Steering", + (int)sizeof(**dev_op_flow_steering), + GVE_DEV_OPT_REQ_FEAT_MASK_FLOW_STEERING, + option_length, req_feat_mask); + break; + } + + if (option_length > sizeof(**dev_op_flow_steering)) + dev_warn(&priv->pdev->dev, + GVE_DEVICE_OPTION_TOO_BIG_FMT, + "Flow Steering"); + *dev_op_flow_steering =3D (void *)(option + 1); + break; default: /* If we don't recognize the option just continue * without doing anything. @@ -208,6 +226,7 @@ gve_process_device_options(struct gve_priv *priv, struct gve_device_option_jumbo_frames **dev_op_jumbo_frames, struct gve_device_option_dqo_qpl **dev_op_dqo_qpl, struct gve_device_option_buffer_sizes **dev_op_buffer_sizes, + struct gve_device_option_flow_steering **dev_op_flow_steering, struct gve_device_option_modify_ring **dev_op_modify_ring) { const int num_options =3D be16_to_cpu(descriptor->num_device_options); @@ -230,7 +249,7 @@ gve_process_device_options(struct gve_priv *priv, dev_op_gqi_rda, dev_op_gqi_qpl, dev_op_dqo_rda, dev_op_jumbo_frames, dev_op_dqo_qpl, dev_op_buffer_sizes, - dev_op_modify_ring); + dev_op_flow_steering, dev_op_modify_ring); dev_opt =3D next_opt; } =20 @@ -838,6 +857,8 @@ static void gve_enable_supported_features(struct gve_pr= iv *priv, *dev_op_dqo_qpl, const struct gve_device_option_buffer_sizes *dev_op_buffer_sizes, + const struct gve_device_option_flow_steering + *dev_op_flow_steering, const struct gve_device_option_modify_ring *dev_op_modify_ring) { @@ -890,10 +911,22 @@ static void gve_enable_supported_features(struct gve_= priv *priv, priv->min_tx_desc_cnt =3D be16_to_cpu(dev_op_modify_ring->min_tx_ring_s= ize); } } + + if (dev_op_flow_steering && + (supported_features_mask & GVE_SUP_FLOW_STEERING_MASK)) { + if (dev_op_flow_steering->max_flow_rules) { + priv->max_flow_rules =3D + be32_to_cpu(dev_op_flow_steering->max_flow_rules); + dev_info(&priv->pdev->dev, + "FLOW STEERING device option enabled with max rule limit of %u.\n", + priv->max_flow_rules); + } + } } =20 int gve_adminq_describe_device(struct gve_priv *priv) { + struct gve_device_option_flow_steering *dev_op_flow_steering =3D NULL; struct gve_device_option_buffer_sizes *dev_op_buffer_sizes =3D NULL; struct gve_device_option_jumbo_frames *dev_op_jumbo_frames =3D NULL; struct gve_device_option_modify_ring *dev_op_modify_ring =3D NULL; @@ -930,6 +963,7 @@ int gve_adminq_describe_device(struct gve_priv *priv) &dev_op_gqi_qpl, &dev_op_dqo_rda, &dev_op_jumbo_frames, &dev_op_dqo_qpl, &dev_op_buffer_sizes, + &dev_op_flow_steering, &dev_op_modify_ring); if (err) goto free_device_descriptor; @@ -969,9 +1003,8 @@ int gve_adminq_describe_device(struct gve_priv *priv) /* set default descriptor counts */ gve_set_default_desc_cnt(priv, descriptor); =20 - /* DQO supports LRO. */ if (!gve_is_gqi(priv)) - priv->dev->hw_features |=3D NETIF_F_LRO; + priv->dev->hw_features |=3D NETIF_F_LRO | NETIF_F_NTUPLE; =20 priv->max_registered_pages =3D be64_to_cpu(descriptor->max_registered_pages); @@ -991,7 +1024,8 @@ int gve_adminq_describe_device(struct gve_priv *priv) =20 gve_enable_supported_features(priv, supported_features_mask, dev_op_jumbo_frames, dev_op_dqo_qpl, - dev_op_buffer_sizes, dev_op_modify_ring); + dev_op_buffer_sizes, dev_op_flow_steering, + dev_op_modify_ring); =20 free_device_descriptor: dma_pool_free(priv->adminq_pool, descriptor, descriptor_bus); diff --git a/drivers/net/ethernet/google/gve/gve_adminq.h b/drivers/net/eth= ernet/google/gve/gve_adminq.h index e0370ace8397..e64a0e72e781 100644 --- a/drivers/net/ethernet/google/gve/gve_adminq.h +++ b/drivers/net/ethernet/google/gve/gve_adminq.h @@ -146,6 +146,14 @@ struct gve_device_option_modify_ring { =20 static_assert(sizeof(struct gve_device_option_modify_ring) =3D=3D 12); =20 +struct gve_device_option_flow_steering { + __be32 supported_features_mask; + __be32 reserved; + __be32 max_flow_rules; +}; + +static_assert(sizeof(struct gve_device_option_flow_steering) =3D=3D 12); + /* Terminology: * * RDA - Raw DMA Addressing - Buffers associated with SKBs are directly DMA @@ -163,6 +171,7 @@ enum gve_dev_opt_id { GVE_DEV_OPT_ID_DQO_QPL =3D 0x7, GVE_DEV_OPT_ID_JUMBO_FRAMES =3D 0x8, GVE_DEV_OPT_ID_BUFFER_SIZES =3D 0xa, + GVE_DEV_OPT_ID_FLOW_STEERING =3D 0xb, }; =20 enum gve_dev_opt_req_feat_mask { @@ -174,12 +183,14 @@ enum gve_dev_opt_req_feat_mask { GVE_DEV_OPT_REQ_FEAT_MASK_DQO_QPL =3D 0x0, GVE_DEV_OPT_REQ_FEAT_MASK_BUFFER_SIZES =3D 0x0, GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING =3D 0x0, + GVE_DEV_OPT_REQ_FEAT_MASK_FLOW_STEERING =3D 0x0, }; =20 enum gve_sup_feature_mask { GVE_SUP_MODIFY_RING_MASK =3D 1 << 0, GVE_SUP_JUMBO_FRAMES_MASK =3D 1 << 2, GVE_SUP_BUFFER_SIZES_MASK =3D 1 << 4, + GVE_SUP_FLOW_STEERING_MASK =3D 1 << 5, }; =20 #define GVE_DEV_OPT_LEN_GQI_RAW_ADDRESSING 0x0 --=20 2.45.0.rc1.225.g2a3ae87e7f-goog From nobody Wed Dec 17 05:49:26 2025 Received: from mail-yb1-f201.google.com (mail-yb1-f201.google.com [209.85.219.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5D8A31384B0 for ; Tue, 7 May 2024 23:00:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715122844; cv=none; b=jyQiAW55PPGP4jocHIscMnMXX9uETKceWEdYlcYLq/iPVOvS2XMkYrb0cPVql70DhAMdcaItqwWMlq5nR+h76GFdjmitkKIvTpu+UXKkRo1eyCPp2XUqtjZdJQDx4JbKp2mnxpYsmIK4UAUbxc7oEiy6IOJC402kDxZ77vKt7u0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715122844; c=relaxed/simple; bh=JLPKU3EH/zSXA5c+t0cinM/Kw6dJpy571zWZmiFAGaE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=VTlGtXMhc+4o1L4EnFS2zdzODvA4eY3t9J6W5n9F/Eu+ak381uZV2brsoIunjRuzY1KLvwyl6+kBuFfudxN6YTAIvSL5QJAvWu3ZuSnxebvSxIomU07IUdREBWolKJ52/VP0aZ4E2gA4Y/sbWy2mHrMnGuG2rO3vGocsS3tPCx4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ziweixiao.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=fnoVhrIF; arc=none smtp.client-ip=209.85.219.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ziweixiao.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="fnoVhrIF" Received: by mail-yb1-f201.google.com with SMTP id 3f1490d57ef6-dc647f65573so8562363276.2 for ; Tue, 07 May 2024 16:00:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1715122841; x=1715727641; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=qa2ApDp7sVX41tA/h7tpdOf/xWuhHAxpVZhJwgu98LM=; b=fnoVhrIFi7YOxuIRJFXWIV0GUs+FL9Hjmi3v8a4vjddg3rSw6hgMTpclhTl15cEXlP 8UkYnMy2zItVSKgmuBMXmMyoDi+byDlatgQo0CfgF4nXjhtAShLdQUiVtJ3OvYItSWrm K53tU1ZiGgCIKGgKN+Y/8tZQlzuieSHqoAWuozGWtJFJUfvCRCd5J0k+EC48ySkrjHpC La9CwhX5oElSJCelWeaGusVGrY+KpfwHubuvGKYsfbMUJ7Ojv1Q7sxRJJbE0gt2uwyXm l3GJ6Iu7ktSkN85jxPZWZ+k58O/MyKonK8JeLPv2Ffr7SiZx16qPMFPGBtdKXy82HkV2 X/XA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715122841; x=1715727641; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=qa2ApDp7sVX41tA/h7tpdOf/xWuhHAxpVZhJwgu98LM=; b=U5vv0Oejaox4jqSJCCMLzEOtxFoytPO9YdZ9PnHN3ngH3JcaPBRsYSBPD81B+xkJ0H GWR5LdTwE4G/YvYHvVreAgrm/jeeC3as/T2zLvuk2Cs85+nl2kUSt0TytWpPklSP26VQ pvkx4F0cVavUAwepYbbViObT3ZHUDlSSYEPu5xSgXxPJMeamKSofF0wZeZfeq4W3tq1K SkUHGepE9mqI9x6YOv+TfN8pY8KQXenXPeH+lGnRbx6soTzaJvtqVyqtYbyB5tdPsbJv 2cI4K3t96cIvMq3mwAt+mnZUoU6LrTJumvbjG8Ax8RsTgDD3eaL5f8gPl071NltX4ZJf EuzQ== X-Forwarded-Encrypted: i=1; AJvYcCWcINS+q+6FmxDkL94vakS+EXZC8idmX3AsmnrGrIQ6/6jLlbbei2TlRSYEh474XxhkwDx6lGtcHXRiuex1P53nDI8VcJJLz8LwD7dm X-Gm-Message-State: AOJu0YzW+Lstc31w+K8SAT/wHfKLKvChRi5QAS4zzD1yC29EYZrKOLvx jPhaOMqFVgZumYQjU5UlM8UPbR7yoNYunKJhI4y2TI0YGPsw6jRjH8rIuw0iZNyJzGqs6RLPig1 McU1YSnaC4qMyLw== X-Google-Smtp-Source: AGHT+IG4mbx+sPYWksZdERanNBVV7jTJLnyyyKn8o+0v4mI8n+WFlIIQIQQjZT7dbMRUS7Yks9kUnhumrh8/caQ= X-Received: from ziwei-gti.c.googlers.com ([fda3:e722:ac3:cc00:20:ed76:c0a8:9b0]) (user=ziweixiao job=sendgmr) by 2002:a05:6902:1542:b0:dc6:fec4:1c26 with SMTP id 3f1490d57ef6-debb9d6f419mr308053276.1.1715122841379; Tue, 07 May 2024 16:00:41 -0700 (PDT) Date: Tue, 7 May 2024 22:59:44 +0000 In-Reply-To: <20240507225945.1408516-1-ziweixiao@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240507225945.1408516-1-ziweixiao@google.com> X-Mailer: git-send-email 2.45.0.rc1.225.g2a3ae87e7f-goog Message-ID: <20240507225945.1408516-5-ziweixiao@google.com> Subject: [PATCH net-next 4/5] gve: Add flow steering adminq commands From: Ziwei Xiao To: netdev@vger.kernel.org Cc: jeroendb@google.com, pkaligineedi@google.com, shailend@google.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, willemb@google.com, hramamurthy@google.com, rushilg@google.com, ziweixiao@google.com, jfraker@google.com, linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Jeroen de Borst Adding new adminq commands for the driver to configure and query flow rules that are stored in the device. Flow steering rules are assigned with a location that determines the relative order of the rules. Flow rules can run up to an order of millions. In such cases, storing a full copy of the rules in the driver to prepare for the ethtool query is infeasible while querying them from the device is better. That needs to be optimized too so that we don't send a lot of adminq commands. The solution here is to store a limited number of rules/rule ids in the driver in a cache. This patch uses dma_pool to allocate 4k bytes which lets device write at most 46 flow rules(4k/88) or 1k rule ids(4096/4) at a time. For configuring flow rules, there are 3 sub-commands: - ADD which adds a rule at the location supplied - DEL which deletes the rule at the location supplied - RESET which clears all currently active rules in the device For querying flow rules, there are also 3 sub-commands: - QUERY_RULES corresponds to ETHTOOL_GRXCLSRULE. It fills the rules in the allocated cache after querying the device - QUERY_RULES_IDS corresponds to ETHTOOL_GRXCLSRLALL. It fills the rule_ids in the allocated cache after querying the device - QUERY_RULES_STATS corresponds to ETHTOOL_GRXCLSRLCNT. It queries the device's current flow rule number and the supported max flow rule limit Signed-off-by: Jeroen de Borst Co-developed-by: Ziwei Xiao Signed-off-by: Ziwei Xiao Reviewed-by: Praveen Kaligineedi Reviewed-by: Harshitha Ramamurthy Reviewed-by: Willem de Bruijn --- drivers/net/ethernet/google/gve/gve.h | 42 ++++++ drivers/net/ethernet/google/gve/gve_adminq.c | 133 ++++++++++++++++++ drivers/net/ethernet/google/gve/gve_adminq.h | 75 ++++++++++ drivers/net/ethernet/google/gve/gve_ethtool.c | 5 +- drivers/net/ethernet/google/gve/gve_main.c | 54 ++++++- 5 files changed, 307 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/g= oogle/gve/gve.h index 58213c15e084..355ae797eacf 100644 --- a/drivers/net/ethernet/google/gve/gve.h +++ b/drivers/net/ethernet/google/gve/gve.h @@ -60,6 +60,10 @@ =20 #define GVE_DEFAULT_RX_BUFFER_OFFSET 2048 =20 +#define GVE_FLOW_RULES_CACHE_SIZE (GVE_ADMINQ_BUFFER_SIZE / sizeof(struct = gve_flow_rule)) +#define GVE_FLOW_RULE_IDS_CACHE_SIZE \ + (GVE_ADMINQ_BUFFER_SIZE / sizeof(((struct gve_flow_rule *)0)->location)) + #define GVE_XDP_ACTIONS 5 =20 #define GVE_GQ_TX_MIN_PKT_DESC_BYTES 182 @@ -678,6 +682,39 @@ enum gve_queue_format { GVE_DQO_QPL_FORMAT =3D 0x4, }; =20 +struct gve_flow_spec { + __be32 src_ip[4]; + __be32 dst_ip[4]; + union { + struct { + __be16 src_port; + __be16 dst_port; + }; + __be32 spi; + }; + union { + u8 tos; + u8 tclass; + }; +}; + +struct gve_flow_rule { + u32 location; + u16 flow_type; + u16 action; + struct gve_flow_spec key; + struct gve_flow_spec mask; +}; + +struct gve_flow_rules_cache { + bool rules_cache_synced; /* False if the driver's rules_cache is outdated= */ + struct gve_flow_rule *rules_cache; + u32 *rule_ids_cache; + /* The total number of queried rules that stored in the caches */ + u32 rules_cache_num; + u32 rule_ids_cache_num; +}; + struct gve_priv { struct net_device *dev; struct gve_tx_ring *tx; /* array of tx_cfg.num_queues */ @@ -744,6 +781,8 @@ struct gve_priv { u32 adminq_report_link_speed_cnt; u32 adminq_get_ptype_map_cnt; u32 adminq_verify_driver_compatibility_cnt; + u32 adminq_query_flow_rules_cnt; + u32 adminq_cfg_flow_rule_cnt; =20 /* Global stats */ u32 interface_up_cnt; /* count of times interface turned up since last re= set */ @@ -788,6 +827,9 @@ struct gve_priv { bool header_split_enabled; /* True if the header split is enabled by the = user */ =20 u32 max_flow_rules; + u32 num_flow_rules; /* Current number of flow rules registered in the dev= ice */ + + struct gve_flow_rules_cache flow_rules_cache; }; =20 enum gve_service_task_flags_bit { diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/eth= ernet/google/gve/gve_adminq.c index 85d0d742ad21..7a929e20cf96 100644 --- a/drivers/net/ethernet/google/gve/gve_adminq.c +++ b/drivers/net/ethernet/google/gve/gve_adminq.c @@ -287,6 +287,8 @@ int gve_adminq_alloc(struct device *dev, struct gve_pri= v *priv) priv->adminq_report_stats_cnt =3D 0; priv->adminq_report_link_speed_cnt =3D 0; priv->adminq_get_ptype_map_cnt =3D 0; + priv->adminq_query_flow_rules_cnt =3D 0; + priv->adminq_cfg_flow_rule_cnt =3D 0; =20 /* Setup Admin queue with the device */ if (priv->pdev->revision < 0x1) { @@ -526,6 +528,12 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv, case GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY: priv->adminq_verify_driver_compatibility_cnt++; break; + case GVE_ADMINQ_QUERY_FLOW_RULES: + priv->adminq_query_flow_rules_cnt++; + break; + case GVE_ADMINQ_CONFIGURE_FLOW_RULE: + priv->adminq_cfg_flow_rule_cnt++; + break; default: dev_err(&priv->pdev->dev, "unknown AQ command opcode %d\n", opcode); } @@ -1188,3 +1196,128 @@ int gve_adminq_get_ptype_map_dqo(struct gve_priv *p= riv, ptype_map_bus); return err; } + +static int +gve_adminq_configure_flow_rule(struct gve_priv *priv, + struct gve_adminq_configure_flow_rule *flow_rule_cmd) +{ + int err =3D gve_adminq_execute_extended_cmd(priv, + GVE_ADMINQ_CONFIGURE_FLOW_RULE, + sizeof(struct gve_adminq_configure_flow_rule), + flow_rule_cmd); + + if (err) { + dev_err(&priv->pdev->dev, "Timeout to configure the flow rule, trigger r= eset"); + gve_reset(priv, true); + } else { + priv->flow_rules_cache.rules_cache_synced =3D false; + } + + return err; +} + +int gve_adminq_add_flow_rule(struct gve_priv *priv, struct gve_adminq_flow= _rule *rule, u32 loc) +{ + struct gve_adminq_configure_flow_rule flow_rule_cmd =3D { + .opcode =3D cpu_to_be16(GVE_RULE_ADD), + .location =3D cpu_to_be32(loc), + .rule =3D *rule, + }; + + return gve_adminq_configure_flow_rule(priv, &flow_rule_cmd); +} + +int gve_adminq_del_flow_rule(struct gve_priv *priv, u32 loc) +{ + struct gve_adminq_configure_flow_rule flow_rule_cmd =3D { + .opcode =3D cpu_to_be16(GVE_RULE_DEL), + .location =3D cpu_to_be32(loc), + }; + + return gve_adminq_configure_flow_rule(priv, &flow_rule_cmd); +} + +int gve_adminq_reset_flow_rules(struct gve_priv *priv) +{ + struct gve_adminq_configure_flow_rule flow_rule_cmd =3D { + .opcode =3D cpu_to_be16(GVE_RULE_RESET), + }; + + return gve_adminq_configure_flow_rule(priv, &flow_rule_cmd); +} + +/* In the dma memory that the driver allocated for the device to query the= flow rules, the device + * will first write it with a struct of gve_query_flow_rules_descriptor. N= ext to it, the device + * will write an array of rules or rule ids with the count that specified = in the descriptor. + * For GVE_FLOW_RULE_QUERY_STATS, the device will only write the descripto= r. + */ +static int gve_adminq_process_flow_rules_query(struct gve_priv *priv, u16 = query_opcode, + struct gve_query_flow_rules_descriptor *descriptor) +{ + struct gve_flow_rules_cache *flow_rules_cache =3D &priv->flow_rules_cache; + u32 num_queried_rules, total_memory_len, rule_info_len; + void *descriptor_end, *rule_info; + + total_memory_len =3D be32_to_cpu(descriptor->total_length); + if (total_memory_len > GVE_ADMINQ_BUFFER_SIZE) { + dev_err(&priv->dev->dev, "flow rules query is out of memory.\n"); + return -ENOMEM; + } + + num_queried_rules =3D be32_to_cpu(descriptor->num_queried_rules); + descriptor_end =3D (void *)descriptor + total_memory_len; + rule_info =3D (void *)(descriptor + 1); + + switch (query_opcode) { + case GVE_FLOW_RULE_QUERY_RULES: + rule_info_len =3D num_queried_rules * sizeof(*flow_rules_cache->rules_ca= che); + + memcpy(flow_rules_cache->rules_cache, rule_info, rule_info_len); + flow_rules_cache->rules_cache_num =3D num_queried_rules; + break; + case GVE_FLOW_RULE_QUERY_IDS: + rule_info_len =3D num_queried_rules * sizeof(*flow_rules_cache->rule_ids= _cache); + + memcpy(flow_rules_cache->rule_ids_cache, rule_info, rule_info_len); + flow_rules_cache->rule_ids_cache_num =3D num_queried_rules; + break; + case GVE_FLOW_RULE_QUERY_STATS: + priv->num_flow_rules =3D be32_to_cpu(descriptor->num_flow_rules); + priv->max_flow_rules =3D be32_to_cpu(descriptor->max_flow_rules); + return 0; + default: + return -EINVAL; + } + + return 0; +} + +int gve_adminq_query_flow_rules(struct gve_priv *priv, u16 query_opcode, u= 32 starting_loc) +{ + struct gve_query_flow_rules_descriptor *descriptor; + union gve_adminq_command cmd; + dma_addr_t descriptor_bus; + int err =3D 0; + + memset(&cmd, 0, sizeof(cmd)); + descriptor =3D dma_pool_alloc(priv->adminq_pool, GFP_KERNEL, &descriptor_= bus); + if (!descriptor) + return -ENOMEM; + + cmd.opcode =3D cpu_to_be32(GVE_ADMINQ_QUERY_FLOW_RULES); + cmd.query_flow_rules =3D (struct gve_adminq_query_flow_rules) { + .opcode =3D cpu_to_be16(query_opcode), + .starting_rule_id =3D cpu_to_be32(starting_loc), + .available_length =3D cpu_to_be64(GVE_ADMINQ_BUFFER_SIZE), + .rule_descriptor_addr =3D cpu_to_be64(descriptor_bus), + }; + err =3D gve_adminq_execute_cmd(priv, &cmd); + if (err) + goto out; + + err =3D gve_adminq_process_flow_rules_query(priv, query_opcode, descripto= r); + +out: + dma_pool_free(priv->adminq_pool, descriptor, descriptor_bus); + return err; +} diff --git a/drivers/net/ethernet/google/gve/gve_adminq.h b/drivers/net/eth= ernet/google/gve/gve_adminq.h index e64a0e72e781..9ddb72f92197 100644 --- a/drivers/net/ethernet/google/gve/gve_adminq.h +++ b/drivers/net/ethernet/google/gve/gve_adminq.h @@ -25,11 +25,21 @@ enum gve_adminq_opcodes { GVE_ADMINQ_REPORT_LINK_SPEED =3D 0xD, GVE_ADMINQ_GET_PTYPE_MAP =3D 0xE, GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY =3D 0xF, + GVE_ADMINQ_QUERY_FLOW_RULES =3D 0x10, =20 /* For commands that are larger than 56 bytes */ GVE_ADMINQ_EXTENDED_COMMAND =3D 0xFF, }; =20 +/* The normal adminq command is restricted to be 56 bytes at maximum. For = the + * longer adminq command, it is wrapped by GVE_ADMINQ_EXTENDED_COMMAND with + * inner opcode of gve_adminq_extended_cmd_opcodes specified. The inner co= mmand + * is written in the dma memory allocated by GVE_ADMINQ_EXTENDED_COMMAND. + */ +enum gve_adminq_extended_cmd_opcodes { + GVE_ADMINQ_CONFIGURE_FLOW_RULE =3D 0x101, +}; + /* Admin queue status codes */ enum gve_adminq_statuses { GVE_ADMINQ_COMMAND_UNSET =3D 0x0, @@ -434,6 +444,66 @@ struct gve_adminq_get_ptype_map { __be64 ptype_map_addr; }; =20 +/* Flow-steering related definitions */ +enum gve_adminq_flow_rule_cfg_opcode { + GVE_RULE_ADD =3D 0, + GVE_RULE_DEL =3D 1, + GVE_RULE_RESET =3D 2, +}; + +enum gve_adminq_flow_rule_query_opcode { + GVE_FLOW_RULE_QUERY_RULES =3D 0, + GVE_FLOW_RULE_QUERY_IDS =3D 1, + GVE_FLOW_RULE_QUERY_STATS =3D 2, +}; + +enum gve_adminq_flow_type { + GVE_FLOW_TYPE_TCPV4, + GVE_FLOW_TYPE_UDPV4, + GVE_FLOW_TYPE_SCTPV4, + GVE_FLOW_TYPE_AHV4, + GVE_FLOW_TYPE_ESPV4, + GVE_FLOW_TYPE_TCPV6, + GVE_FLOW_TYPE_UDPV6, + GVE_FLOW_TYPE_SCTPV6, + GVE_FLOW_TYPE_AHV6, + GVE_FLOW_TYPE_ESPV6, +}; + +/* Flow-steering command */ +struct gve_adminq_flow_rule { + __be16 flow_type; + __be16 action; /* RX queue id */ + struct gve_flow_spec key; + struct gve_flow_spec mask; +}; + +struct gve_adminq_configure_flow_rule { + __be16 opcode; + u8 padding[2]; + struct gve_adminq_flow_rule rule; + __be32 location; +}; + +static_assert(sizeof(struct gve_adminq_configure_flow_rule) =3D=3D 92); + +struct gve_query_flow_rules_descriptor { + __be32 num_flow_rules; /* Current rule counts stored in the device */ + __be32 max_flow_rules; + __be32 num_queried_rules; + __be32 total_length; /* The memory length that the device writes */ +}; + +struct gve_adminq_query_flow_rules { + __be16 opcode; + u8 padding[2]; + __be32 starting_rule_id; + __be64 available_length; /* The dma memory length that the driver allocat= ed */ + __be64 rule_descriptor_addr; /* The dma memory address */ +}; + +static_assert(sizeof(struct gve_adminq_query_flow_rules) =3D=3D 24); + union gve_adminq_command { struct { __be32 opcode; @@ -454,6 +524,7 @@ union gve_adminq_command { struct gve_adminq_get_ptype_map get_ptype_map; struct gve_adminq_verify_driver_compatibility verify_driver_compatibility; + struct gve_adminq_query_flow_rules query_flow_rules; struct gve_adminq_extended_command extended_command; }; }; @@ -488,6 +559,10 @@ int gve_adminq_verify_driver_compatibility(struct gve_= priv *priv, u64 driver_info_len, dma_addr_t driver_info_addr); int gve_adminq_report_link_speed(struct gve_priv *priv); +int gve_adminq_add_flow_rule(struct gve_priv *priv, struct gve_adminq_flow= _rule *rule, u32 loc); +int gve_adminq_del_flow_rule(struct gve_priv *priv, u32 loc); +int gve_adminq_reset_flow_rules(struct gve_priv *priv); +int gve_adminq_query_flow_rules(struct gve_priv *priv, u16 query_opcode, u= 32 starting_loc); =20 struct gve_ptype_lut; int gve_adminq_get_ptype_map_dqo(struct gve_priv *priv, diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/et= hernet/google/gve/gve_ethtool.c index 156b7e128b53..02cee7e0e229 100644 --- a/drivers/net/ethernet/google/gve/gve_ethtool.c +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c @@ -74,7 +74,8 @@ static const char gve_gstrings_adminq_stats[][ETH_GSTRING= _LEN] =3D { "adminq_create_tx_queue_cnt", "adminq_create_rx_queue_cnt", "adminq_destroy_tx_queue_cnt", "adminq_destroy_rx_queue_cnt", "adminq_dcfg_device_resources_cnt", "adminq_set_driver_parameter_cnt", - "adminq_report_stats_cnt", "adminq_report_link_speed_cnt", "adminq_get_pt= ype_map_cnt" + "adminq_report_stats_cnt", "adminq_report_link_speed_cnt", "adminq_get_pt= ype_map_cnt", + "adminq_query_flow_rules", "adminq_cfg_flow_rule", }; =20 static const char gve_gstrings_priv_flags[][ETH_GSTRING_LEN] =3D { @@ -458,6 +459,8 @@ gve_get_ethtool_stats(struct net_device *netdev, data[i++] =3D priv->adminq_report_stats_cnt; data[i++] =3D priv->adminq_report_link_speed_cnt; data[i++] =3D priv->adminq_get_ptype_map_cnt; + data[i++] =3D priv->adminq_query_flow_rules_cnt; + data[i++] =3D priv->adminq_cfg_flow_rule_cnt; } =20 static void gve_get_channels(struct net_device *netdev, diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ether= net/google/gve/gve_main.c index cabf7d4bcecb..eb435ccbe98e 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -141,6 +141,52 @@ static void gve_get_stats(struct net_device *dev, stru= ct rtnl_link_stats64 *s) } } =20 +static int gve_alloc_flow_rule_caches(struct gve_priv *priv) +{ + struct gve_flow_rules_cache *flow_rules_cache =3D &priv->flow_rules_cache; + int err =3D 0; + + if (!priv->max_flow_rules) + return 0; + + flow_rules_cache->rules_cache =3D + kvcalloc(GVE_FLOW_RULES_CACHE_SIZE, sizeof(*flow_rules_cache->rules_cach= e), + GFP_KERNEL); + if (!flow_rules_cache->rules_cache) { + dev_err(&priv->pdev->dev, "Cannot alloc flow rules cache\n"); + return -ENOMEM; + } + + flow_rules_cache->rule_ids_cache =3D + kvcalloc(GVE_FLOW_RULE_IDS_CACHE_SIZE, sizeof(*flow_rules_cache->rule_id= s_cache), + GFP_KERNEL); + if (!flow_rules_cache->rule_ids_cache) { + dev_err(&priv->pdev->dev, "Cannot alloc flow rule ids cache\n"); + err =3D -ENOMEM; + goto free_rules_cache; + } + + return 0; + +free_rules_cache: + kvfree(flow_rules_cache->rules_cache); + flow_rules_cache->rules_cache =3D NULL; + return err; +} + +static void gve_free_flow_rule_caches(struct gve_priv *priv) +{ + struct gve_flow_rules_cache *flow_rules_cache =3D &priv->flow_rules_cache; + + if (!priv->max_flow_rules) + return; + + kvfree(flow_rules_cache->rule_ids_cache); + flow_rules_cache->rule_ids_cache =3D NULL; + kvfree(flow_rules_cache->rules_cache); + flow_rules_cache->rules_cache =3D NULL; +} + static int gve_alloc_counter_array(struct gve_priv *priv) { priv->counter_array =3D @@ -521,9 +567,12 @@ static int gve_setup_device_resources(struct gve_priv = *priv) { int err; =20 - err =3D gve_alloc_counter_array(priv); + err =3D gve_alloc_flow_rule_caches(priv); if (err) return err; + err =3D gve_alloc_counter_array(priv); + if (err) + goto abort_with_flow_rule_caches; err =3D gve_alloc_notify_blocks(priv); if (err) goto abort_with_counter; @@ -575,6 +624,8 @@ static int gve_setup_device_resources(struct gve_priv *= priv) gve_free_notify_blocks(priv); abort_with_counter: gve_free_counter_array(priv); +abort_with_flow_rule_caches: + gve_free_flow_rule_caches(priv); =20 return err; } @@ -606,6 +657,7 @@ static void gve_teardown_device_resources(struct gve_pr= iv *priv) kvfree(priv->ptype_lut_dqo); priv->ptype_lut_dqo =3D NULL; =20 + gve_free_flow_rule_caches(priv); gve_free_counter_array(priv); gve_free_notify_blocks(priv); gve_free_stats_report(priv); --=20 2.45.0.rc1.225.g2a3ae87e7f-goog From nobody Wed Dec 17 05:49:26 2025 Received: from mail-yb1-f201.google.com (mail-yb1-f201.google.com [209.85.219.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C6235139CF3 for ; Tue, 7 May 2024 23:00:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715122847; cv=none; b=mLfPEN4DYawSTRkoCIHQd6m8001CE9Hpz8ZNDBC1MAd5sU/5xb3eMaQEebXxsmvGQH66hMtLOwGUu6G5olVko6iIWX/0uAlbydZ8fMKc52OJmdxxGR31UR9ukoQEDigKIAJGS4a4EDSyaLQCj8Dbv9TIWjVeVkpqYgdyB301mMU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715122847; c=relaxed/simple; bh=VJuGsdKOFSnR7yBmRXM9ZcoqmipHayyWCd2FXVdFIWI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=rYNULz314Da6Ci8FayBFYjZ2br1pg4rjtgSyU4bGuxZdPPz/ZXp0eqlPMbRn2blcCa049nXNZ71MeQhQogmIHirhYdnFpsi3g2iSjLHEBCm+simbqjOC0Q4l0EQ5OKRIgTBJL3nU0SVb27i3+wPWrNFdmuyvcq1WHctX4jAk3tQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ziweixiao.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=yR5iEoHd; arc=none smtp.client-ip=209.85.219.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ziweixiao.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="yR5iEoHd" Received: by mail-yb1-f201.google.com with SMTP id 3f1490d57ef6-de468af2b73so7569877276.0 for ; Tue, 07 May 2024 16:00:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1715122844; x=1715727644; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=jdBwK00+cUoOYOBMlsXTnW4ybuvzE5bAMQxEnP1MIVo=; b=yR5iEoHd2UVJUTTpBnN82kt3GYrfQrewZqc7oUh38/xi8wXDledVSLzvUV9umg8JL5 m4Zc6NyMkWEbqPqR4GmFTYzauL1Klu7uAkr1c19DUGoPHR5WHzEOHQqGEtxZd0pZD5RM 2jexlbceyPyoKMGTOxapKSq5/wv01avCg+acu8AYOdx8dhOnU0MtNkF+4QG75rO1IoON tuHo8LqCglWKwVhzFKTB9LeRhEYWboWFxvlGLMoUSqObwfJw+haD6fHlXOhe2TsRLVt+ 65n6n74Zo2XcmJZJp/QEENrfCENxerdzqe0arlHSn3UyQyoZw70hMynn/IUeXxTUmXE2 G1/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715122844; x=1715727644; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=jdBwK00+cUoOYOBMlsXTnW4ybuvzE5bAMQxEnP1MIVo=; b=kshBCRtaNFQa5HvvgIsJq5fguor/crkexJ+OECBHNXZyE8j7YBvzH2AALMzH01veE4 MRqkSmy7i+DToIjjX+520IZeQ3gZD3rEKG6RJatjdvO8N4EcZfGEy1tODCXhtE5hKPvy cieNn/VOBfrgynG37Q1PZD/Dz53OTd5ULnGBnP2lKF4nnZ27hdJ6rJKOXG8v+FLEZan2 PoyNnvuAQEMlXYuhBnXSu7RHn1jZciTdCtjhOIRlx3JvW2fr4t1pFypyhcx/qo2FqXFE tJC3M9gUJ85X0Ksep7o2USsrg85l+5fUvrYPKQqOTe3A1R1ciFr9HfFhX3LgpPJyTTl1 buog== X-Forwarded-Encrypted: i=1; AJvYcCVmeYIrlEeU+UGO0ER2PJDTCYmlPmS9XpkXbxKLytK60WmWdrfFdUp+F/0DteHiyQgyDq2Ey9cCNUHV5mcPCRdzGbhHKOhPLWjWyiCf X-Gm-Message-State: AOJu0Yxct5udg7QsLMgal7PX5REOv+c03G41SvnE+VFwEk3KjOgMZZvd BF+hk8tsvBaA7FABtanT3DCVXtFQQ7cGobRu9XycfMmKL/H82ISZTOTMy97KKZM7wODhHcD/Hab JFxIm9m138+NX1A== X-Google-Smtp-Source: AGHT+IEkRaFSj8NdmdvkaiQD562Zu5UVcyLLv01EspnNh3ZQpNGrqyyKuTxF7U0rANgCfYQ7UNMXE/YgdyfWeVA= X-Received: from ziwei-gti.c.googlers.com ([fda3:e722:ac3:cc00:20:ed76:c0a8:9b0]) (user=ziweixiao job=sendgmr) by 2002:a05:6902:18c1:b0:de4:77ab:5fea with SMTP id 3f1490d57ef6-debb9d6d8d6mr320623276.2.1715122843703; Tue, 07 May 2024 16:00:43 -0700 (PDT) Date: Tue, 7 May 2024 22:59:45 +0000 In-Reply-To: <20240507225945.1408516-1-ziweixiao@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240507225945.1408516-1-ziweixiao@google.com> X-Mailer: git-send-email 2.45.0.rc1.225.g2a3ae87e7f-goog Message-ID: <20240507225945.1408516-6-ziweixiao@google.com> Subject: [PATCH net-next 5/5] gve: Add flow steering ethtool support From: Ziwei Xiao To: netdev@vger.kernel.org Cc: jeroendb@google.com, pkaligineedi@google.com, shailend@google.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, willemb@google.com, hramamurthy@google.com, rushilg@google.com, ziweixiao@google.com, jfraker@google.com, linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Jeroen de Borst Implement the ethtool commands that can be used to configure and query flow-steering rules. For these ethtool commands, the driver will temporarily drop the rtnl lock to reduce the latency for the flow steering commands on separate NICs. It will then be protected by the new added adminq lock. A large part of this change consists of translating the ethtool representation of 'ntuples' to our internal gve_flow_rule and vice-versa in the new created gve_flow_rule.c Considering the possible large amount of flow rules, the driver doesn't store all the rules locally. When the user runs 'ethtool -n ' to check the registered rules, the driver will send adminq command to query a limited amount of rules/rule ids(that filled in a 4096 bytes dma memory) at a time as a cache for the ethtool queries. The adminq query commands will be repeated for several times until the ethtool has queried all the needed rules. Signed-off-by: Jeroen de Borst Co-developed-by: Ziwei Xiao Signed-off-by: Ziwei Xiao Reviewed-by: Praveen Kaligineedi Reviewed-by: Harshitha Ramamurthy Reviewed-by: Willem de Bruijn --- drivers/net/ethernet/google/gve/Makefile | 2 +- drivers/net/ethernet/google/gve/gve.h | 8 +- drivers/net/ethernet/google/gve/gve_ethtool.c | 86 ++++- .../net/ethernet/google/gve/gve_flow_rule.c | 296 ++++++++++++++++++ drivers/net/ethernet/google/gve/gve_main.c | 32 +- 5 files changed, 415 insertions(+), 9 deletions(-) create mode 100644 drivers/net/ethernet/google/gve/gve_flow_rule.c diff --git a/drivers/net/ethernet/google/gve/Makefile b/drivers/net/etherne= t/google/gve/Makefile index b9a6be76531b..9ed07080b38a 100644 --- a/drivers/net/ethernet/google/gve/Makefile +++ b/drivers/net/ethernet/google/gve/Makefile @@ -1,4 +1,4 @@ # Makefile for the Google virtual Ethernet (gve) driver =20 obj-$(CONFIG_GVE) +=3D gve.o -gve-objs :=3D gve_main.o gve_tx.o gve_tx_dqo.o gve_rx.o gve_rx_dqo.o gve_e= thtool.o gve_adminq.o gve_utils.o +gve-objs :=3D gve_main.o gve_tx.o gve_tx_dqo.o gve_rx.o gve_rx_dqo.o gve_e= thtool.o gve_adminq.o gve_utils.o gve_flow_rule.o diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/g= oogle/gve/gve.h index 355ae797eacf..8565f1df9c50 100644 --- a/drivers/net/ethernet/google/gve/gve.h +++ b/drivers/net/ethernet/google/gve/gve.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: (GPL-2.0 OR MIT) * Google virtual Ethernet (gve) driver * - * Copyright (C) 2015-2021 Google, Inc. + * Copyright (C) 2015-2024 Google LLC */ =20 #ifndef _GVE_H_ @@ -1169,6 +1169,12 @@ int gve_adjust_config(struct gve_priv *priv, int gve_adjust_queues(struct gve_priv *priv, struct gve_queue_config new_rx_config, struct gve_queue_config new_tx_config); +/* flow steering rule */ +int gve_get_flow_rule_entry(struct gve_priv *priv, struct ethtool_rxnfc *c= md); +int gve_get_flow_rule_ids(struct gve_priv *priv, struct ethtool_rxnfc *cmd= , u32 *rule_locs); +int gve_add_flow_rule(struct gve_priv *priv, struct ethtool_rxnfc *cmd); +int gve_del_flow_rule(struct gve_priv *priv, struct ethtool_rxnfc *cmd); +int gve_flow_rules_reset(struct gve_priv *priv); /* report stats handling */ void gve_handle_report_stats(struct gve_priv *priv); /* exported by ethtool.c */ diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/et= hernet/google/gve/gve_ethtool.c index 02cee7e0e229..27166bde5fa0 100644 --- a/drivers/net/ethernet/google/gve/gve_ethtool.c +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: (GPL-2.0 OR MIT) /* Google virtual Ethernet (gve) driver * - * Copyright (C) 2015-2021 Google, Inc. + * Copyright (C) 2015-2024 Google LLC */ =20 #include @@ -503,6 +503,12 @@ static int gve_set_channels(struct net_device *netdev, return -EINVAL; } =20 + if (old_settings.rx_count !=3D new_rx && priv->num_flow_rules) { + dev_err(&priv->pdev->dev, + "Changing number of RX queues is disabled when flow rules are active"); + return -EBUSY; + } + if (!netif_carrier_ok(netdev)) { priv->tx_cfg.num_queues =3D new_tx; priv->rx_cfg.num_queues =3D new_rx; @@ -783,6 +789,82 @@ static int gve_set_coalesce(struct net_device *netdev, return 0; } =20 +static int gve_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *= cmd) +{ + struct gve_priv *priv =3D netdev_priv(netdev); + int err =3D 0; + + if (!(netdev->features & NETIF_F_NTUPLE)) + return -EOPNOTSUPP; + + dev_hold(netdev); + rtnl_unlock(); + + switch (cmd->cmd) { + case ETHTOOL_SRXCLSRLINS: + err =3D gve_add_flow_rule(priv, cmd); + break; + case ETHTOOL_SRXCLSRLDEL: + err =3D gve_del_flow_rule(priv, cmd); + break; + case ETHTOOL_SRXFH: + err =3D -EOPNOTSUPP; + break; + default: + err =3D -EOPNOTSUPP; + break; + } + + rtnl_lock(); + dev_put(netdev); + return err; +} + +static int gve_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *= cmd, u32 *rule_locs) +{ + struct gve_priv *priv =3D netdev_priv(netdev); + int err =3D 0; + + dev_hold(netdev); + rtnl_unlock(); + + switch (cmd->cmd) { + case ETHTOOL_GRXRINGS: + cmd->data =3D priv->rx_cfg.num_queues; + break; + case ETHTOOL_GRXCLSRLCNT: + if (!priv->max_flow_rules) { + err =3D -EOPNOTSUPP; + goto out; + } + + err =3D gve_adminq_query_flow_rules(priv, GVE_FLOW_RULE_QUERY_STATS, 0); + if (err) + goto out; + + cmd->rule_cnt =3D priv->num_flow_rules; + cmd->data =3D priv->max_flow_rules; + break; + case ETHTOOL_GRXCLSRULE: + err =3D gve_get_flow_rule_entry(priv, cmd); + break; + case ETHTOOL_GRXCLSRLALL: + err =3D gve_get_flow_rule_ids(priv, cmd, (u32 *)rule_locs); + break; + case ETHTOOL_GRXFH: + err =3D -EOPNOTSUPP; + break; + default: + err =3D -EOPNOTSUPP; + break; + } + +out: + rtnl_lock(); + dev_put(netdev); + return err; +} + const struct ethtool_ops gve_ethtool_ops =3D { .supported_coalesce_params =3D ETHTOOL_COALESCE_USECS, .supported_ring_params =3D ETHTOOL_RING_USE_TCP_DATA_SPLIT, @@ -794,6 +876,8 @@ const struct ethtool_ops gve_ethtool_ops =3D { .get_msglevel =3D gve_get_msglevel, .set_channels =3D gve_set_channels, .get_channels =3D gve_get_channels, + .set_rxnfc =3D gve_set_rxnfc, + .get_rxnfc =3D gve_get_rxnfc, .get_link =3D ethtool_op_get_link, .get_coalesce =3D gve_get_coalesce, .set_coalesce =3D gve_set_coalesce, diff --git a/drivers/net/ethernet/google/gve/gve_flow_rule.c b/drivers/net/= ethernet/google/gve/gve_flow_rule.c new file mode 100644 index 000000000000..1cafd520f2db --- /dev/null +++ b/drivers/net/ethernet/google/gve/gve_flow_rule.c @@ -0,0 +1,296 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* Google virtual Ethernet (gve) driver + * + * Copyright (C) 2015-2024 Google LLC + */ + +#include "gve.h" +#include "gve_adminq.h" + +static +int gve_fill_ethtool_flow_spec(struct ethtool_rx_flow_spec *fsp, struct gv= e_flow_rule *rule) +{ + static const u16 flow_type_lut[] =3D { + [GVE_FLOW_TYPE_TCPV4] =3D TCP_V4_FLOW, + [GVE_FLOW_TYPE_UDPV4] =3D UDP_V4_FLOW, + [GVE_FLOW_TYPE_SCTPV4] =3D SCTP_V4_FLOW, + [GVE_FLOW_TYPE_AHV4] =3D AH_V4_FLOW, + [GVE_FLOW_TYPE_ESPV4] =3D ESP_V4_FLOW, + [GVE_FLOW_TYPE_TCPV6] =3D TCP_V6_FLOW, + [GVE_FLOW_TYPE_UDPV6] =3D UDP_V6_FLOW, + [GVE_FLOW_TYPE_SCTPV6] =3D SCTP_V6_FLOW, + [GVE_FLOW_TYPE_AHV6] =3D AH_V6_FLOW, + [GVE_FLOW_TYPE_ESPV6] =3D ESP_V6_FLOW, + }; + + if (be16_to_cpu(rule->flow_type) >=3D ARRAY_SIZE(flow_type_lut)) + return -EINVAL; + + fsp->flow_type =3D flow_type_lut[be16_to_cpu(rule->flow_type)]; + + memset(&fsp->h_u, 0, sizeof(fsp->h_u)); + memset(&fsp->h_ext, 0, sizeof(fsp->h_ext)); + memset(&fsp->m_u, 0, sizeof(fsp->m_u)); + memset(&fsp->m_ext, 0, sizeof(fsp->m_ext)); + + switch (fsp->flow_type) { + case TCP_V4_FLOW: + case UDP_V4_FLOW: + case SCTP_V4_FLOW: + fsp->h_u.tcp_ip4_spec.ip4src =3D rule->key.src_ip[0]; + fsp->h_u.tcp_ip4_spec.ip4dst =3D rule->key.dst_ip[0]; + fsp->h_u.tcp_ip4_spec.psrc =3D rule->key.src_port; + fsp->h_u.tcp_ip4_spec.pdst =3D rule->key.dst_port; + fsp->h_u.tcp_ip4_spec.tos =3D rule->key.tos; + fsp->m_u.tcp_ip4_spec.ip4src =3D rule->mask.src_ip[0]; + fsp->m_u.tcp_ip4_spec.ip4dst =3D rule->mask.dst_ip[0]; + fsp->m_u.tcp_ip4_spec.psrc =3D rule->mask.src_port; + fsp->m_u.tcp_ip4_spec.pdst =3D rule->mask.dst_port; + fsp->m_u.tcp_ip4_spec.tos =3D rule->mask.tos; + break; + case AH_V4_FLOW: + case ESP_V4_FLOW: + fsp->h_u.ah_ip4_spec.ip4src =3D rule->key.src_ip[0]; + fsp->h_u.ah_ip4_spec.ip4dst =3D rule->key.dst_ip[0]; + fsp->h_u.ah_ip4_spec.spi =3D rule->key.spi; + fsp->h_u.ah_ip4_spec.tos =3D rule->key.tos; + fsp->m_u.ah_ip4_spec.ip4src =3D rule->mask.src_ip[0]; + fsp->m_u.ah_ip4_spec.ip4dst =3D rule->mask.dst_ip[0]; + fsp->m_u.ah_ip4_spec.spi =3D rule->mask.spi; + fsp->m_u.ah_ip4_spec.tos =3D rule->mask.tos; + break; + case TCP_V6_FLOW: + case UDP_V6_FLOW: + case SCTP_V6_FLOW: + memcpy(fsp->h_u.tcp_ip6_spec.ip6src, &rule->key.src_ip, + sizeof(struct in6_addr)); + memcpy(fsp->h_u.tcp_ip6_spec.ip6dst, &rule->key.dst_ip, + sizeof(struct in6_addr)); + fsp->h_u.tcp_ip6_spec.psrc =3D rule->key.src_port; + fsp->h_u.tcp_ip6_spec.pdst =3D rule->key.dst_port; + fsp->h_u.tcp_ip6_spec.tclass =3D rule->key.tclass; + memcpy(fsp->m_u.tcp_ip6_spec.ip6src, &rule->mask.src_ip, + sizeof(struct in6_addr)); + memcpy(fsp->m_u.tcp_ip6_spec.ip6dst, &rule->mask.dst_ip, + sizeof(struct in6_addr)); + fsp->m_u.tcp_ip6_spec.psrc =3D rule->mask.src_port; + fsp->m_u.tcp_ip6_spec.pdst =3D rule->mask.dst_port; + fsp->m_u.tcp_ip6_spec.tclass =3D rule->mask.tclass; + break; + case AH_V6_FLOW: + case ESP_V6_FLOW: + memcpy(fsp->h_u.ah_ip6_spec.ip6src, &rule->key.src_ip, + sizeof(struct in6_addr)); + memcpy(fsp->h_u.ah_ip6_spec.ip6dst, &rule->key.dst_ip, + sizeof(struct in6_addr)); + fsp->h_u.ah_ip6_spec.spi =3D rule->key.spi; + fsp->h_u.ah_ip6_spec.tclass =3D rule->key.tclass; + memcpy(fsp->m_u.ah_ip6_spec.ip6src, &rule->mask.src_ip, + sizeof(struct in6_addr)); + memcpy(fsp->m_u.ah_ip6_spec.ip6dst, &rule->mask.dst_ip, + sizeof(struct in6_addr)); + fsp->m_u.ah_ip6_spec.spi =3D rule->mask.spi; + fsp->m_u.ah_ip6_spec.tclass =3D rule->mask.tclass; + break; + default: + return -EINVAL; + } + + fsp->ring_cookie =3D be16_to_cpu(rule->action); + + return 0; +} + +static int gve_generate_flow_rule(struct gve_priv *priv, struct ethtool_rx= _flow_spec *fsp, + struct gve_adminq_flow_rule *rule) +{ + static const u16 flow_type_lut[] =3D { + [TCP_V4_FLOW] =3D GVE_FLOW_TYPE_TCPV4, + [UDP_V4_FLOW] =3D GVE_FLOW_TYPE_UDPV4, + [SCTP_V4_FLOW] =3D GVE_FLOW_TYPE_SCTPV4, + [AH_V4_FLOW] =3D GVE_FLOW_TYPE_AHV4, + [ESP_V4_FLOW] =3D GVE_FLOW_TYPE_ESPV4, + [TCP_V6_FLOW] =3D GVE_FLOW_TYPE_TCPV6, + [UDP_V6_FLOW] =3D GVE_FLOW_TYPE_UDPV6, + [SCTP_V6_FLOW] =3D GVE_FLOW_TYPE_SCTPV6, + [AH_V6_FLOW] =3D GVE_FLOW_TYPE_AHV6, + [ESP_V6_FLOW] =3D GVE_FLOW_TYPE_ESPV6, + }; + u32 flow_type; + + if (fsp->ring_cookie =3D=3D RX_CLS_FLOW_DISC) + return -EOPNOTSUPP; + + if (fsp->ring_cookie >=3D priv->rx_cfg.num_queues) + return -EINVAL; + + rule->action =3D cpu_to_be16(fsp->ring_cookie); + + flow_type =3D fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS); + if (!flow_type || flow_type >=3D ARRAY_SIZE(flow_type_lut)) + return -EINVAL; + + rule->flow_type =3D cpu_to_be16(flow_type_lut[flow_type]); + + switch (flow_type) { + case TCP_V4_FLOW: + case UDP_V4_FLOW: + case SCTP_V4_FLOW: + rule->key.src_ip[0] =3D fsp->h_u.tcp_ip4_spec.ip4src; + rule->key.dst_ip[0] =3D fsp->h_u.tcp_ip4_spec.ip4dst; + rule->key.src_port =3D fsp->h_u.tcp_ip4_spec.psrc; + rule->key.dst_port =3D fsp->h_u.tcp_ip4_spec.pdst; + rule->mask.src_ip[0] =3D fsp->m_u.tcp_ip4_spec.ip4src; + rule->mask.dst_ip[0] =3D fsp->m_u.tcp_ip4_spec.ip4dst; + rule->mask.src_port =3D fsp->m_u.tcp_ip4_spec.psrc; + rule->mask.dst_port =3D fsp->m_u.tcp_ip4_spec.pdst; + break; + case AH_V4_FLOW: + case ESP_V4_FLOW: + rule->key.src_ip[0] =3D fsp->h_u.tcp_ip4_spec.ip4src; + rule->key.dst_ip[0] =3D fsp->h_u.tcp_ip4_spec.ip4dst; + rule->key.spi =3D fsp->h_u.ah_ip4_spec.spi; + rule->mask.src_ip[0] =3D fsp->m_u.tcp_ip4_spec.ip4src; + rule->mask.dst_ip[0] =3D fsp->m_u.tcp_ip4_spec.ip4dst; + rule->mask.spi =3D fsp->m_u.ah_ip4_spec.spi; + break; + case TCP_V6_FLOW: + case UDP_V6_FLOW: + case SCTP_V6_FLOW: + memcpy(&rule->key.src_ip, fsp->h_u.tcp_ip6_spec.ip6src, + sizeof(struct in6_addr)); + memcpy(&rule->key.dst_ip, fsp->h_u.tcp_ip6_spec.ip6dst, + sizeof(struct in6_addr)); + rule->key.src_port =3D fsp->h_u.tcp_ip6_spec.psrc; + rule->key.dst_port =3D fsp->h_u.tcp_ip6_spec.pdst; + memcpy(&rule->mask.src_ip, fsp->m_u.tcp_ip6_spec.ip6src, + sizeof(struct in6_addr)); + memcpy(&rule->mask.dst_ip, fsp->m_u.tcp_ip6_spec.ip6dst, + sizeof(struct in6_addr)); + rule->mask.src_port =3D fsp->m_u.tcp_ip6_spec.psrc; + rule->mask.dst_port =3D fsp->m_u.tcp_ip6_spec.pdst; + break; + case AH_V6_FLOW: + case ESP_V6_FLOW: + memcpy(&rule->key.src_ip, fsp->h_u.usr_ip6_spec.ip6src, + sizeof(struct in6_addr)); + memcpy(&rule->key.dst_ip, fsp->h_u.usr_ip6_spec.ip6dst, + sizeof(struct in6_addr)); + rule->key.spi =3D fsp->h_u.ah_ip6_spec.spi; + memcpy(&rule->mask.src_ip, fsp->m_u.usr_ip6_spec.ip6src, + sizeof(struct in6_addr)); + memcpy(&rule->mask.dst_ip, fsp->m_u.usr_ip6_spec.ip6dst, + sizeof(struct in6_addr)); + rule->key.spi =3D fsp->h_u.ah_ip6_spec.spi; + break; + default: + /* not doing un-parsed flow types */ + return -EINVAL; + } + + return 0; +} + +int gve_get_flow_rule_entry(struct gve_priv *priv, struct ethtool_rxnfc *c= md) +{ + struct ethtool_rx_flow_spec *fsp =3D (struct ethtool_rx_flow_spec *)&cmd-= >fs; + struct gve_flow_rule *rules_cache =3D priv->flow_rules_cache.rules_cache; + u32 *cache_num =3D &priv->flow_rules_cache.rules_cache_num; + struct gve_flow_rule *rule =3D NULL; + int err =3D 0; + u32 i; + + if (!priv->max_flow_rules) + return -EOPNOTSUPP; + + if (!priv->flow_rules_cache.rules_cache_synced || + fsp->location < be32_to_cpu(rules_cache[0].location) || + fsp->location > be32_to_cpu(rules_cache[*cache_num - 1].location)) { + err =3D gve_adminq_query_flow_rules(priv, GVE_FLOW_RULE_QUERY_RULES, fsp= ->location); + if (err) + return err; + + priv->flow_rules_cache.rules_cache_synced =3D true; + } + + for (i =3D 0; i < *cache_num; i++) { + if (fsp->location =3D=3D be32_to_cpu(rules_cache[i].location)) { + rule =3D &rules_cache[i]; + break; + } + } + + if (!rule) + return -EINVAL; + + err =3D gve_fill_ethtool_flow_spec(fsp, rule); + + return err; +} + +int gve_get_flow_rule_ids(struct gve_priv *priv, struct ethtool_rxnfc *cmd= , u32 *rule_locs) +{ + u32 *rule_ids_cache =3D priv->flow_rules_cache.rule_ids_cache; + u32 *cache_num =3D &priv->flow_rules_cache.rule_ids_cache_num; + u32 starting_rule_id =3D 0; + u32 i =3D 0, j =3D 0; + int err =3D 0; + + if (!priv->max_flow_rules) + return -EOPNOTSUPP; + + do { + err =3D gve_adminq_query_flow_rules(priv, GVE_FLOW_RULE_QUERY_IDS, + starting_rule_id); + if (err) + return err; + + for (i =3D 0; i < *cache_num; i++) { + if (j >=3D cmd->rule_cnt) + return -EMSGSIZE; + + rule_locs[j++] =3D be32_to_cpu(rule_ids_cache[i]); + starting_rule_id =3D be32_to_cpu(rule_ids_cache[i]) + 1; + } + } while (*cache_num !=3D 0); + cmd->data =3D priv->max_flow_rules; + + return err; +} + +int gve_add_flow_rule(struct gve_priv *priv, struct ethtool_rxnfc *cmd) +{ + struct ethtool_rx_flow_spec *fsp =3D &cmd->fs; + struct gve_adminq_flow_rule *rule =3D NULL; + int err; + + if (!priv->max_flow_rules) + return -EOPNOTSUPP; + + rule =3D kvzalloc(sizeof(*rule), GFP_KERNEL); + if (!rule) + return -ENOMEM; + + err =3D gve_generate_flow_rule(priv, fsp, rule); + if (err) + goto out; + + err =3D gve_adminq_add_flow_rule(priv, rule, fsp->location); + +out: + kfree(rule); + if (err) + dev_err(&priv->pdev->dev, "Failed to add the flow rule: %u", fsp->locati= on); + + return err; +} + +int gve_del_flow_rule(struct gve_priv *priv, struct ethtool_rxnfc *cmd) +{ + struct ethtool_rx_flow_spec *fsp =3D (struct ethtool_rx_flow_spec *)&cmd-= >fs; + + if (!priv->max_flow_rules) + return -EOPNOTSUPP; + + return gve_adminq_del_flow_rule(priv, fsp->location); +} diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ether= net/google/gve/gve_main.c index eb435ccbe98e..ac38453327c3 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: (GPL-2.0 OR MIT) /* Google virtual Ethernet (gve) driver * - * Copyright (C) 2015-2021 Google, Inc. + * Copyright (C) 2015-2024 Google LLC */ =20 #include @@ -638,6 +638,12 @@ static void gve_teardown_device_resources(struct gve_p= riv *priv) =20 /* Tell device its resources are being freed */ if (gve_get_device_resources_ok(priv)) { + err =3D gve_flow_rules_reset(priv); + if (err) { + dev_err(&priv->pdev->dev, + "Failed to reset flow rules: err=3D%d\n", err); + gve_trigger_reset(priv); + } /* detach the stats report */ err =3D gve_adminq_report_stats(priv, 0, 0x0, GVE_STATS_REPORT_TIMER_PER= IOD); if (err) { @@ -1782,6 +1788,14 @@ static int gve_xdp(struct net_device *dev, struct ne= tdev_bpf *xdp) } } =20 +int gve_flow_rules_reset(struct gve_priv *priv) +{ + if (!priv->max_flow_rules) + return 0; + + return gve_adminq_reset_flow_rules(priv); +} + int gve_adjust_config(struct gve_priv *priv, struct gve_tx_alloc_rings_cfg *tx_alloc_cfg, struct gve_rx_alloc_rings_cfg *rx_alloc_cfg) @@ -2055,15 +2069,21 @@ static int gve_set_features(struct net_device *netd= ev, netdev->features ^=3D NETIF_F_LRO; if (netif_carrier_ok(netdev)) { err =3D gve_adjust_config(priv, &tx_alloc_cfg, &rx_alloc_cfg); - if (err) { - /* Revert the change on error. */ - netdev->features =3D orig_features; - return err; - } + if (err) + goto revert_features; } } + if ((netdev->features & NETIF_F_NTUPLE) && !(features & NETIF_F_NTUPLE)) { + err =3D gve_flow_rules_reset(priv); + if (err) + goto revert_features; + } =20 return 0; + +revert_features: + netdev->features =3D orig_features; + return err; } =20 static const struct net_device_ops gve_netdev_ops =3D { --=20 2.45.0.rc1.225.g2a3ae87e7f-goog