From patchwork Thu Mar 6 23:01:51 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 14005471 Received: from mail-qv1-f53.google.com (mail-qv1-f53.google.com [209.85.219.53]) (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 619A5279349 for ; Thu, 6 Mar 2025 23:04:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302242; cv=none; b=Ea2619UqaDXZI3gq7fCvXtAl/38g0ayJISFECOzkBRfY1RDNaRPKSgM6cvYRGVBjPnSAZGhkekqFifmLSQd2IIvXj1/LlpQgXQzdOJiHrTUbAHZBUA8EC0Fm34jEBQUcVoYSVVrPp1vNm+MljiDGHfl2rDyWC9YpZwXNIg1yqmw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302242; c=relaxed/simple; bh=A9mobOvuIeF00fIfjCqC9uNVWIrG6j7W2+rdHsW6dwk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JRNj4y1sanPhD2Kzg4dWmUtEzVwihXoeUZfqg6YdhFdo45RcuTq+C1mvHnl2eXMhhhaLTdSM9Iy9X/XptLW2vy8jZFMioQn45HOAWhGTiRqQHUCk1dXg1GfOCqD/2yOpRkA8mnUERgHDhF07DfhRDDv74OfGuMZTuRemrqxqJU0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net; spf=pass smtp.mailfrom=enfabrica.net; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b=JAg5nyfN; arc=none smtp.client-ip=209.85.219.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b="JAg5nyfN" Received: by mail-qv1-f53.google.com with SMTP id 6a1803df08f44-6e8f254b875so9606796d6.1 for ; Thu, 06 Mar 2025 15:04:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enfabrica.net; s=google; t=1741302239; x=1741907039; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WdHcT+hSCoYTik958njnGQie2UZi8YbiCIJN/dVy/UQ=; b=JAg5nyfN5RaHuEntmBdUUTuczyCp7OYwxGwEeYFUtP4PxZRfWe4epLXmfUtpeNFrmh tn5nn65djzlxI93yakBkU+bvlEf1+nRy00RFlSoFP/ZtFxF1m7cnuUz4cIgQy4qruqFs s5I15mCxKpf8w1utGm+BrZuaCmTEJgQqQ6Wo10j4GhDjlZ35bZkunem6EI80D/TXMhGN fRNyJfZrzJ2+p+VcDUQmk4oEMdgaWjMXhfP3Mtg5DqhiqMH+f930EBOZeSgarB1jTVva zKMSCdYjnbms4JQ1WeqDE686761kovjU8tZNJZNrF1wAYqVw7r0gIpUupSxtFTTQ75zE 865g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302239; x=1741907039; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=WdHcT+hSCoYTik958njnGQie2UZi8YbiCIJN/dVy/UQ=; b=KJKPjIeyjYMSD1W9ZqLzhjbKiKR6SDG1GwaN+2j2Uc/quGMdvH1lfrHP7Twu46bYF3 Q0kBaoKOJDuD5YjAN048T83wscnENnoQmu6DKi8dy38b7iWMf5Xw8twWt3GK/CqlzXpW ebUMn3X3cxWDyeM3u6V1K++wHu9NxDVm57Lf60xqDYzrLplXrwVdQbLNEtoWumGMACz6 D79U+833oCZqKV43fU0V/cDlT83tl7NFJnbdMvdzIt7O1ekPO/rh7oPlSwbBX43SxJMW wVyGBEETm+PdrYbKLNNm6jB9C9m0UVg7gRspZbTSbpKq6Ad1iFt7O/TGXwO4j6Z4X4MU P/+Q== X-Gm-Message-State: AOJu0YzIuLGBQhyLCxZBSoxq10JZ+VL/lcM4LcQ6uKk96EOMdmzayowS +oP9oWkUCztsVy514bVq1IYH079RjQsxB31lGSoOvXVuqm+EFTkB5WSCyBHu0Dt4E51MehNRmvp sRQYopVITte9RzZNPmtfwBmhMJIz7sMtg6QJn++RbygeUe2tyI5GSh9Au0TYPcgiaylPl8SGD3K YHs0JJUEx5iYd55MeV83F5y11hABph3fSV3iQTbf+AUN8= X-Gm-Gg: ASbGncuB6tMU933WARqhsGQ6VCAd1k6xVtPo6btL6cz94cIgqlBd2jTZCe19ijZb1AR oNw1/9SDJfFHl2bxfKf3k/NAnym/eEO5wo3qJ4T3ToctObXqVP4jPlhj3jqoxdGazmBi5R9fdFT yCRuaPMZ4VRUCovnCtZe5QGssvL3m5nGIN14ay6OAqIdULjPJ1SODbyDMRBAShBh1PgN0FVhrSe bjsSDedrQo8CScCzznEL0nix/oEWkQ8d7hPq3ODuI5wPoO5aaVxk7aLD5SjQMf5Fs3Xd7/o6+BZ 635oRK+obhKyIXyFc4nFDhHbCo7Ib/Fv8tdx/XVKTRZPeDpNC5Z9DqgQDyYYjFSqnAG/ X-Google-Smtp-Source: AGHT+IF1kfGspX38JaOE5QuV2pL9LaOd4NlYMWkRbiYsvXZp2jxSiWbyI1svMuCu7yxj+68lLI/tfg== X-Received: by 2002:ad4:5d49:0:b0:6e8:fbb7:6764 with SMTP id 6a1803df08f44-6e9006ba2fbmr13156446d6.45.1741302239103; Thu, 06 Mar 2025 15:03:59 -0800 (PST) Received: from debil.. (78-154-15-142.ip.btc-net.bg. [78.154.15.142]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac256654fa6sm14971966b.93.2025.03.06.15.03.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Mar 2025 15:03:58 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: shrijeet@enfabrica.net, alex.badea@keysight.com, eric.davis@broadcom.com, rip.sohan@amd.com, dsahern@kernel.org, bmt@zurich.ibm.com, roland@enfabrica.net, nikolay@enfabrica.net, winston.liu@keysight.com, dan.mihailescu@keysight.com, kheib@redhat.com, parth.v.parikh@keysight.com, davem@redhat.com, ian.ziemba@hpe.com, andrew.tauferner@cornelisnetworks.com, welch@hpe.com, rakhahari.bhunia@keysight.com, kingshuk.mandal@keysight.com, linux-rdma@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com Subject: [RFC PATCH 01/13] drivers: ultraeth: add initial skeleton and kconfig option Date: Fri, 7 Mar 2025 01:01:51 +0200 Message-ID: <20250306230203.1550314-2-nikolay@enfabrica.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250306230203.1550314-1-nikolay@enfabrica.net> References: <20250306230203.1550314-1-nikolay@enfabrica.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-State: RFC Create drivers/ultraeth/ for the upcoming new Ultra Ethernet driver and add a new Kconfig option for it. Signed-off-by: Nikolay Aleksandrov Signed-off-by: Alex Badea --- drivers/Kconfig | 2 ++ drivers/Makefile | 1 + drivers/ultraeth/Kconfig | 11 +++++++++++ drivers/ultraeth/Makefile | 3 +++ drivers/ultraeth/uet_main.c | 19 +++++++++++++++++++ 5 files changed, 36 insertions(+) create mode 100644 drivers/ultraeth/Kconfig create mode 100644 drivers/ultraeth/Makefile create mode 100644 drivers/ultraeth/uet_main.c diff --git a/drivers/Kconfig b/drivers/Kconfig index 7bdad836fc62..df3369781d37 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -245,4 +245,6 @@ source "drivers/cdx/Kconfig" source "drivers/dpll/Kconfig" +source "drivers/ultraeth/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 45d1c3e630f7..47848677605a 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -195,3 +195,4 @@ obj-$(CONFIG_CDX_BUS) += cdx/ obj-$(CONFIG_DPLL) += dpll/ obj-$(CONFIG_S390) += s390/ +obj-$(CONFIG_ULTRAETH) += ultraeth/ diff --git a/drivers/ultraeth/Kconfig b/drivers/ultraeth/Kconfig new file mode 100644 index 000000000000..a769c6118f2f --- /dev/null +++ b/drivers/ultraeth/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config ULTRAETH + tristate "Ultra Ethernet core" + depends on INET + depends on IPV6 || !IPV6 + select NET_UDP_TUNNEL + select GRO_CELLS + help + To compile this driver as a module, choose M here: the module + will be called ultraeth. diff --git a/drivers/ultraeth/Makefile b/drivers/ultraeth/Makefile new file mode 100644 index 000000000000..e30373d4b5dc --- /dev/null +++ b/drivers/ultraeth/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_ULTRAETH) += ultraeth.o + +ultraeth-objs := uet_main.o diff --git a/drivers/ultraeth/uet_main.c b/drivers/ultraeth/uet_main.c new file mode 100644 index 000000000000..0d74175fc047 --- /dev/null +++ b/drivers/ultraeth/uet_main.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) + +#include +#include +#include + +static int __init uet_init(void) +{ + return 0; +} + +static void __exit uet_exit(void) +{ +} + +module_init(uet_init); +module_exit(uet_exit); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Ultra Ethernet core"); From patchwork Thu Mar 6 23:01:52 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 14005472 X-Patchwork-Delegate: kuba@kernel.org Received: from mail-qv1-f46.google.com (mail-qv1-f46.google.com [209.85.219.46]) (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 02B9527D785 for ; Thu, 6 Mar 2025 23:04:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302244; cv=none; b=AwUvvMhj/+79f+FhriJFLBnfuR7ImPIDDG06caEi0LG6Pc2805krN/2Fh8rAi/wNVYdKoX6WMyMLX5i0Yubg6LmetuucdFoFyC6WKVcl6iKQ+4bJ5SQYxOHax7JIlaqzmvuEeXTBe3IiDVebciRN6URY7RF0BOq7QzLgcJDIJq0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302244; c=relaxed/simple; bh=VHDaj2dFWf0huRfzMhshaU6/zQL7nlq4K/C8/Go+Zts=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Udj2+RgDLmR/OlybuP9ZOzGU8yTfDQh4aoKTWK1tJu/m9tHndg/K54FRcu+eu6604t3T7qK9jyAy+xUeigA2V7mPBN73rIpBNs+OOwXhJIbDZIdqu8wRnWpo1/A/n6uvt/sfmxK0S+G19QE6u66YSWG2CM0XYrgNcBcQBxeKZz0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net; spf=pass smtp.mailfrom=enfabrica.net; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b=IXIVWwc5; arc=none smtp.client-ip=209.85.219.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b="IXIVWwc5" Received: by mail-qv1-f46.google.com with SMTP id 6a1803df08f44-6e17d3e92d9so8382266d6.1 for ; Thu, 06 Mar 2025 15:04:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enfabrica.net; s=google; t=1741302242; x=1741907042; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Z+HMmIGPgvz4lBJFzaO8GeogBJftxbQ/ueBJRS3zwq0=; b=IXIVWwc5h1bHO3+9QP8seXn7UmnEYm6cXpdOiWYkCBr3P8Uy0oUWjm8I1K8mz/x9K7 A8Mp+A9zermIXAkl0G3vQV2XWWUxw7LwMBRIe/O1e6bOzWOH9FnW0d3jLi/2RlW8jvR5 IqAUIfjJ52hCUmnlKBjhQAB3Jg2s8qNHm7CWccj/ROqCRS6fkWr1AtgkiT0EDavhriNt CYMAhblB0Pa7RS7XQCGWdfW2bT7CmcdmcFqX7ZoNJB3sbLecziGidbxjJmo1U7/g7mrE j6lmkH0TPbD+BKuMfbSdPt+tKTSX6aeMbc/Ior8JyaoLN388an0uiTocWzeZRXVifPpw vgOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302242; x=1741907042; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Z+HMmIGPgvz4lBJFzaO8GeogBJftxbQ/ueBJRS3zwq0=; b=KqJkFEuwROTo5/pJZEo4gn8VsA6xENuVAydvtbYbLkMKUjhmn0kZq0Dis0yS77SPXT Xvc5Ae6TR86eZS4A2a0oqrg2bigA2D3Lp6cZIWfLFM2Gc7luB+sMbg3jAHbDkvPV5IjG dmsHZmYLIF9hRV3FhspN6Q0DjDJDpDEt9vJ5NuyAPf6Segj2TSpu75prskRoNAS/Amx1 IZte+gm54G/kPFMQpgmUiANovUt5YeYlUHAabeVfhMDoi+3QoMT7at5xbX4C1DzDBElK hsejsIKTSZclcLFwp7eScXQGM3CYytNENkYRtbWL+RyvxTGQPCvjJo73EJr2kkxE18qD fOxw== X-Gm-Message-State: AOJu0YwKfLPs3wStujj3Hk6494JyjHLjhH9UL6KWOuyxZKmkxqH5JxTO 3KjN1Fc3ryO3zD53KND7qXGfYdLO+rsU6VD7UvAS5QiQQu8tENS0vd+bthfbUYDHw6Dpd7rTQn1 x3vSH7SF1sKJzyvCXNiZxB4RalerY2mXHkfq33yOcDC3sr6z2IFQFbxPvGQDBreQLJBalRXsrmh eQaa7l8CHU4NkeG7CqFmgvuurFWKe/HuNEqi/KlOyy2Ug= X-Gm-Gg: ASbGncvIExCifVjZ4ePtQaU7h04QPvmo85syuAm9b/pUPLbjsUvTEyBxS3DrBcXYsYu tSUXilvV/d0K0F3WbsfzJZwJJ0a7MA4Y7HIH5xhH9bWWkwfBgCF14BEWvyTtwOv62dHm7JoMrM5 wcxrXmets/PBXPgkmoRcczoS9bcbORCWqpNgqLOraPxMsWy6hoY0p3SHziKCuZolGR9GZ8FrgmA RNG3q4xrNRxrXP0t9zA7mTEtDfF0HMXusYGN7g34xZt2SJKL3FOmYjwzcitL32pble+qfpUeO5D Nyc3Dsh2e/sy9VOMc/7imPVUQ4W6LLWSzI5VIIAs+YAshu7d31dCiy5PLmnVa3Xp8Tyd X-Google-Smtp-Source: AGHT+IElZaiOv/FIthqpFAMu6jcbTAo/35EvxhNrODQalY6dTWOVJZ786VW8xHepZXH+ATJpRyowxQ== X-Received: by 2002:ad4:5aaf:0:b0:6e8:ea29:fdd1 with SMTP id 6a1803df08f44-6e9005d4500mr16521666d6.3.1741302241684; Thu, 06 Mar 2025 15:04:01 -0800 (PST) Received: from debil.. (78-154-15-142.ip.btc-net.bg. [78.154.15.142]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac256654fa6sm14971966b.93.2025.03.06.15.03.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Mar 2025 15:04:01 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: shrijeet@enfabrica.net, alex.badea@keysight.com, eric.davis@broadcom.com, rip.sohan@amd.com, dsahern@kernel.org, bmt@zurich.ibm.com, roland@enfabrica.net, nikolay@enfabrica.net, winston.liu@keysight.com, dan.mihailescu@keysight.com, kheib@redhat.com, parth.v.parikh@keysight.com, davem@redhat.com, ian.ziemba@hpe.com, andrew.tauferner@cornelisnetworks.com, welch@hpe.com, rakhahari.bhunia@keysight.com, kingshuk.mandal@keysight.com, linux-rdma@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com Subject: [RFC PATCH 02/13] drivers: ultraeth: add context support Date: Fri, 7 Mar 2025 01:01:52 +0200 Message-ID: <20250306230203.1550314-3-nikolay@enfabrica.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250306230203.1550314-1-nikolay@enfabrica.net> References: <20250306230203.1550314-1-nikolay@enfabrica.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC The ultra ethernet context is at the root and must be created first. UET contexts are identified by host unique assigned ids on creation and are protected by a ref counter. Signed-off-by: Nikolay Aleksandrov Signed-off-by: Alex Badea --- drivers/ultraeth/Makefile | 2 +- drivers/ultraeth/uet_context.c | 149 +++++++++++++++++++++++++++++ drivers/ultraeth/uet_main.c | 2 + include/net/ultraeth/uet_context.h | 27 ++++++ 4 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 drivers/ultraeth/uet_context.c create mode 100644 include/net/ultraeth/uet_context.h diff --git a/drivers/ultraeth/Makefile b/drivers/ultraeth/Makefile index e30373d4b5dc..dc0c07eeef65 100644 --- a/drivers/ultraeth/Makefile +++ b/drivers/ultraeth/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_ULTRAETH) += ultraeth.o -ultraeth-objs := uet_main.o +ultraeth-objs := uet_main.o uet_context.o diff --git a/drivers/ultraeth/uet_context.c b/drivers/ultraeth/uet_context.c new file mode 100644 index 000000000000..1c74cd8bbd56 --- /dev/null +++ b/drivers/ultraeth/uet_context.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) + +#include + +#define MAX_CONTEXT_ID 256 +static DECLARE_BITMAP(uet_context_ids, MAX_CONTEXT_ID); +static LIST_HEAD(uet_context_list); +static DEFINE_MUTEX(uet_context_lock); + +static int uet_context_get_new_id(int id) +{ + if (WARN_ON(id < -1 || id >= MAX_CONTEXT_ID)) + return -EINVAL; + + mutex_lock(&uet_context_lock); + if (id == -1) + id = find_first_zero_bit(uet_context_ids, MAX_CONTEXT_ID); + if (id < MAX_CONTEXT_ID) { + if (test_and_set_bit(id, uet_context_ids)) + id = -EBUSY; + } else { + id = -ENOSPC; + } + mutex_unlock(&uet_context_lock); + + return id; +} + +static void uet_context_put_id(struct uet_context *ctx) +{ + clear_bit(ctx->id, uet_context_ids); +} + +static void uet_context_link(struct uet_context *ctx) +{ + WARN_ON(!list_empty(&ctx->list)); + list_add(&ctx->list, &uet_context_list); +} + +static void uet_context_unlink(struct uet_context *ctx) +{ + list_del_init(&ctx->list); + if (refcount_dec_and_test(&ctx->refcnt)) + return; + + mutex_unlock(&uet_context_lock); + wait_event(ctx->refcnt_wait, refcount_read(&ctx->refcnt) == 0); + mutex_lock(&uet_context_lock); + WARN_ON(refcount_read(&ctx->refcnt) > 0); +} + +static struct uet_context *uet_context_find(int id) +{ + struct uet_context *ctx; + + if (!test_bit(id, uet_context_ids)) + return NULL; + + list_for_each_entry(ctx, &uet_context_list, list) + if (ctx->id == id) + return ctx; + + return NULL; +} + +struct uet_context *uet_context_get_by_id(int id) +{ + struct uet_context *ctx; + + mutex_lock(&uet_context_lock); + ctx = uet_context_find(id); + if (ctx) + refcount_inc(&ctx->refcnt); + mutex_unlock(&uet_context_lock); + + return ctx; +} + +void uet_context_put(struct uet_context *ctx) +{ + if (refcount_dec_and_test(&ctx->refcnt)) + wake_up(&ctx->refcnt_wait); +} + +int uet_context_create(int id) +{ + struct uet_context *ctx; + int err = -ENOMEM; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return err; + + INIT_LIST_HEAD(&ctx->list); + init_waitqueue_head(&ctx->refcnt_wait); + refcount_set(&ctx->refcnt, 1); + + ctx->id = uet_context_get_new_id(id); + if (ctx->id < 0) { + err = ctx->id; + goto ctx_id_err; + } + + uet_context_link(ctx); + + return 0; + +ctx_id_err: + kfree(ctx); + + return err; +} + +static void __uet_context_destroy(struct uet_context *ctx) +{ + uet_context_unlink(ctx); + uet_context_put_id(ctx); + kfree(ctx); +} + +bool uet_context_destroy(int id) +{ + struct uet_context *ctx; + bool found = false; + + mutex_lock(&uet_context_lock); + ctx = uet_context_find(id); + if (ctx) { + __uet_context_destroy(ctx); + found = true; + } + mutex_unlock(&uet_context_lock); + + return found; +} + +void uet_context_destroy_all(void) +{ + struct uet_context *ctx; + + mutex_lock(&uet_context_lock); + while ((ctx = list_first_entry_or_null(&uet_context_list, + struct uet_context, + list))) + __uet_context_destroy(ctx); + + WARN_ON(!list_empty(&uet_context_list)); + mutex_unlock(&uet_context_lock); +} diff --git a/drivers/ultraeth/uet_main.c b/drivers/ultraeth/uet_main.c index 0d74175fc047..0f8383c6aba0 100644 --- a/drivers/ultraeth/uet_main.c +++ b/drivers/ultraeth/uet_main.c @@ -3,6 +3,7 @@ #include #include #include +#include static int __init uet_init(void) { @@ -11,6 +12,7 @@ static int __init uet_init(void) static void __exit uet_exit(void) { + uet_context_destroy_all(); } module_init(uet_init); diff --git a/include/net/ultraeth/uet_context.h b/include/net/ultraeth/uet_context.h new file mode 100644 index 000000000000..150ad2c9b456 --- /dev/null +++ b/include/net/ultraeth/uet_context.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ + +#ifndef _UET_CONTEXT_H +#define _UET_CONTEXT_H + +#include +#include +#include +#include +#include +#include + +struct uet_context { + int id; + refcount_t refcnt; + wait_queue_head_t refcnt_wait; + struct list_head list; +}; + +struct uet_context *uet_context_get_by_id(int id); +void uet_context_put(struct uet_context *ses_pl); + +int uet_context_create(int id); +bool uet_context_destroy(int id); +void uet_context_destroy_all(void); + +#endif /* _UET_CONTEXT_H */ From patchwork Thu Mar 6 23:01:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 14005473 Received: from mail-qk1-f179.google.com (mail-qk1-f179.google.com [209.85.222.179]) (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 0C6F227E1B2 for ; Thu, 6 Mar 2025 23:04:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302247; cv=none; b=Zgg4kOTK6C5qBwry3x6TePu5WXd+oYOhjo/X0aDWsEI87yq1eazqoDVbPlO+aYFEQjWCvtMA5Uu5KzOjYEJjFfORO/DEuoHwgqBtemeLl6JZqjj+q97DmNpTYpnmw1fP6nvxMfm6J8zoeMOmEIqEGyFR9ytKF9+B1kLlkSqHQeM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302247; c=relaxed/simple; bh=9t+BWyeKo3lXUFD7OKztQ3S+oioUT+EA4xokMzKS89o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uHV1eZjDFURzmZld701cF/Fjn9Lgr34KFXLOOoLulgzmnga2yXyj1HcMzD4e5Rr1YABjxVO9yHAzA8LkD4GeT85ZOnp0Q8t3SxOBLIv/MFOpPxjbFGXCyEOk8y2nTLV9AHrJLKMji76HBs8nNy+Zds3QE1k/xRNnIWKNGAm9Ln0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net; spf=pass smtp.mailfrom=enfabrica.net; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b=gEvP7s6d; arc=none smtp.client-ip=209.85.222.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b="gEvP7s6d" Received: by mail-qk1-f179.google.com with SMTP id af79cd13be357-7c08b14baa9so117763085a.3 for ; Thu, 06 Mar 2025 15:04:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enfabrica.net; s=google; t=1741302244; x=1741907044; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tI+QptX8aFaKo9m7kn+rX3JmnFQXDEQcbJWxJ5w+bWw=; b=gEvP7s6dOJUILgjrRMzutasGBvW+t94Yn4ZXZqdNe8CYmmC6bzT0nZp3T+y+fNM3Mh VtL5RFTCYxW7DgAKW7VqK2714DUz1Xcd+QTT/sESBnsoXdA23zmjyzK15m3VLXynYwU6 VtkU8f6MaNePSG7FEb23PEq9vWWDzHtUGp1CXKd2xllr6Wy4QLfShVfQNrs1X+2lWPc1 h+W8Nn/PjgyNGzmLpT30DxSp2gIMzRVRekwoQEc9wbI9IT9MjMg/t7dmA7g+U9cg24Ek jWRsDenN+cdq4HMEMgquZohjjUxueIo2VOUuWCn67BM/evgdQImmwPoRv085ygvGkkgR tofg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302244; x=1741907044; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tI+QptX8aFaKo9m7kn+rX3JmnFQXDEQcbJWxJ5w+bWw=; b=U4JHqSP0xAOqa5b/Nen3zspvxutjDsJJfR1lMjjaT0N1ih1sQXfzRwVFDyf4+gp8mH Gp15r3s730a5bNtaGJ+H2hYTLQz/CeE2tJlxOvOLS6QjmIpVHkubagwEdREZJuUJaU4R cXNQHZw5fA4VEOX8+Z0jrNKRMiZSKEZvEdXzoxCOrQc+OBVvcJmMnKsNfZ9Ju/nj7iey BJpKwl7L2mfQmHUiMTn3s1RcRiO4nrEX2em22J0nltvEkcMg4xxmOGJUqPxgMx3/dbgo GesERyS/9cmRWvH9t05pebo0UTfg9vwIOk0nd3yUS1Irzc5lTzZF/xDBGttLtBNY7yw/ YEwg== X-Gm-Message-State: AOJu0Yw6KBTwmLLpQmZ6x+cKcRWVqG7Ir7w8QlMwNHgHgMhcmdK/BfYq hfzTdKbUZS9ra4g3vakx5Zy7REVoJc8fmZXgjI5m08Dr3RzwohJmy4D1TKgDl1lKy4ZsmbAEcYO wRwSpbqS87FufdWGQER9dWNiy9n+9+nZ+qkP0QVoggpxgFItn8G8AdXe4gZVoNerMOLGkwqz17+ mj5N2NNiS43few6vrwjz89G1thwH+bZXbHyFs2/TYRsR8= X-Gm-Gg: ASbGncuAMi3Iygy2i42CZJ8c4tjeEY3cM7m/aQ5JN9bAW8dkUPrpnKxejCNZDkuJpJg 8xp7WQPyotuxs9dCj3Slvws2Y41EHSk8nIil+MB1x1Eq4aXkwVOoXi1tD1QbJydAq1bJFXg/cba JC3tTQth+WLU505vkq+o6eE4yvtlfmkCnHGesV/eUtKOj4mfdiBvNmlGsbF5ooYIjwUFMQPeb4U p6xjMbRJ28c3gkNDv8SWPBvThVF/ZIFABUAaQlz866lnBYMQzGir0L0hWH+NFlP21ythBU9DWZ3 8nEivr2VTfoABUZ1uYlxlqpXvkiJYMLWfxno+CxWF8xAkf7x67YXUEq0y38WVNgP4KzU X-Google-Smtp-Source: AGHT+IHYhgnp81nqwMBCWbPMWFBfzmSZkACfQ2sKTr2EMOGmU8XQOZdZtUBPiAChJ7TPftti0v9yCg== X-Received: by 2002:a05:620a:2608:b0:7c0:b0b7:493f with SMTP id af79cd13be357-7c4e617614bmr171776485a.37.1741302243486; Thu, 06 Mar 2025 15:04:03 -0800 (PST) Received: from debil.. (78-154-15-142.ip.btc-net.bg. [78.154.15.142]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac256654fa6sm14971966b.93.2025.03.06.15.04.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Mar 2025 15:04:03 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: shrijeet@enfabrica.net, alex.badea@keysight.com, eric.davis@broadcom.com, rip.sohan@amd.com, dsahern@kernel.org, bmt@zurich.ibm.com, roland@enfabrica.net, nikolay@enfabrica.net, winston.liu@keysight.com, dan.mihailescu@keysight.com, kheib@redhat.com, parth.v.parikh@keysight.com, davem@redhat.com, ian.ziemba@hpe.com, andrew.tauferner@cornelisnetworks.com, welch@hpe.com, rakhahari.bhunia@keysight.com, kingshuk.mandal@keysight.com, linux-rdma@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com Subject: [RFC PATCH 03/13] drivers: ultraeth: add new genl family Date: Fri, 7 Mar 2025 01:01:53 +0200 Message-ID: <20250306230203.1550314-4-nikolay@enfabrica.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250306230203.1550314-1-nikolay@enfabrica.net> References: <20250306230203.1550314-1-nikolay@enfabrica.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-State: RFC The UE genl family is described by ynl spec in Documentation/netlink/specs/ultraeth.yaml. It supports context list, create and delete. The corresponding files are auto-generated by ynl: drivers/ultraeth/uet_netlink.c drivers/ultraeth/uet_netlink.h include/uapi/linux/ultraeth_nl.h Signed-off-by: Nikolay Aleksandrov Signed-off-by: Alex Badea --- Documentation/netlink/specs/ultraeth.yaml | 56 ++++++++++++++++++ drivers/ultraeth/Makefile | 2 +- drivers/ultraeth/uet_context.c | 72 +++++++++++++++++++++++ drivers/ultraeth/uet_main.c | 5 +- drivers/ultraeth/uet_netlink.c | 54 +++++++++++++++++ drivers/ultraeth/uet_netlink.h | 21 +++++++ include/uapi/linux/ultraeth_nl.h | 35 +++++++++++ 7 files changed, 243 insertions(+), 2 deletions(-) create mode 100644 Documentation/netlink/specs/ultraeth.yaml create mode 100644 drivers/ultraeth/uet_netlink.c create mode 100644 drivers/ultraeth/uet_netlink.h create mode 100644 include/uapi/linux/ultraeth_nl.h diff --git a/Documentation/netlink/specs/ultraeth.yaml b/Documentation/netlink/specs/ultraeth.yaml new file mode 100644 index 000000000000..55ab4d9b82a9 --- /dev/null +++ b/Documentation/netlink/specs/ultraeth.yaml @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) + +name: ultraeth +protocol: genetlink +uapi-header: linux/ultraeth_nl.h + +doc: Ultra Ethernet driver genetlink operations + +attribute-sets: + - + name: context + attributes: + - + name: id + type: s32 + checks: + min: 0 + max: 255 + - + name: contexts + attributes: + - + name: context + type: nest + nested-attributes: context + multi-attr: true + +operations: + name-prefix: ultraeth-cmd- + list: + - + name: context-get + doc: dump ultraeth context information + attribute-set: context + dump: + reply: + attributes: &all-context-attrs + - id + - + name: context-new + doc: add new ultraeth context + attribute-set: context + flags: [ admin-perm ] + do: + request: + attributes: + - id + - + name: context-del + doc: delete ultraeth context + attribute-set: context + flags: [ admin-perm ] + do: + request: + attributes: + - id diff --git a/drivers/ultraeth/Makefile b/drivers/ultraeth/Makefile index dc0c07eeef65..599d91d205c1 100644 --- a/drivers/ultraeth/Makefile +++ b/drivers/ultraeth/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_ULTRAETH) += ultraeth.o -ultraeth-objs := uet_main.o uet_context.o +ultraeth-objs := uet_main.o uet_context.o uet_netlink.o diff --git a/drivers/ultraeth/uet_context.c b/drivers/ultraeth/uet_context.c index 1c74cd8bbd56..2444fa3f35cd 100644 --- a/drivers/ultraeth/uet_context.c +++ b/drivers/ultraeth/uet_context.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) #include +#include "uet_netlink.h" #define MAX_CONTEXT_ID 256 static DECLARE_BITMAP(uet_context_ids, MAX_CONTEXT_ID); @@ -147,3 +148,74 @@ void uet_context_destroy_all(void) WARN_ON(!list_empty(&uet_context_list)); mutex_unlock(&uet_context_lock); } + +static int __nl_ctx_fill_one(struct sk_buff *skb, + const struct uet_context *ctx, + int cmd, u32 flags, u32 seq, u32 portid) +{ + void *hdr; + + hdr = genlmsg_put(skb, portid, seq, &ultraeth_nl_family, flags, cmd); + if (!hdr) + return -EMSGSIZE; + + if (nla_put_s32(skb, ULTRAETH_A_CONTEXT_ID, ctx->id)) + goto out_err; + + genlmsg_end(skb, hdr); + return 0; + +out_err: + genlmsg_cancel(skb, hdr); + return -EMSGSIZE; +} + +int ultraeth_nl_context_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) +{ + int idx = 0, s_idx = cb->args[0], err; + struct uet_context *ctx; + + mutex_lock(&uet_context_lock); + list_for_each_entry(ctx, &uet_context_list, list) { + if (idx < s_idx) { + idx++; + continue; + } + err = __nl_ctx_fill_one(skb, ctx, ULTRAETH_CMD_CONTEXT_GET, + NLM_F_MULTI, cb->nlh->nlmsg_seq, + NETLINK_CB(cb->skb).portid); + if (err) + break; + idx++; + } + cb->args[0] = idx; + mutex_unlock(&uet_context_lock); + + return err ? err : skb->len; +} + +int ultraeth_nl_context_new_doit(struct sk_buff *skb, struct genl_info *info) +{ + int id = -1; + + if (info->attrs[ULTRAETH_A_CONTEXT_ID]) + id = nla_get_s32(info->attrs[ULTRAETH_A_CONTEXT_ID]); + + return uet_context_create(id); +} + +int ultraeth_nl_context_del_doit(struct sk_buff *skb, struct genl_info *info) +{ + bool destroyed = false; + int id; + + if (!info->attrs[ULTRAETH_A_CONTEXT_ID]) { + NL_SET_ERR_MSG(info->extack, "UET context id must be specified"); + return -EINVAL; + } + + id = nla_get_s32(info->attrs[ULTRAETH_A_CONTEXT_ID]); + destroyed = uet_context_destroy(id); + + return destroyed ? 0 : -ENOENT; +} diff --git a/drivers/ultraeth/uet_main.c b/drivers/ultraeth/uet_main.c index 0f8383c6aba0..0ec1dc74abbb 100644 --- a/drivers/ultraeth/uet_main.c +++ b/drivers/ultraeth/uet_main.c @@ -5,13 +5,16 @@ #include #include +#include "uet_netlink.h" + static int __init uet_init(void) { - return 0; + return genl_register_family(&ultraeth_nl_family); } static void __exit uet_exit(void) { + genl_unregister_family(&ultraeth_nl_family); uet_context_destroy_all(); } diff --git a/drivers/ultraeth/uet_netlink.c b/drivers/ultraeth/uet_netlink.c new file mode 100644 index 000000000000..39e4aa6092a9 --- /dev/null +++ b/drivers/ultraeth/uet_netlink.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/ultraeth.yaml */ +/* YNL-GEN kernel source */ + +#include +#include + +#include "uet_netlink.h" + +#include + +/* ULTRAETH_CMD_CONTEXT_NEW - do */ +static const struct nla_policy ultraeth_context_new_nl_policy[ULTRAETH_A_CONTEXT_ID + 1] = { + [ULTRAETH_A_CONTEXT_ID] = NLA_POLICY_RANGE(NLA_S32, 0, 255), +}; + +/* ULTRAETH_CMD_CONTEXT_DEL - do */ +static const struct nla_policy ultraeth_context_del_nl_policy[ULTRAETH_A_CONTEXT_ID + 1] = { + [ULTRAETH_A_CONTEXT_ID] = NLA_POLICY_RANGE(NLA_S32, 0, 255), +}; + +/* Ops table for ultraeth */ +static const struct genl_split_ops ultraeth_nl_ops[] = { + { + .cmd = ULTRAETH_CMD_CONTEXT_GET, + .dumpit = ultraeth_nl_context_get_dumpit, + .flags = GENL_CMD_CAP_DUMP, + }, + { + .cmd = ULTRAETH_CMD_CONTEXT_NEW, + .doit = ultraeth_nl_context_new_doit, + .policy = ultraeth_context_new_nl_policy, + .maxattr = ULTRAETH_A_CONTEXT_ID, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = ULTRAETH_CMD_CONTEXT_DEL, + .doit = ultraeth_nl_context_del_doit, + .policy = ultraeth_context_del_nl_policy, + .maxattr = ULTRAETH_A_CONTEXT_ID, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, +}; + +struct genl_family ultraeth_nl_family __ro_after_init = { + .name = ULTRAETH_FAMILY_NAME, + .version = ULTRAETH_FAMILY_VERSION, + .netnsok = true, + .parallel_ops = true, + .module = THIS_MODULE, + .split_ops = ultraeth_nl_ops, + .n_split_ops = ARRAY_SIZE(ultraeth_nl_ops), +}; diff --git a/drivers/ultraeth/uet_netlink.h b/drivers/ultraeth/uet_netlink.h new file mode 100644 index 000000000000..9dd9df24513a --- /dev/null +++ b/drivers/ultraeth/uet_netlink.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/ultraeth.yaml */ +/* YNL-GEN kernel header */ + +#ifndef _LINUX_ULTRAETH_GEN_H +#define _LINUX_ULTRAETH_GEN_H + +#include +#include + +#include + +int ultraeth_nl_context_get_dumpit(struct sk_buff *skb, + struct netlink_callback *cb); +int ultraeth_nl_context_new_doit(struct sk_buff *skb, struct genl_info *info); +int ultraeth_nl_context_del_doit(struct sk_buff *skb, struct genl_info *info); + +extern struct genl_family ultraeth_nl_family; + +#endif /* _LINUX_ULTRAETH_GEN_H */ diff --git a/include/uapi/linux/ultraeth_nl.h b/include/uapi/linux/ultraeth_nl.h new file mode 100644 index 000000000000..f3bdf8111623 --- /dev/null +++ b/include/uapi/linux/ultraeth_nl.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/ultraeth.yaml */ +/* YNL-GEN uapi header */ + +#ifndef _UAPI_LINUX_ULTRAETH_NL_H +#define _UAPI_LINUX_ULTRAETH_NL_H + +#define ULTRAETH_FAMILY_NAME "ultraeth" +#define ULTRAETH_FAMILY_VERSION 1 + +enum { + ULTRAETH_A_CONTEXT_ID = 1, + + __ULTRAETH_A_CONTEXT_MAX, + ULTRAETH_A_CONTEXT_MAX = (__ULTRAETH_A_CONTEXT_MAX - 1) +}; + +enum { + ULTRAETH_A_CONTEXTS_CONTEXT = 1, + + __ULTRAETH_A_CONTEXTS_MAX, + ULTRAETH_A_CONTEXTS_MAX = (__ULTRAETH_A_CONTEXTS_MAX - 1) +}; + +enum { + ULTRAETH_CMD_CONTEXT_GET = 1, + ULTRAETH_CMD_CONTEXT_NEW, + ULTRAETH_CMD_CONTEXT_DEL, + + __ULTRAETH_CMD_MAX, + ULTRAETH_CMD_MAX = (__ULTRAETH_CMD_MAX - 1) +}; + +#endif /* _UAPI_LINUX_ULTRAETH_NL_H */ From patchwork Thu Mar 6 23:01:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 14005474 X-Patchwork-Delegate: kuba@kernel.org Received: from mail-qk1-f174.google.com (mail-qk1-f174.google.com [209.85.222.174]) (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 2EE2D27D77D for ; Thu, 6 Mar 2025 23:04:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302249; cv=none; b=mOnphd+QAtD01KUwYGM3JNTGANTiZi3ECy6WYPEy9+LM2qhnKZ0czxvV/9IirGql83kObNUsme1o2vup3ehCa0kmRZnK99c3G01J5OyU5J1TDov3mfp4zIWdk80n9tkiV7urDDrSm5pzess6905WSMPOnEKJDMXOmI7Ie7bc6dA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302249; c=relaxed/simple; bh=wYg6lFDju4MwSCX2v7KdEDVQKw2PzFuai0DklCho61I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bTm3tNPQmejumkIA26WAidzbjlZEggegZjERvsg/NMCyStJyc8lbu0oN7GAG7QrrYiEsT/gSv1D9u2gX1LUeRa+90gsKEcPKfA36Wa8v5o29ueJkOhuOqu3RiUlUksX60Vb09+hJ7VacMQGL/zYd1gd74e09FK5+KP3GBvzL8ho= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net; spf=pass smtp.mailfrom=enfabrica.net; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b=asfu8MdV; arc=none smtp.client-ip=209.85.222.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b="asfu8MdV" Received: by mail-qk1-f174.google.com with SMTP id af79cd13be357-7c0155af484so184424185a.0 for ; Thu, 06 Mar 2025 15:04:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enfabrica.net; s=google; t=1741302246; x=1741907046; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=XROOKg8tgS+XFar/TPgH4HyrmnuBnyWnrGnnHBmR0+U=; b=asfu8MdV4U0vs8mt/5845HUv7BqLf1xfFRBTkuwTx81Xa3MtolnPDlNBXJgz5amQhz YCAldIoEPfafMvB6BvSabMmJB9BHns1AOH/pNmox/4GWgu+9McyslSMdcSRo2e5ibxCf VGSHgShYY1unLtlgikS/jlMxu2fDlLDF/DZeJ8nSB1IwzGUcUwfUlV4jwG4D9iU0Ff9r s+Rnx10E8NPPiLLui5KqoO+bxxISTOPIXGwbnzhi8MguRIp+mpk9L6pjvNREFdJLkncA chsp+F51TP9runxJ390wqzx9ayeXdVGi/TYHIIyj8zHwf75V4E/XyINn/CYFpyc6WPdl 0B1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302246; x=1741907046; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=XROOKg8tgS+XFar/TPgH4HyrmnuBnyWnrGnnHBmR0+U=; b=DQQNufPzjcQ+3ZnIbl8TzTojnDuysTfq+P/zp48zJ6eYBOXPoN+QZoiCUdGrjYCljZ e2EGpvcNWADdYUH0NOgddUhf44d9XzzdDmrIpJJKfdtsU9tAAADw1H2JSinViIr/wHjt UdKFaqJ9y4K6BCGkpZEORfV/V5cSu8brZrgvDE96W0hHEXKZJwtOANEuA7bH1yefrPys yS1Sq/5yPVbtNz4wi6SkxZ9bYUXf4IlamC7bFG694aGIhkdl6FIp/Fulo/MNaS7uTzCh 5FeXUhNoYd+R46c2eXMzVTD1teOHKIe0V6MjZcOUQN3PUNwtyHEvTAU+gnen8izhnI55 NeIA== X-Gm-Message-State: AOJu0Yz6UbkxPTLRvRw8jX3m0Fm2hI1E1/iScHgEFnJKf8+oP+g7YDWS v1AbfAYmvHXqlYyEkY6hQaGm1SAZ6g1tdTooQ8Xcv664nFGGNVC/uNKng9PZZnmWnNMWLQzQUWD ms/MP1BPiD3uoQRqay+6mpGRp/jF7/Q4O7VkUtkDQh1sdhuoHk0Gxd72ti016YD2eGf0XAMIok+ U+IDKE0vmHKQ9WOfZ765y4nH+tLlaqJuKdUp9EjiY6tVc= X-Gm-Gg: ASbGncu29USlqveE0bZeJb6ivSIqc9TiVhxPPjUOI4NxCuPriBI4Hys42xsS1HCONYx pHLSL+TtZe0Z4Sib/bmSKi9CFRP4SfiDLjtpw4zIv9ig81Bg8N4B1vtM5WPPKRHTTtYwytYgW5C z8nYQnbONdATYmPlMkeSNq+gXVmkBqdW30stHK6EAAlL8etjZvZoKzQyOfGRdBwXEY8JyXHOhO1 QFpbBnN0jAmWtM+hgKB/gbppURR0UyfKxHayCQYoGLJR+jb3G0Ro2M0frVnh6DLwd9O0e3wAIab fml8+FhBXnCYKE02VD3LqIvPn3JCfHBcPVlQV18BqRArLJP7K58xPwFqfxqQ4zUVgdZX X-Google-Smtp-Source: AGHT+IHABfobyGcfE7W8wGZq5vTIyQjIr95DOZim/xF7tcvT96CCCt+5Wdl6Y0QxBg1dfm/gwpPW9w== X-Received: by 2002:a05:620a:47a4:b0:7c3:bdce:d1f7 with SMTP id af79cd13be357-7c4e8dd2430mr121616285a.58.1741302245496; Thu, 06 Mar 2025 15:04:05 -0800 (PST) Received: from debil.. (78-154-15-142.ip.btc-net.bg. [78.154.15.142]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac256654fa6sm14971966b.93.2025.03.06.15.04.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Mar 2025 15:04:04 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: shrijeet@enfabrica.net, alex.badea@keysight.com, eric.davis@broadcom.com, rip.sohan@amd.com, dsahern@kernel.org, bmt@zurich.ibm.com, roland@enfabrica.net, nikolay@enfabrica.net, winston.liu@keysight.com, dan.mihailescu@keysight.com, kheib@redhat.com, parth.v.parikh@keysight.com, davem@redhat.com, ian.ziemba@hpe.com, andrew.tauferner@cornelisnetworks.com, welch@hpe.com, rakhahari.bhunia@keysight.com, kingshuk.mandal@keysight.com, linux-rdma@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com Subject: [RFC PATCH 04/13] drivers: ultraeth: add job support Date: Fri, 7 Mar 2025 01:01:54 +0200 Message-ID: <20250306230203.1550314-5-nikolay@enfabrica.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250306230203.1550314-1-nikolay@enfabrica.net> References: <20250306230203.1550314-1-nikolay@enfabrica.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC A UE job identifies an application that a communicating process belongs to within a distributed parallel application. Jobs are assigned to the initiating process and are a part of addressing, they are present in all packets. Jobs are supposed to be assigned by a provisioning system. Job ids must be globally unique within a UE context. Every UE context contains a job registry with all current jobs, regardless if they're associated with a fabric endpoint (FEP) or not. The Ultra Ethernet netlink spec is updated with job support to create, delete and list jobs. Signed-off-by: Nikolay Aleksandrov Signed-off-by: Alex Badea --- Documentation/netlink/specs/ultraeth.yaml | 147 +++++++ drivers/ultraeth/Makefile | 2 +- drivers/ultraeth/uet_context.c | 7 + drivers/ultraeth/uet_job.c | 455 ++++++++++++++++++++++ drivers/ultraeth/uet_netlink.c | 59 +++ drivers/ultraeth/uet_netlink.h | 8 + include/net/ultraeth/uet_context.h | 3 + include/net/ultraeth/uet_job.h | 78 ++++ include/uapi/linux/ultraeth.h | 44 +++ include/uapi/linux/ultraeth_nl.h | 76 ++++ 10 files changed, 878 insertions(+), 1 deletion(-) create mode 100644 drivers/ultraeth/uet_job.c create mode 100644 include/net/ultraeth/uet_job.h create mode 100644 include/uapi/linux/ultraeth.h diff --git a/Documentation/netlink/specs/ultraeth.yaml b/Documentation/netlink/specs/ultraeth.yaml index 55ab4d9b82a9..e95c73a36892 100644 --- a/Documentation/netlink/specs/ultraeth.yaml +++ b/Documentation/netlink/specs/ultraeth.yaml @@ -24,6 +24,119 @@ attribute-sets: type: nest nested-attributes: context multi-attr: true + - + name: fep-in-addr + attributes: + - + name: ip + type: binary + display-hint: ipv4 + - + name: ip6 + type: binary + byte-order: big-endian + display-hint: ipv6 + - + name: family + type: u16 + - + name: fep-address + attributes: + - + name: in-address + type: nest + nested-attributes: fep-in-addr + - + name: flags + type: u16 + - + name: caps + type: u16 + - + name: start-resource-index + type: u16 + - + name: num-resource-indices + type: u16 + - + name: initiator-id + type: u32 + - + name: pid-on-fep + type: u16 + - + name: padding + type: u16 + - + name: version + type: u8 + - + name: fep-entry + attributes: + - + name: address + type: nest + nested-attributes: fep-address + - + name: flist + attributes: + - + name: fep + type: nest + multi-attr: true + nested-attributes: fep-entry + - + name: job-req + attributes: + - + name: context-id + type: s32 + - + name: id + type : u32 + - + name: address + type: nest + nested-attributes: fep-address + - + name: service-name + type: string + - + name: job + attributes: + - + name: id + type : u32 + - + name: address + type: nest + nested-attributes: fep-address + - + name: service-name + type: string + - + name: flist + type: nest + nested-attributes: flist + multi-attr: true + - + name: jlist + attributes: + - + name: job + type: nest + nested-attributes: job + multi-attr: true + - + name: jobs + attributes: + - + name: context-id + type: s32 + - + name: jlist + type: nest + nested-attributes: jlist operations: name-prefix: ultraeth-cmd- @@ -54,3 +167,37 @@ operations: request: attributes: - id + - + name: job-get + doc: dump uecon context jobs + attribute-set: jobs + dump: + request: + attributes: + - context-id + reply: + attributes: + - context-id + - jlist + - + name: job-new + doc: add a new job to uecon context + attribute-set: job-req + flags: [ admin-perm ] + do: + request: + attributes: + - context-id + - id + - address + - service-name + - + name: job-del + doc: delete a job in uecon context + attribute-set: job-req + flags: [ admin-perm ] + do: + request: + attributes: + - context-id + - id diff --git a/drivers/ultraeth/Makefile b/drivers/ultraeth/Makefile index 599d91d205c1..bf41a62273f9 100644 --- a/drivers/ultraeth/Makefile +++ b/drivers/ultraeth/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_ULTRAETH) += ultraeth.o -ultraeth-objs := uet_main.o uet_context.o uet_netlink.o +ultraeth-objs := uet_main.o uet_context.o uet_netlink.o uet_job.o diff --git a/drivers/ultraeth/uet_context.c b/drivers/ultraeth/uet_context.c index 2444fa3f35cd..3d738c02e992 100644 --- a/drivers/ultraeth/uet_context.c +++ b/drivers/ultraeth/uet_context.c @@ -102,10 +102,16 @@ int uet_context_create(int id) goto ctx_id_err; } + err = uet_jobs_init(&ctx->job_reg); + if (err) + goto ctx_jobs_err; + uet_context_link(ctx); return 0; +ctx_jobs_err: + uet_context_put_id(ctx); ctx_id_err: kfree(ctx); @@ -115,6 +121,7 @@ int uet_context_create(int id) static void __uet_context_destroy(struct uet_context *ctx) { uet_context_unlink(ctx); + uet_jobs_uninit(&ctx->job_reg); uet_context_put_id(ctx); kfree(ctx); } diff --git a/drivers/ultraeth/uet_job.c b/drivers/ultraeth/uet_job.c new file mode 100644 index 000000000000..3a55a0f70749 --- /dev/null +++ b/drivers/ultraeth/uet_job.c @@ -0,0 +1,455 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) + +#include +#include +#include +#include +#include + +#include "uet_netlink.h" + +static const struct rhashtable_params uet_job_registry_rht_params = { + .head_offset = offsetof(struct uet_job, rht_node), + .key_offset = offsetof(struct uet_job, id), + .key_len = sizeof(u32), + .nelem_hint = 128, + .automatic_shrinking = true, +}; + +int uet_jobs_init(struct uet_job_registry *jreg) +{ + int ret; + + mutex_init(&jreg->jobs_lock); + + ret = rhashtable_init(&jreg->jobs_hash, &uet_job_registry_rht_params); + if (ret) + mutex_destroy(&jreg->jobs_lock); + + return ret; +} + +static int __job_associate(struct uet_job *job, struct uet_fep *fep) +{ + lockdep_assert_held_once(&job->jreg->jobs_lock); + + if (rcu_access_pointer(job->fep)) + return -EBUSY; + + WRITE_ONCE(fep->job_id, job->id); + rcu_assign_pointer(job->fep, fep); + + return 0; +} + +/* disassociate and close all PDCs related to the job */ +static void __job_disassociate(struct uet_job *job) +{ + struct uet_fep *fep; + + fep = rcu_dereference_check(job->fep, + lockdep_is_held(&job->jreg->jobs_lock)); + if (!fep) + return; + + WRITE_ONCE(fep->job_id, 0); + RCU_INIT_POINTER(job->fep, NULL); + synchronize_rcu(); +} + +struct uet_job *uet_job_find(struct uet_job_registry *jreg, u32 id) +{ + return rhashtable_lookup_fast(&jreg->jobs_hash, &id, + uet_job_registry_rht_params); +} + +static struct uet_job *uet_job_find_svc_name(struct uet_job_registry *jreg, + char *service_name) +{ + struct uet_job *job; + + lockdep_assert_held_once(&jreg->jobs_lock); + + hlist_for_each_entry(job, &jreg->jobs_list, hnode) { + if (!strcmp(job->service_name, service_name)) + return job; + } + + return NULL; +} + +static void __uet_job_remove(struct uet_job *job) +{ + struct uet_job_registry *jreg = job->jreg; + + __job_disassociate(job); + hlist_del_init_rcu(&job->hnode); + rhashtable_remove_fast(&jreg->jobs_hash, &job->rht_node, + uet_job_registry_rht_params); + kfree_rcu(job, rcu); +} + +bool uet_job_remove(struct uet_job_registry *jreg, u32 job_id) +{ + bool removed = false; + struct uet_job *job; + + mutex_lock(&jreg->jobs_lock); + job = uet_job_find(jreg, job_id); + if (job) { + __uet_job_remove(job); + removed = true; + } + mutex_unlock(&jreg->jobs_lock); + + return removed; +} + +void uet_jobs_uninit(struct uet_job_registry *jreg) +{ + struct hlist_node *tmp; + struct uet_job *job; + + mutex_lock(&jreg->jobs_lock); + hlist_for_each_entry_safe(job, tmp, &jreg->jobs_list, hnode) + __uet_job_remove(job); + mutex_unlock(&jreg->jobs_lock); + + rhashtable_destroy(&jreg->jobs_hash); + rcu_barrier(); + mutex_destroy(&jreg->jobs_lock); +} + +struct uet_job *uet_job_create(struct uet_job_registry *jreg, + struct uet_job_ctrl_addr_req *job_req) +{ + struct uet_job *job; + int ret; + + if (job_req->job_id == 0) + return ERR_PTR(-EINVAL); + + mutex_lock(&jreg->jobs_lock); + if (uet_job_find_svc_name(jreg, job_req->service_name)) { + mutex_unlock(&jreg->jobs_lock); + return ERR_PTR(-EEXIST); + } + + job = kzalloc(sizeof(*job), GFP_KERNEL); + if (!job) + return ERR_PTR(-ENOMEM); + + job->jreg = jreg; + job->id = job_req->job_id; + strscpy(job->service_name, job_req->service_name, sizeof(job->service_name)); + + ret = rhashtable_lookup_insert_fast(&jreg->jobs_hash, &job->rht_node, + uet_job_registry_rht_params); + if (ret) { + kfree_rcu(job, rcu); + mutex_unlock(&jreg->jobs_lock); + return ERR_PTR(ret); + } + hlist_add_head_rcu(&job->hnode, &jreg->jobs_list); + mutex_unlock(&jreg->jobs_lock); + + return job; +} + +int uet_job_reg_associate(struct uet_job_registry *jreg, struct uet_fep *fep, + char *service_name) +{ + struct uet_job *job; + int ret = -ENOENT; + + mutex_lock(&jreg->jobs_lock); + job = uet_job_find_svc_name(jreg, service_name); + if (job) + ret = __job_associate(job, fep); + mutex_unlock(&jreg->jobs_lock); + + return ret; +} + +void uet_job_reg_disassociate(struct uet_job_registry *jreg, u32 job_id) +{ + struct uet_job *job; + + mutex_lock(&jreg->jobs_lock); + job = uet_job_find(jreg, job_id); + if (job) + __job_disassociate(job); + mutex_unlock(&jreg->jobs_lock); +} + +/* returns <0 (error) or 1 (queued the skb) */ +int uet_job_fep_queue_skb(struct uet_context *ctx, + u32 job_id, struct sk_buff *skb, + __be32 remote_fep_addr) +{ + struct uet_job *job = uet_job_find(&ctx->job_reg, job_id); + struct uet_fep *fep; + + if (!job) + return -ENOENT; + + fep = rcu_dereference(job->fep); + if (!fep) + return -ENODEV; + + skb_dst_drop(skb); + skb_queue_tail(&fep->rxq, skb); + + return 1; +} + +static int __nl_fep_addr_fill_one(struct sk_buff *skb, + const struct fep_in_address *fep_addr, + int fep_attr) +{ + struct nlattr *nest; + int attr, len; + + if (!fep_addr->family) + return 0; + + nest = nla_nest_start(skb, fep_attr); + if (!nest) + return -EMSGSIZE; + + switch (fep_addr->family) { + case AF_INET: + attr = ULTRAETH_A_FEP_IN_ADDR_IP; + len = sizeof(fep_addr->ip); + break; + case AF_INET6: + attr = ULTRAETH_A_FEP_IN_ADDR_IP6; + len = sizeof(fep_addr->ip6); + break; + default: + WARN_ON_ONCE(1); + nla_nest_cancel(skb, nest); + return 0; + } + + if (nla_put(skb, attr, len, &fep_addr->ip) || + nla_put_u16(skb, ULTRAETH_A_FEP_IN_ADDR_FAMILY, fep_addr->family)) { + nla_nest_cancel(skb, nest); + return -EMSGSIZE; + } + + nla_nest_end(skb, nest); + + return 0; +} + +static int __nl_uet_addr_fill_one(struct sk_buff *skb, + const struct fep_address *addr, int attr) +{ + struct nlattr *nest; + + nest = nla_nest_start(skb, attr); + if (!nest) + return -EMSGSIZE; + if (__nl_fep_addr_fill_one(skb, &addr->in_address, + ULTRAETH_A_FEP_ADDRESS_IN_ADDRESS) || + nla_put_u16(skb, ULTRAETH_A_FEP_ADDRESS_FLAGS, addr->flags) || + nla_put_u16(skb, ULTRAETH_A_FEP_ADDRESS_CAPS, addr->fep_caps) || + nla_put_u16(skb, ULTRAETH_A_FEP_ADDRESS_START_RESOURCE_INDEX, + addr->start_resource_index) || + nla_put_u16(skb, ULTRAETH_A_FEP_ADDRESS_NUM_RESOURCE_INDICES, + addr->num_resource_indices) || + nla_put_u32(skb, ULTRAETH_A_FEP_ADDRESS_INITIATOR_ID, + addr->initiator_id) || + nla_put_u16(skb, ULTRAETH_A_FEP_ADDRESS_PID_ON_FEP, + addr->pid_on_fep) || + nla_put_u8(skb, ULTRAETH_A_FEP_ADDRESS_VERSION, addr->version)) { + nla_nest_cancel(skb, nest); + return -EMSGSIZE; + } + nla_nest_end(skb, nest); + + return 0; +} + +static int __nl_fep_fill_one(struct sk_buff *skb, + const struct uet_fep *fep, int attr) +{ + struct nlattr *nest; + + nest = nla_nest_start(skb, attr); + if (!nest) + return -EMSGSIZE; + if (__nl_uet_addr_fill_one(skb, &fep->addr, ULTRAETH_A_FEP_ENTRY_ADDRESS)) { + nla_nest_cancel(skb, nest); + return -EMSGSIZE; + } + nla_nest_end(skb, nest); + + return 0; +} + +static int __nl_job_feps_fill(struct sk_buff *skb, const struct uet_fep *fep) +{ + struct nlattr *nest; + + nest = nla_nest_start(skb, ULTRAETH_A_JOB_FLIST); + if (!nest) + return -EMSGSIZE; + if (fep && __nl_fep_fill_one(skb, fep, ULTRAETH_A_FLIST_FEP)) { + nla_nest_cancel(skb, nest); + return -EMSGSIZE; + } + nla_nest_end(skb, nest); + + return 0; +} + +static int __nl_job_fill_one(struct sk_buff *skb, const struct uet_job *job) +{ + struct nlattr *nest; + + nest = nla_nest_start(skb, ULTRAETH_A_JLIST_JOB); + if (!nest) + return -EMSGSIZE; + + if (__nl_uet_addr_fill_one(skb, &job->addr, ULTRAETH_A_JOB_ADDRESS) || + nla_put_u32(skb, ULTRAETH_A_JOB_ID, job->id) || + nla_put_string(skb, ULTRAETH_A_JOB_SERVICE_NAME, job->service_name) || + __nl_job_feps_fill(skb, rcu_dereference(job->fep))) { + nla_nest_cancel(skb, nest); + return -EMSGSIZE; + } + + nla_nest_end(skb, nest); + return 0; +} + +int ultraeth_nl_job_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) +{ + const struct genl_info *info = genl_info_dump(cb); + int idx = 0, s_idx = cb->args[0], err; + struct uet_context *ctx; + struct uet_job *job; + struct nlattr *nest; + int context_id; + void *hdr; + + if (!info->attrs[ULTRAETH_A_JOBS_CONTEXT_ID]) { + NL_SET_ERR_MSG(info->extack, "context id must be specified"); + return -EINVAL; + } + + context_id = nla_get_s32(info->attrs[ULTRAETH_A_JOBS_CONTEXT_ID]); + ctx = uet_context_get_by_id(context_id); + if (!ctx) { + NL_SET_ERR_MSG(info->extack, "context doesn't exist"); + return -ENOENT; + } + + /* filled all, return 0 */ + if (s_idx == atomic_read(&ctx->job_reg.jobs_hash.nelems)) + goto out_put; + + err = -EMSGSIZE; + hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, + &ultraeth_nl_family, NLM_F_MULTI, ULTRAETH_CMD_JOB_GET); + if (!hdr) + goto out_put; + if (nla_put_s32(skb, ULTRAETH_A_JOBS_CONTEXT_ID, ctx->id)) + goto out_end; + nest = nla_nest_start(skb, ULTRAETH_A_JOBS_JLIST); + if (!nest) + goto out_end; + err = 0; + rcu_read_lock(); + hlist_for_each_entry_rcu(job, &ctx->job_reg.jobs_list, hnode) { + if (idx < s_idx) { + idx++; + continue; + } + err = __nl_job_fill_one(skb, job); + if (err) + break; + idx++; + } + cb->args[0] = idx; + rcu_read_unlock(); + nla_nest_end(skb, nest); +out_end: + genlmsg_end(skb, hdr); +out_put: + uet_context_put(ctx); + + return err ? err : skb->len; +} + +int ultraeth_nl_job_new_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct uet_job_ctrl_addr_req jreq; + struct uet_context *ctx; + int context_id, job_id; + struct uet_job *job; + char *service_name; + int ret = 0; + + if (!info->attrs[ULTRAETH_A_JOB_REQ_CONTEXT_ID]) { + NL_SET_ERR_MSG(info->extack, "context id must be specified"); + return -EINVAL; + } + if (!info->attrs[ULTRAETH_A_JOB_REQ_ID]) { + NL_SET_ERR_MSG(info->extack, "Job id must be specified"); + return -EINVAL; + } + if (!info->attrs[ULTRAETH_A_JOB_REQ_SERVICE_NAME]) { + NL_SET_ERR_MSG(info->extack, "Job service name must be specified"); + return -EINVAL; + } + service_name = nla_data(info->attrs[ULTRAETH_A_JOB_REQ_SERVICE_NAME]); + job_id = nla_get_u32(info->attrs[ULTRAETH_A_JOB_REQ_ID]); + context_id = nla_get_s32(info->attrs[ULTRAETH_A_JOB_REQ_CONTEXT_ID]); + ctx = uet_context_get_by_id(context_id); + if (!ctx) { + NL_SET_ERR_MSG(info->extack, "context doesn't exist"); + return -ENOENT; + } + + memset(&jreq, 0, sizeof(jreq)); + jreq.job_id = job_id; + strscpy(jreq.service_name, service_name, sizeof(jreq.service_name)); + job = uet_job_create(&ctx->job_reg, &jreq); + if (IS_ERR(job)) + ret = PTR_ERR(job); + + uet_context_put(ctx); + + return ret; +} + +int ultraeth_nl_job_del_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct uet_context *ctx; + bool destroyed = false; + int context_id, job_id; + + if (!info->attrs[ULTRAETH_A_JOB_REQ_CONTEXT_ID]) { + NL_SET_ERR_MSG(info->extack, "context id must be specified"); + return -EINVAL; + } + if (!info->attrs[ULTRAETH_A_JOB_REQ_ID]) { + NL_SET_ERR_MSG(info->extack, "Job id must be specified"); + return -EINVAL; + } + job_id = nla_get_u32(info->attrs[ULTRAETH_A_JOB_REQ_ID]); + context_id = nla_get_s32(info->attrs[ULTRAETH_A_JOB_REQ_CONTEXT_ID]); + ctx = uet_context_get_by_id(context_id); + if (!ctx) { + NL_SET_ERR_MSG(info->extack, "context doesn't exist"); + return -ENOENT; + } + + destroyed = uet_job_remove(&ctx->job_reg, job_id); + uet_context_put(ctx); + + return destroyed ? 0 : -ENOENT; +} diff --git a/drivers/ultraeth/uet_netlink.c b/drivers/ultraeth/uet_netlink.c index 39e4aa6092a9..7fdaf15e43e3 100644 --- a/drivers/ultraeth/uet_netlink.c +++ b/drivers/ultraeth/uet_netlink.c @@ -10,6 +10,25 @@ #include +/* Common nested types */ +const struct nla_policy ultraeth_fep_address_nl_policy[ULTRAETH_A_FEP_ADDRESS_VERSION + 1] = { + [ULTRAETH_A_FEP_ADDRESS_IN_ADDRESS] = NLA_POLICY_NESTED(ultraeth_fep_in_addr_nl_policy), + [ULTRAETH_A_FEP_ADDRESS_FLAGS] = { .type = NLA_U16, }, + [ULTRAETH_A_FEP_ADDRESS_CAPS] = { .type = NLA_U16, }, + [ULTRAETH_A_FEP_ADDRESS_START_RESOURCE_INDEX] = { .type = NLA_U16, }, + [ULTRAETH_A_FEP_ADDRESS_NUM_RESOURCE_INDICES] = { .type = NLA_U16, }, + [ULTRAETH_A_FEP_ADDRESS_INITIATOR_ID] = { .type = NLA_U32, }, + [ULTRAETH_A_FEP_ADDRESS_PID_ON_FEP] = { .type = NLA_U16, }, + [ULTRAETH_A_FEP_ADDRESS_PADDING] = { .type = NLA_U16, }, + [ULTRAETH_A_FEP_ADDRESS_VERSION] = { .type = NLA_U8, }, +}; + +const struct nla_policy ultraeth_fep_in_addr_nl_policy[ULTRAETH_A_FEP_IN_ADDR_FAMILY + 1] = { + [ULTRAETH_A_FEP_IN_ADDR_IP] = { .type = NLA_BINARY, }, + [ULTRAETH_A_FEP_IN_ADDR_IP6] = { .type = NLA_BINARY, }, + [ULTRAETH_A_FEP_IN_ADDR_FAMILY] = { .type = NLA_U16, }, +}; + /* ULTRAETH_CMD_CONTEXT_NEW - do */ static const struct nla_policy ultraeth_context_new_nl_policy[ULTRAETH_A_CONTEXT_ID + 1] = { [ULTRAETH_A_CONTEXT_ID] = NLA_POLICY_RANGE(NLA_S32, 0, 255), @@ -20,6 +39,25 @@ static const struct nla_policy ultraeth_context_del_nl_policy[ULTRAETH_A_CONTEXT [ULTRAETH_A_CONTEXT_ID] = NLA_POLICY_RANGE(NLA_S32, 0, 255), }; +/* ULTRAETH_CMD_JOB_GET - dump */ +static const struct nla_policy ultraeth_job_get_nl_policy[ULTRAETH_A_JOBS_CONTEXT_ID + 1] = { + [ULTRAETH_A_JOBS_CONTEXT_ID] = { .type = NLA_S32, }, +}; + +/* ULTRAETH_CMD_JOB_NEW - do */ +static const struct nla_policy ultraeth_job_new_nl_policy[ULTRAETH_A_JOB_REQ_SERVICE_NAME + 1] = { + [ULTRAETH_A_JOB_REQ_CONTEXT_ID] = { .type = NLA_S32, }, + [ULTRAETH_A_JOB_REQ_ID] = { .type = NLA_U32, }, + [ULTRAETH_A_JOB_REQ_ADDRESS] = NLA_POLICY_NESTED(ultraeth_fep_address_nl_policy), + [ULTRAETH_A_JOB_REQ_SERVICE_NAME] = { .type = NLA_NUL_STRING, }, +}; + +/* ULTRAETH_CMD_JOB_DEL - do */ +static const struct nla_policy ultraeth_job_del_nl_policy[ULTRAETH_A_JOB_REQ_ID + 1] = { + [ULTRAETH_A_JOB_REQ_CONTEXT_ID] = { .type = NLA_S32, }, + [ULTRAETH_A_JOB_REQ_ID] = { .type = NLA_U32, }, +}; + /* Ops table for ultraeth */ static const struct genl_split_ops ultraeth_nl_ops[] = { { @@ -41,6 +79,27 @@ static const struct genl_split_ops ultraeth_nl_ops[] = { .maxattr = ULTRAETH_A_CONTEXT_ID, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, + { + .cmd = ULTRAETH_CMD_JOB_GET, + .dumpit = ultraeth_nl_job_get_dumpit, + .policy = ultraeth_job_get_nl_policy, + .maxattr = ULTRAETH_A_JOBS_CONTEXT_ID, + .flags = GENL_CMD_CAP_DUMP, + }, + { + .cmd = ULTRAETH_CMD_JOB_NEW, + .doit = ultraeth_nl_job_new_doit, + .policy = ultraeth_job_new_nl_policy, + .maxattr = ULTRAETH_A_JOB_REQ_SERVICE_NAME, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = ULTRAETH_CMD_JOB_DEL, + .doit = ultraeth_nl_job_del_doit, + .policy = ultraeth_job_del_nl_policy, + .maxattr = ULTRAETH_A_JOB_REQ_ID, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, }; struct genl_family ultraeth_nl_family __ro_after_init = { diff --git a/drivers/ultraeth/uet_netlink.h b/drivers/ultraeth/uet_netlink.h index 9dd9df24513a..6e7226f39ddf 100644 --- a/drivers/ultraeth/uet_netlink.h +++ b/drivers/ultraeth/uet_netlink.h @@ -11,10 +11,18 @@ #include +/* Common nested types */ +extern const struct nla_policy ultraeth_fep_address_nl_policy[ULTRAETH_A_FEP_ADDRESS_VERSION + 1]; +extern const struct nla_policy ultraeth_fep_in_addr_nl_policy[ULTRAETH_A_FEP_IN_ADDR_FAMILY + 1]; + int ultraeth_nl_context_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb); int ultraeth_nl_context_new_doit(struct sk_buff *skb, struct genl_info *info); int ultraeth_nl_context_del_doit(struct sk_buff *skb, struct genl_info *info); +int ultraeth_nl_job_get_dumpit(struct sk_buff *skb, + struct netlink_callback *cb); +int ultraeth_nl_job_new_doit(struct sk_buff *skb, struct genl_info *info); +int ultraeth_nl_job_del_doit(struct sk_buff *skb, struct genl_info *info); extern struct genl_family ultraeth_nl_family; diff --git a/include/net/ultraeth/uet_context.h b/include/net/ultraeth/uet_context.h index 150ad2c9b456..7638c768597e 100644 --- a/include/net/ultraeth/uet_context.h +++ b/include/net/ultraeth/uet_context.h @@ -9,12 +9,15 @@ #include #include #include +#include struct uet_context { int id; refcount_t refcnt; wait_queue_head_t refcnt_wait; struct list_head list; + + struct uet_job_registry job_reg; }; struct uet_context *uet_context_get_by_id(int id); diff --git a/include/net/ultraeth/uet_job.h b/include/net/ultraeth/uet_job.h new file mode 100644 index 000000000000..fac1f0752a78 --- /dev/null +++ b/include/net/ultraeth/uet_job.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ + +#ifndef _UET_JOB_H +#define _UET_JOB_H + +#include +#include +#include +#include +#include + +struct uet_context; + +struct uet_job_registry { + struct mutex jobs_lock; + struct hlist_head jobs_list; + struct rhashtable jobs_hash; +}; + +struct uet_fep { + struct uet_context *context; + struct sk_buff_head rxq; + struct fep_address addr; + u32 job_id; +}; + +/** + * struct uet_job - single job + * + * @rht_node: link into the job registry's job hash table + * @hnode: link into the job registry's list + * @jreg: pointer to job registry (owner) + * @service_name: service name used for lookups on address req + * @addr: job specific address (XXX) + * @job_id: unique job id + * @rcu: used for freeing + * + * if @fep is set then the job is considered associated, i.e. there is + * an fd for the context's character device which is bound to this + * job (FEP) + */ +struct uet_job { + struct rhash_head rht_node; + struct hlist_node hnode; + + struct uet_job_registry *jreg; + + char service_name[UET_SVC_MAX_LEN]; + + struct fep_address addr; + struct uet_fep __rcu *fep; + + u32 id; + + struct rcu_head rcu; +}; + +struct uet_job_ctrl_addr_req { + char service_name[UET_SVC_MAX_LEN]; + struct fep_in_address address; + __u32 job_id; + __u32 os_pid; + __u8 flags; +}; + +int uet_jobs_init(struct uet_job_registry *jreg); +void uet_jobs_uninit(struct uet_job_registry *jreg); + +struct uet_job *uet_job_create(struct uet_job_registry *jreg, + struct uet_job_ctrl_addr_req *job_req); +bool uet_job_remove(struct uet_job_registry *jreg, u32 job_id); +struct uet_job *uet_job_find(struct uet_job_registry *jreg, u32 id); +void uet_job_reg_disassociate(struct uet_job_registry *jreg, u32 job_id); +int uet_job_reg_associate(struct uet_job_registry *jreg, struct uet_fep *fep, + char *service_name); +int uet_job_fep_queue_skb(struct uet_context *ctx, u32 job_id, + struct sk_buff *skb, __be32 remote_fep_addr); +#endif /* _UET_JOB_H */ diff --git a/include/uapi/linux/ultraeth.h b/include/uapi/linux/ultraeth.h new file mode 100644 index 000000000000..a6f244de6d75 --- /dev/null +++ b/include/uapi/linux/ultraeth.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ + +#ifndef _UAPI_LINUX_ULTRAETH_H +#define _UAPI_LINUX_ULTRAETH_H + +#include +#include + +#define UET_SVC_MAX_LEN 64 + +enum { + UET_ADDR_F_VALID_FEP_CAP = (1 << 0), + UET_ADDR_F_VALID_ADDR = (1 << 1), + UET_ADDR_F_VALID_PID_ON_FEP = (1 << 2), + UET_ADDR_F_VALID_RI = (1 << 3), + UET_ADDR_F_VALID_INIT_ID = (1 << 4), + UET_ADDR_F_ADDRESS_MODE = (1 << 5), + UET_ADDR_F_ADDRESS_TYPE = (1 << 6), + UET_ADDR_F_MTU_LIMITED = (1 << 7), +}; + +#define UET_ADDR_FLAG_IP_VER (1 << 6) + +struct fep_in_address { + union { + __be32 ip; + __u8 ip6[16]; + }; + __u16 family; +}; + +struct fep_address { + struct fep_in_address in_address; + + __u16 flags; + __u16 fep_caps; + __u16 start_resource_index; + __u16 num_resource_indices; + __u32 initiator_id; + __u16 pid_on_fep; + __u16 padding; + __u8 version; +}; +#endif /* _UAPI_LINUX_ULTRAETH_H */ diff --git a/include/uapi/linux/ultraeth_nl.h b/include/uapi/linux/ultraeth_nl.h index f3bdf8111623..d65521de196a 100644 --- a/include/uapi/linux/ultraeth_nl.h +++ b/include/uapi/linux/ultraeth_nl.h @@ -23,10 +23,86 @@ enum { ULTRAETH_A_CONTEXTS_MAX = (__ULTRAETH_A_CONTEXTS_MAX - 1) }; +enum { + ULTRAETH_A_FEP_IN_ADDR_IP = 1, + ULTRAETH_A_FEP_IN_ADDR_IP6, + ULTRAETH_A_FEP_IN_ADDR_FAMILY, + + __ULTRAETH_A_FEP_IN_ADDR_MAX, + ULTRAETH_A_FEP_IN_ADDR_MAX = (__ULTRAETH_A_FEP_IN_ADDR_MAX - 1) +}; + +enum { + ULTRAETH_A_FEP_ADDRESS_IN_ADDRESS = 1, + ULTRAETH_A_FEP_ADDRESS_FLAGS, + ULTRAETH_A_FEP_ADDRESS_CAPS, + ULTRAETH_A_FEP_ADDRESS_START_RESOURCE_INDEX, + ULTRAETH_A_FEP_ADDRESS_NUM_RESOURCE_INDICES, + ULTRAETH_A_FEP_ADDRESS_INITIATOR_ID, + ULTRAETH_A_FEP_ADDRESS_PID_ON_FEP, + ULTRAETH_A_FEP_ADDRESS_PADDING, + ULTRAETH_A_FEP_ADDRESS_VERSION, + + __ULTRAETH_A_FEP_ADDRESS_MAX, + ULTRAETH_A_FEP_ADDRESS_MAX = (__ULTRAETH_A_FEP_ADDRESS_MAX - 1) +}; + +enum { + ULTRAETH_A_FEP_ENTRY_ADDRESS = 1, + + __ULTRAETH_A_FEP_ENTRY_MAX, + ULTRAETH_A_FEP_ENTRY_MAX = (__ULTRAETH_A_FEP_ENTRY_MAX - 1) +}; + +enum { + ULTRAETH_A_FLIST_FEP = 1, + + __ULTRAETH_A_FLIST_MAX, + ULTRAETH_A_FLIST_MAX = (__ULTRAETH_A_FLIST_MAX - 1) +}; + +enum { + ULTRAETH_A_JOB_REQ_CONTEXT_ID = 1, + ULTRAETH_A_JOB_REQ_ID, + ULTRAETH_A_JOB_REQ_ADDRESS, + ULTRAETH_A_JOB_REQ_SERVICE_NAME, + + __ULTRAETH_A_JOB_REQ_MAX, + ULTRAETH_A_JOB_REQ_MAX = (__ULTRAETH_A_JOB_REQ_MAX - 1) +}; + +enum { + ULTRAETH_A_JOB_ID = 1, + ULTRAETH_A_JOB_ADDRESS, + ULTRAETH_A_JOB_SERVICE_NAME, + ULTRAETH_A_JOB_FLIST, + + __ULTRAETH_A_JOB_MAX, + ULTRAETH_A_JOB_MAX = (__ULTRAETH_A_JOB_MAX - 1) +}; + +enum { + ULTRAETH_A_JLIST_JOB = 1, + + __ULTRAETH_A_JLIST_MAX, + ULTRAETH_A_JLIST_MAX = (__ULTRAETH_A_JLIST_MAX - 1) +}; + +enum { + ULTRAETH_A_JOBS_CONTEXT_ID = 1, + ULTRAETH_A_JOBS_JLIST, + + __ULTRAETH_A_JOBS_MAX, + ULTRAETH_A_JOBS_MAX = (__ULTRAETH_A_JOBS_MAX - 1) +}; + enum { ULTRAETH_CMD_CONTEXT_GET = 1, ULTRAETH_CMD_CONTEXT_NEW, ULTRAETH_CMD_CONTEXT_DEL, + ULTRAETH_CMD_JOB_GET, + ULTRAETH_CMD_JOB_NEW, + ULTRAETH_CMD_JOB_DEL, __ULTRAETH_CMD_MAX, ULTRAETH_CMD_MAX = (__ULTRAETH_CMD_MAX - 1) From patchwork Thu Mar 6 23:01:55 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 14005475 X-Patchwork-Delegate: kuba@kernel.org Received: from mail-qv1-f54.google.com (mail-qv1-f54.google.com [209.85.219.54]) (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 DBE8527E1D4 for ; Thu, 6 Mar 2025 23:04:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302250; cv=none; b=Yi0CUGL4yUhIlwP106UthbIGlgbiOv1x15GgHpqBsVmD8rTLXkzV8eFROy/Nth+wEdB5+84wHsyktg5SKR9/lsayaC/NteLN1/2Kv5TdxRHaHEd00JsgcimxzgmUJYma5uTk/YvgtXrnWi4tqR+cH32ZAYor2spZC5sE3pHcMQk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302250; c=relaxed/simple; bh=R/kZ61XsnXa7JkZ9eNlhtUWSSS5M9Pt+qwZTdVsBeSY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VwWBCjMZ2M4OuXLrbRZ8GaBlyPHIqBxagYoD2xOnsYxWNbr0yIyrJvOBpK7DyHY3X7n+CY0NtVCxiwhviTjlznDT+oCrba0yPhwbCK+54Uec7GFNOY9MyeQizjahaVC4HMwdnQvWpMKj8T03wf6k01cyJC58lcd9Zx4lEobLllw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net; spf=pass smtp.mailfrom=enfabrica.net; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b=iHOUfJy/; arc=none smtp.client-ip=209.85.219.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b="iHOUfJy/" Received: by mail-qv1-f54.google.com with SMTP id 6a1803df08f44-6e8f6970326so9491066d6.0 for ; Thu, 06 Mar 2025 15:04:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enfabrica.net; s=google; t=1741302247; x=1741907047; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GYVU6L/OlKky7XJzEMEAkcQ6curT0ppBzRueik5Aobo=; b=iHOUfJy/w8cClRd/mG90zhN+RBiD27j8q26YQthuYv+9a4rAG/4noIwAVuHABeMALs E9hvNiDulnDkvltWPcurZUeFaxxJtNWG8gwcWkkHmc9k/yK2S2Qehj7f6QC1S20KQ4QZ 0YNTIh2xqXelBajYM5fZhQVmbCiHA93LBNe0vEbChqqPqmCS1CZJZBj13bUKuaShB8Q/ /I9rwzdn+ZJ4sHJlfSULJXP/mPtMx0rCFC8Tz7SoLz36O7v750kb7UfiEeT+JEamytmr k3W3Gf5zz517juZlfha4XSXnI+Ubd7DBwBYa5eE8dPBO2EZyD0GZLHOoL1qgRhVC/ZTO qqZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302247; x=1741907047; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GYVU6L/OlKky7XJzEMEAkcQ6curT0ppBzRueik5Aobo=; b=dERHG42ojXXzkZa9jr+5sv6JREAKfGcfOJ3bNMB+j3efWRklqI0HDwMUHOm5p1gUnX 9cuugf4ANe3jHiUjtBUw5wnr8PjQhLmhXoRM3R4ok2YcSQLRqgjRe0ifVycJkAxRUopW p21j5STElkZmRdeUaw+6b2yeC+WlLfuN/j7zszbUlvJrFHsN1ptJIm6Wui0x1LFclFhM 1COvRIcRTaj/bC75J95c7aXWbZ4txfE5lO7Hfnv6zhSoVKYnzLcdKi2v4thfU7b5SDHg DOzEzUgAHp0uw74CrKrnHkKY8idszDnaHMc5Z2vmYCQ3gQJxmFasNv7l2a0nV6AbIefd y97A== X-Gm-Message-State: AOJu0YxO2zumopwRxYcs0y+ZWOuVwZcIEmxvhxd0cOE7FnmsnF63AMzR DoBnijIj1h5izgrn84JKjVDqxcXw07SbXMC1co9eKMu8L0risUnFwj2JccuiGIxEb/OdV3iJ3va 49NjLZGXDKouTQ3y2GyIBVm3jBDDWypQyzy6xyJBVWRjwD2zIf9ctmc6co+AAAWzdG8WbFXIZ5V +CCW+WOel0Wsdv3LiVXN4qe3T7pMcnOzKNwYGQ/rkuJhQ= X-Gm-Gg: ASbGncvNscQ4E5thdZeeD0i/E0MJtHYhqdFkfNtVda+clihN+ejBSjre28BsyrZUmCQ EccKdF8zM65shzvykky1mt+nUQxAOI9Mr5ACx/ujWpZenYBBUussSA/+kuA+iu+q7eIcrGWc5Ka I7VZiY43rNlM/A+Jw/oMRLeGV6BPyEmT37LVzxrKJQUfyLKWzD3mIgm7AsYxHBgwEGfHHlQnnt3 Z1qHCoXibr8Fg7W1p/YGd8CPwnjcN15cqb/pyn46zJQQ3Il2QZdQM5yMqpJTsIXv88IBBzml4B5 IVKT3f7OHGM4tkrLBMUuAH0XildfR7FcGxF92ki75kGKPkXtJG3E4Fc3O5zcCDt+9GE/ X-Google-Smtp-Source: AGHT+IEtncuowmhdYM7QMeqyKKQ2lcV0+26jElV9BIp23ZCGTdI3+CIK1QRj81WnI/qAY2PW8pDtow== X-Received: by 2002:ad4:5cca:0:b0:6e8:f4c6:681a with SMTP id 6a1803df08f44-6e9005dc3eemr9045006d6.12.1741302247411; Thu, 06 Mar 2025 15:04:07 -0800 (PST) Received: from debil.. (78-154-15-142.ip.btc-net.bg. [78.154.15.142]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac256654fa6sm14971966b.93.2025.03.06.15.04.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Mar 2025 15:04:06 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: shrijeet@enfabrica.net, alex.badea@keysight.com, eric.davis@broadcom.com, rip.sohan@amd.com, dsahern@kernel.org, bmt@zurich.ibm.com, roland@enfabrica.net, nikolay@enfabrica.net, winston.liu@keysight.com, dan.mihailescu@keysight.com, kheib@redhat.com, parth.v.parikh@keysight.com, davem@redhat.com, ian.ziemba@hpe.com, andrew.tauferner@cornelisnetworks.com, welch@hpe.com, rakhahari.bhunia@keysight.com, kingshuk.mandal@keysight.com, linux-rdma@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com Subject: [RFC PATCH 05/13] drivers: ultraeth: add tunnel udp device support Date: Fri, 7 Mar 2025 01:01:55 +0200 Message-ID: <20250306230203.1550314-6-nikolay@enfabrica.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250306230203.1550314-1-nikolay@enfabrica.net> References: <20250306230203.1550314-1-nikolay@enfabrica.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Add UE UDP tunnel device (uecon) which is created for each context. It will be used to transmit and receive UE packets. Currently all packets are dropped. A default port of 5432 will be used at context creation. It can be changed at runtime when the net device is down. Signed-off-by: Nikolay Aleksandrov Signed-off-by: Alex Badea --- Documentation/netlink/specs/rt_link.yaml | 14 + Documentation/netlink/specs/ultraeth.yaml | 6 + drivers/ultraeth/Makefile | 3 +- drivers/ultraeth/uecon.c | 311 ++++++++++++++++++++++ drivers/ultraeth/uet_context.c | 12 +- drivers/ultraeth/uet_main.c | 19 +- include/net/ultraeth/uecon.h | 28 ++ include/net/ultraeth/uet_context.h | 2 +- include/uapi/linux/if_link.h | 8 + include/uapi/linux/ultraeth.h | 1 + include/uapi/linux/ultraeth_nl.h | 2 + 11 files changed, 402 insertions(+), 4 deletions(-) create mode 100644 drivers/ultraeth/uecon.c create mode 100644 include/net/ultraeth/uecon.h diff --git a/Documentation/netlink/specs/rt_link.yaml b/Documentation/netlink/specs/rt_link.yaml index 31238455f8e9..747231b1fd6d 100644 --- a/Documentation/netlink/specs/rt_link.yaml +++ b/Documentation/netlink/specs/rt_link.yaml @@ -2272,6 +2272,17 @@ attribute-sets: - name: tailroom type: u16 + - + name: linkinfo-uecon-attrs + name-prefix: ifla-uecon- + attributes: + - + name: context-id + type: u32 + - + name: port + type: u16 + byte-order: big-endian sub-messages: - @@ -2322,6 +2333,9 @@ sub-messages: - value: netkit attribute-set: linkinfo-netkit-attrs + - + value: uecon + attribute-set: linkinfo-uecon-attrs - name: linkinfo-member-data-msg formats: diff --git a/Documentation/netlink/specs/ultraeth.yaml b/Documentation/netlink/specs/ultraeth.yaml index e95c73a36892..847f748efa52 100644 --- a/Documentation/netlink/specs/ultraeth.yaml +++ b/Documentation/netlink/specs/ultraeth.yaml @@ -16,6 +16,12 @@ attribute-sets: checks: min: 0 max: 255 + - + name: netdev-ifindex + type: s32 + - + name: netdev-name + type: string - name: contexts attributes: diff --git a/drivers/ultraeth/Makefile b/drivers/ultraeth/Makefile index bf41a62273f9..0035023876ab 100644 --- a/drivers/ultraeth/Makefile +++ b/drivers/ultraeth/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_ULTRAETH) += ultraeth.o -ultraeth-objs := uet_main.o uet_context.o uet_netlink.o uet_job.o +ultraeth-objs := uet_main.o uet_context.o uet_netlink.o uet_job.o \ + uecon.o diff --git a/drivers/ultraeth/uecon.c b/drivers/ultraeth/uecon.c new file mode 100644 index 000000000000..4b74680700af --- /dev/null +++ b/drivers/ultraeth/uecon.c @@ -0,0 +1,311 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct nla_policy uecon_ndev_policy[IFLA_UECON_MAX + 1] = { + [IFLA_UECON_CONTEXT_ID] = { .type = NLA_REJECT, + .reject_message = "Domain id attribute is read-only" }, + [IFLA_UECON_PORT] = { .type = NLA_BE16 }, +}; + +static netdev_tx_t uecon_ndev_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct uecon_ndev_priv *uecpriv = netdev_priv(dev); + struct ip_tunnel_info *info; + int err, min_headroom; + struct socket *sock; + struct rtable *rt; + bool use_cache; + __be32 saddr; + __be16 sport; + + rcu_read_lock(); + sock = rcu_dereference(uecpriv->sock); + if (!sock) + goto out_err; + info = skb_tunnel_info(skb); + if (!info) + goto out_err; + use_cache = ip_tunnel_dst_cache_usable(skb, info); + sport = uecpriv->udp_port; + rt = udp_tunnel_dst_lookup(skb, dev, dev_net(dev), 0, &saddr, + &info->key, sport, + info->key.tp_dst, info->key.tos, + use_cache ? &info->dst_cache : NULL); + if (IS_ERR(rt)) { + if (PTR_ERR(rt) == -ELOOP) + dev->stats.collisions++; + else if (PTR_ERR(rt) == -ENETUNREACH) + dev->stats.tx_carrier_errors++; + + goto out_err; + } + + skb_tunnel_check_pmtu(skb, &rt->dst, + sizeof(struct iphdr) + sizeof(struct udphdr), + false); + skb_scrub_packet(skb, false); + + min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len + + sizeof(struct iphdr) + sizeof(struct udphdr); + err = skb_cow_head(skb, min_headroom); + if (unlikely(err)) { + dst_release(&rt->dst); + goto out_err; + } + + err = udp_tunnel_handle_offloads(skb, false); + if (err) { + dst_release(&rt->dst); + goto out_err; + } + + skb_reset_mac_header(skb); + skb_set_inner_protocol(skb, skb->protocol); + + udp_tunnel_xmit_skb(rt, sock->sk, skb, saddr, + info->key.u.ipv4.dst, info->key.tos, + ip4_dst_hoplimit(&rt->dst), 0, + sport, info->key.tp_dst, + false, false); + rcu_read_unlock(); + + return NETDEV_TX_OK; + +out_err: + rcu_read_unlock(); + dev_kfree_skb(skb); + dev->stats.tx_errors++; + + return NETDEV_TX_OK; +} + +static int uecon_ndev_encap_recv(struct sock *sk, struct sk_buff *skb) +{ + struct uecon_ndev_priv *uecpriv; + int len; + + uecpriv = rcu_dereference_sk_user_data(sk); + if (!uecpriv) + goto drop; + + if (skb->protocol != htons(ETH_P_IP)) + goto drop; + + /* we assume [ tnl ip hdr ] [ tnl udp hdr ] [ pdc hdr ] [ ses hdr ] */ + if (iptunnel_pull_header(skb, sizeof(struct udphdr), htons(ETH_P_802_3), false)) + goto drop_count; + + skb_reset_mac_header(skb); + skb_reset_network_header(skb); + skb->pkt_type = PACKET_HOST; + skb->dev = uecpriv->dev; + len = skb->len; + consume_skb(skb); + dev_sw_netstats_rx_add(uecpriv->dev, len); + + return 0; + +drop_count: + dev_core_stats_rx_dropped_inc(uecpriv->dev); +drop: + kfree_skb(skb); + return 0; +} + +static int uecon_ndev_err_lookup(struct sock *sk, struct sk_buff *skb) +{ + return 0; +} + +static struct socket *uecon_ndev_create_sock(struct net_device *dev) +{ + struct uecon_ndev_priv *uecpriv = netdev_priv(dev); + struct udp_port_cfg udp_conf; + struct socket *sock; + int err; + + memset(&udp_conf, 0, sizeof(udp_conf)); + udp_conf.family = AF_INET; + udp_conf.local_udp_port = uecpriv->udp_port; + err = udp_sock_create(dev_net(dev), &udp_conf, &sock); + if (err < 0) + return ERR_PTR(err); + + udp_allow_gso(sock->sk); + + return sock; +} + +static int uecon_ndev_open(struct net_device *dev) +{ + struct uecon_ndev_priv *uecpriv = netdev_priv(dev); + struct udp_tunnel_sock_cfg tunnel_cfg; + struct socket *sock; + + sock = uecon_ndev_create_sock(dev); + if (IS_ERR(sock)) + return PTR_ERR(sock); + memset(&tunnel_cfg, 0, sizeof(tunnel_cfg)); + tunnel_cfg.sk_user_data = uecpriv; + tunnel_cfg.encap_type = 1; + tunnel_cfg.encap_rcv = uecon_ndev_encap_recv; + tunnel_cfg.encap_err_lookup = uecon_ndev_err_lookup; + setup_udp_tunnel_sock(dev_net(dev), sock, &tunnel_cfg); + + rcu_assign_pointer(uecpriv->sock, sock); + + return 0; +} + +static int uecon_ndev_stop(struct net_device *dev) +{ + struct uecon_ndev_priv *uecpriv = netdev_priv(dev); + struct socket *sock = rtnl_dereference(uecpriv->sock); + + rcu_assign_pointer(uecpriv->sock, NULL); + synchronize_rcu(); + udp_tunnel_sock_release(sock); + + return 0; +} + +const struct net_device_ops uecon_netdev_ops = { + .ndo_open = uecon_ndev_open, + .ndo_stop = uecon_ndev_stop, + .ndo_start_xmit = uecon_ndev_xmit, + .ndo_get_stats64 = dev_get_tstats64, +}; + +static const struct device_type uecon_ndev_type = { + .name = "uecon", +}; + +static void uecon_ndev_setup(struct net_device *dev) +{ + struct uecon_ndev_priv *uecpriv = netdev_priv(dev); + + dev->netdev_ops = &uecon_netdev_ops; + SET_NETDEV_DEVTYPE(dev, &uecon_ndev_type); + + dev->features |= NETIF_F_VLAN_CHALLENGED | NETIF_F_SG | NETIF_F_HW_CSUM; + dev->features |= NETIF_F_FRAGLIST | NETIF_F_RXCSUM | NETIF_F_GSO_SOFTWARE; + + dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_FRAGLIST; + dev->hw_features |= NETIF_F_RXCSUM | NETIF_F_GSO_SOFTWARE; + + dev->priv_flags |= IFF_NO_QUEUE; + + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->type = ARPHRD_NONE; + + dev->min_mtu = IPV4_MIN_MTU; + /* No header for the time being, account for it later */ + dev->max_mtu = IP_MAX_MTU; + dev->mtu = ETH_DATA_LEN; + dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; + + netif_keep_dst(dev); + uecpriv->dev = dev; +} + +static int uecon_ndev_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[], + struct netlink_ext_ack *extack) +{ + if (dev->flags & IFF_UP) { + NL_SET_ERR_MSG_MOD(extack, "Cannot change uecon settings while the device is up"); + return -EBUSY; + } + + if (tb[IFLA_UECON_PORT]) { + struct uecon_ndev_priv *uecpriv = netdev_priv(dev); + + uecpriv->udp_port = nla_get_be16(tb[IFLA_UECON_PORT]); + } + + return 0; +} + +static size_t uecon_ndev_get_size(const struct net_device *dev) +{ + return nla_total_size(sizeof(__u32)) + /* IFLA_UECON_CONTEXT_ID */ + nla_total_size(sizeof(__be16)) + /* IFLA_UECON_PORT */ + 0; +} + +static int uecon_ndev_fill_info(struct sk_buff *skb, const struct net_device *dev) +{ + struct uecon_ndev_priv *uecpriv = netdev_priv(dev); + + if (nla_put_u32(skb, IFLA_UECON_CONTEXT_ID, uecpriv->context->id) || + nla_put_be16(skb, IFLA_UECON_PORT, uecpriv->udp_port)) + return -EMSGSIZE; + + return 0; +} + +static struct rtnl_link_ops uecon_netdev_link_ops __read_mostly = { + .kind = "uecon", + .priv_size = sizeof(struct uecon_ndev_priv), + .setup = uecon_ndev_setup, + .get_size = uecon_ndev_get_size, + .fill_info = uecon_ndev_fill_info, + .changelink = uecon_ndev_changelink, + .policy = uecon_ndev_policy, + .maxtype = IFLA_UECON_MAX +}; + +int uecon_netdev_init(struct uet_context *ctx) +{ + struct net *net = current->nsproxy->net_ns; + struct uecon_ndev_priv *priv; + char ifname[IFNAMSIZ]; + int ret; + + snprintf(ifname, IFNAMSIZ, "uecon%d", ctx->id); + ctx->netdev = alloc_netdev(sizeof(struct uecon_ndev_priv), ifname, + NET_NAME_PREDICTABLE, uecon_ndev_setup); + if (!ctx->netdev) + return -ENOMEM; + priv = netdev_priv(ctx->netdev); + + priv->context = ctx; + priv->dev = ctx->netdev; + priv->udp_port = htons(UECON_DEFAULT_PORT); + ctx->netdev->rtnl_link_ops = &uecon_netdev_link_ops; + dev_net_set(ctx->netdev, net); + + ret = register_netdev(ctx->netdev); + if (ret) { + free_netdev(ctx->netdev); + ctx->netdev = NULL; + } + + return ret; +} + +void uecon_netdev_uninit(struct uet_context *ctx) +{ + unregister_netdev(ctx->netdev); + free_netdev(ctx->netdev); + ctx->netdev = NULL; +} + +int uecon_rtnl_link_register(void) +{ + return rtnl_link_register(&uecon_netdev_link_ops); +} + +void uecon_rtnl_link_unregister(void) +{ + rtnl_link_unregister(&uecon_netdev_link_ops); +} diff --git a/drivers/ultraeth/uet_context.c b/drivers/ultraeth/uet_context.c index 3d738c02e992..e0d276cb1942 100644 --- a/drivers/ultraeth/uet_context.c +++ b/drivers/ultraeth/uet_context.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) #include +#include #include "uet_netlink.h" #define MAX_CONTEXT_ID 256 @@ -106,10 +107,16 @@ int uet_context_create(int id) if (err) goto ctx_jobs_err; + err = uecon_netdev_init(ctx); + if (err) + goto ctx_netdev_err; + uet_context_link(ctx); return 0; +ctx_netdev_err: + uet_jobs_uninit(&ctx->job_reg); ctx_jobs_err: uet_context_put_id(ctx); ctx_id_err: @@ -121,6 +128,7 @@ int uet_context_create(int id) static void __uet_context_destroy(struct uet_context *ctx) { uet_context_unlink(ctx); + uecon_netdev_uninit(ctx); uet_jobs_uninit(&ctx->job_reg); uet_context_put_id(ctx); kfree(ctx); @@ -166,7 +174,9 @@ static int __nl_ctx_fill_one(struct sk_buff *skb, if (!hdr) return -EMSGSIZE; - if (nla_put_s32(skb, ULTRAETH_A_CONTEXT_ID, ctx->id)) + if (nla_put_s32(skb, ULTRAETH_A_CONTEXT_ID, ctx->id) || + nla_put_s32(skb, ULTRAETH_A_CONTEXT_NETDEV_IFINDEX, ctx->netdev->ifindex) || + nla_put_string(skb, ULTRAETH_A_CONTEXT_NETDEV_NAME, ctx->netdev->name)) goto out_err; genlmsg_end(skb, hdr); diff --git a/drivers/ultraeth/uet_main.c b/drivers/ultraeth/uet_main.c index 0ec1dc74abbb..c37f65978ecf 100644 --- a/drivers/ultraeth/uet_main.c +++ b/drivers/ultraeth/uet_main.c @@ -4,18 +4,35 @@ #include #include #include +#include #include "uet_netlink.h" static int __init uet_init(void) { - return genl_register_family(&ultraeth_nl_family); + int err; + + err = genl_register_family(&ultraeth_nl_family); + if (err) + goto out_err; + + err = uecon_rtnl_link_register(); + if (err) + goto rtnl_link_err; + + return 0; + +rtnl_link_err: + genl_unregister_family(&ultraeth_nl_family); +out_err: + return err; } static void __exit uet_exit(void) { genl_unregister_family(&ultraeth_nl_family); uet_context_destroy_all(); + uecon_rtnl_link_unregister(); } module_init(uet_init); diff --git a/include/net/ultraeth/uecon.h b/include/net/ultraeth/uecon.h new file mode 100644 index 000000000000..6316a0557b1f --- /dev/null +++ b/include/net/ultraeth/uecon.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ + +#ifndef _UECON_H +#define _UECON_H +#include + +#define UECON_DEFAULT_PORT 5432 + +struct socket; +struct net_device; + +struct uecon_ndev_priv { + struct uet_context *context; + struct socket __rcu *sock; + struct net_device *dev; + __be16 udp_port; +}; + +extern const struct net_device_ops uecon_netdev_ops; +int uecon_netdev_init(struct uet_context *ctx); +void uecon_netdev_uninit(struct uet_context *ctx); + +int uecon_rtnl_link_register(void); +void uecon_rtnl_link_unregister(void); + +int uecon_netdev_register(void); +void uecon_netdev_unregister(void); +#endif /* _UECON_H */ diff --git a/include/net/ultraeth/uet_context.h b/include/net/ultraeth/uet_context.h index 7638c768597e..8210f69a1571 100644 --- a/include/net/ultraeth/uet_context.h +++ b/include/net/ultraeth/uet_context.h @@ -17,6 +17,7 @@ struct uet_context { wait_queue_head_t refcnt_wait; struct list_head list; + struct net_device *netdev; struct uet_job_registry job_reg; }; @@ -26,5 +27,4 @@ void uet_context_put(struct uet_context *ses_pl); int uet_context_create(int id); bool uet_context_destroy(int id); void uet_context_destroy_all(void); - #endif /* _UET_CONTEXT_H */ diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 318386cc5b0d..1ba189ecf9da 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -1986,4 +1986,12 @@ enum { #define IFLA_DSA_MAX (__IFLA_DSA_MAX - 1) +enum { + IFLA_UECON_UNSPEC, + IFLA_UECON_CONTEXT_ID, + IFLA_UECON_PORT, + __IFLA_UECON_MAX +}; + +#define IFLA_UECON_MAX (__IFLA_UECON_MAX - 1) #endif /* _UAPI_LINUX_IF_LINK_H */ diff --git a/include/uapi/linux/ultraeth.h b/include/uapi/linux/ultraeth.h index a6f244de6d75..a4ac25455aa0 100644 --- a/include/uapi/linux/ultraeth.h +++ b/include/uapi/linux/ultraeth.h @@ -6,6 +6,7 @@ #include #include +#define UET_DEFAULT_PORT 5432 #define UET_SVC_MAX_LEN 64 enum { diff --git a/include/uapi/linux/ultraeth_nl.h b/include/uapi/linux/ultraeth_nl.h index d65521de196a..515044022906 100644 --- a/include/uapi/linux/ultraeth_nl.h +++ b/include/uapi/linux/ultraeth_nl.h @@ -11,6 +11,8 @@ enum { ULTRAETH_A_CONTEXT_ID = 1, + ULTRAETH_A_CONTEXT_NETDEV_IFINDEX, + ULTRAETH_A_CONTEXT_NETDEV_NAME, __ULTRAETH_A_CONTEXT_MAX, ULTRAETH_A_CONTEXT_MAX = (__ULTRAETH_A_CONTEXT_MAX - 1) From patchwork Thu Mar 6 23:01:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 14005477 X-Patchwork-Delegate: kuba@kernel.org Received: from mail-qv1-f42.google.com (mail-qv1-f42.google.com [209.85.219.42]) (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 1EE2C27EC79 for ; Thu, 6 Mar 2025 23:04:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302254; cv=none; b=JDjZKIYl35jIO3JKKNdeHr4ZTrybDXE2RLN6S+dck6tET5KaBXamcer7AcAmRhiuly1+gp8n6xgtt6hCEdIGsyJVdGyjDlFOYEnURzebbNodmcbmsKZBBb6uyNjfXNcCU0gKDLioRqRpPh5TSX4Nb7Ap6NUJlwlwY195mQk0Fgw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302254; c=relaxed/simple; bh=rhAdls14aXXr+B3banKqLmvbLqUuZInVd88ZhCUc3TA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hNDu7PUbdq4SYnL59htFov4SZR21W9R0Y60Yh/Dsb3UZXrL8n74CraKjD+J4Vs+hRULZdVOzXmfaefr1kSFYuzUoH83e6FDuzP7qX9DrQ4olaxUcQ2Vk8v+sqEHBa0XSIJ3w8COPQ16r9hjLty9wItUkkQojW5OmL17MGe+vm7c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net; spf=pass smtp.mailfrom=enfabrica.net; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b=E4MzcdNn; arc=none smtp.client-ip=209.85.219.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b="E4MzcdNn" Received: by mail-qv1-f42.google.com with SMTP id 6a1803df08f44-6e8f06e13a4so19127926d6.0 for ; Thu, 06 Mar 2025 15:04:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enfabrica.net; s=google; t=1741302250; x=1741907050; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8fIFQBWAbnslNfcoBo9zTprT+wxmi9gtYJ6rGux2+U8=; b=E4MzcdNn2dU+wC9TgXT2sdpL8CZCPSA7NxPfW82EoVDquyS0LSKIKQQG+9RD5rcp/G gsyfA8eVWOcy6Qqo0ExsfZ7Io3rI0VyfYP4JnSiV3UlOSxQ7h9nHLThgB4i22LxIb0Qv 3QAOypGWBdvrrottBJTlJPXanpT8RKTWujCbCDC0Q7A6qmspRfh+WYGdImHCvXWCu9wy Fwu8cF4gooiFXpcjnDRsGvinZlwT5ZxXEIYL3iRc7Z+U9B0uga/kk/6JBp6LBteaRNA0 2NXJ7/U7GzsWPqtuZoIyguyFYss2//vJ3y5DS/jLyBQIIma/QNhTMUsYbxQLJArchDGr YBew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302250; x=1741907050; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8fIFQBWAbnslNfcoBo9zTprT+wxmi9gtYJ6rGux2+U8=; b=KhT73l58MavNu/pUCyV5dPXuGLVNRFlx8l4Nm/p1fLhkc5MLNqPHdtCwJaW3m+SA/S VSW8+36bTRLtAGBSFA4IqHpOBBQhaMtYsJF+uJraOLkpznRneRz4XKLHwKI/NcGwe7Ky XM8g/ynDH8+xgWsKXYCSfdWUAupH/zzvBCtRRKSpLaxHDLL/naqw/ba5vxz2pE8wLxGh tlXrepI36wboKzW0nud+tpxetInEBY7g3FScc7NbJy4f+RN/svOqA37ns7RelXaQknmE 16S57HsEJQ1B79NfUXNkIgEtaiBSjM4Joufl8UcfyMgEZV+kCNTCxCpDZFcK5XBe2Hin i4Kg== X-Gm-Message-State: AOJu0YyCjht150UOhyjuXUZ5XDk2eWbw9tPHyz/r/0/5qPYJXm4xSy9G nVXPQAML157wKzrXlwHDSVw+wN6pgffwSm6kU1JijVbq/HquYvGoH2czlthmqd+NH3+RPPyUHvp 0cZ1mILDwFf9cg/UdfbhOjGGmFvhhEpwRrcSsZrBYTFO+ep7rOcM/zbwoP6GcL8T+2bpgFZAV41 MqzATipzoXyqB7gcROn4m/8EUENw0CYyfmxYFPXrUkBAw= X-Gm-Gg: ASbGncs4VJIY+E7Fy46K3tzFUZ9s7EbR3mWLLHM0ihura6irlPS5HkhkFHaadbh6+FJ EQKuAg5F0l4bGYIQ+D3U8jXn0Sh9XipDPplGSxIB4RWsshtLsB6vUuGp+XAciUXG4zucfd4/gw3 BCja70xDRRd8AQ2QwiJRLqoRyhpQqJU/7MS514z1CcZWI4pevMcKp1lgZdcdJ3A8yEnPIKPdRFW 7mgSo+mShBgcYeiLxS6maOQ4WyDO9Sl9m+9Gah3bf2Iwl7lgAu0UR8F59M8MK/gWFclW3twQ2v+ VbK6gqCgkv6C3YlxEjvAYpviaJuAYicsb+Zpnz+db4Pk+CmEA9wb99f3b4MD4s2QuIY4 X-Google-Smtp-Source: AGHT+IE8RTkpccWKR7R9PIQ42rOgsV9xy4dpzuu3Ea5ud+SklRJR2rjnOUq4KV2vowlIyWuc7cqZ0Q== X-Received: by 2002:a05:6214:2606:b0:6e4:31d9:b357 with SMTP id 6a1803df08f44-6e8f46b019cmr93542806d6.1.1741302249312; Thu, 06 Mar 2025 15:04:09 -0800 (PST) Received: from debil.. (78-154-15-142.ip.btc-net.bg. [78.154.15.142]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac256654fa6sm14971966b.93.2025.03.06.15.04.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Mar 2025 15:04:08 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: shrijeet@enfabrica.net, alex.badea@keysight.com, eric.davis@broadcom.com, rip.sohan@amd.com, dsahern@kernel.org, bmt@zurich.ibm.com, roland@enfabrica.net, nikolay@enfabrica.net, winston.liu@keysight.com, dan.mihailescu@keysight.com, kheib@redhat.com, parth.v.parikh@keysight.com, davem@redhat.com, ian.ziemba@hpe.com, andrew.tauferner@cornelisnetworks.com, welch@hpe.com, rakhahari.bhunia@keysight.com, kingshuk.mandal@keysight.com, linux-rdma@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com Subject: [RFC PATCH 06/13] drivers: ultraeth: add initial PDS infrastructure Date: Fri, 7 Mar 2025 01:01:56 +0200 Message-ID: <20250306230203.1550314-7-nikolay@enfabrica.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250306230203.1550314-1-nikolay@enfabrica.net> References: <20250306230203.1550314-1-nikolay@enfabrica.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Add PDS structures as described in the specifications and helpers to access their fields which are also exposed to user-space. Add initial kernel PDS structures and routines to manage PDCs. PDC ids are random and allocated when a PDC gets created. Each PDC instance has a spinlock to protect it, lookups are done with RCU using two rhashtables - one for our local PDC ids - one for endpoints Receiving a packet currently is a noop. Signed-off-by: Nikolay Aleksandrov Signed-off-by: Alex Badea --- drivers/ultraeth/Makefile | 2 +- drivers/ultraeth/uecon.c | 23 +- drivers/ultraeth/uet_context.c | 7 + drivers/ultraeth/uet_job.c | 1 + drivers/ultraeth/uet_pdc.c | 124 ++++++++++ drivers/ultraeth/uet_pds.c | 159 +++++++++++++ include/net/ultraeth/uet_context.h | 14 ++ include/net/ultraeth/uet_pdc.h | 79 +++++++ include/net/ultraeth/uet_pds.h | 93 ++++++++ include/uapi/linux/ultraeth.h | 354 +++++++++++++++++++++++++++++ 10 files changed, 850 insertions(+), 6 deletions(-) create mode 100644 drivers/ultraeth/uet_pdc.c create mode 100644 drivers/ultraeth/uet_pds.c create mode 100644 include/net/ultraeth/uet_pdc.h create mode 100644 include/net/ultraeth/uet_pds.h diff --git a/drivers/ultraeth/Makefile b/drivers/ultraeth/Makefile index 0035023876ab..f2d6a8569dbf 100644 --- a/drivers/ultraeth/Makefile +++ b/drivers/ultraeth/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_ULTRAETH) += ultraeth.o ultraeth-objs := uet_main.o uet_context.o uet_netlink.o uet_job.o \ - uecon.o + uecon.o uet_pdc.o uet_pds.o diff --git a/drivers/ultraeth/uecon.c b/drivers/ultraeth/uecon.c index 4b74680700af..38f930bf93ec 100644 --- a/drivers/ultraeth/uecon.c +++ b/drivers/ultraeth/uecon.c @@ -42,9 +42,9 @@ static netdev_tx_t uecon_ndev_xmit(struct sk_buff *skb, struct net_device *dev) use_cache ? &info->dst_cache : NULL); if (IS_ERR(rt)) { if (PTR_ERR(rt) == -ELOOP) - dev->stats.collisions++; + DEV_STATS_INC(dev, collisions); else if (PTR_ERR(rt) == -ENETUNREACH) - dev->stats.tx_carrier_errors++; + DEV_STATS_INC(dev, tx_carrier_errors); goto out_err; } @@ -83,7 +83,7 @@ static netdev_tx_t uecon_ndev_xmit(struct sk_buff *skb, struct net_device *dev) out_err: rcu_read_unlock(); dev_kfree_skb(skb); - dev->stats.tx_errors++; + DEV_STATS_INC(dev, tx_errors); return NETDEV_TX_OK; } @@ -91,7 +91,11 @@ static netdev_tx_t uecon_ndev_xmit(struct sk_buff *skb, struct net_device *dev) static int uecon_ndev_encap_recv(struct sock *sk, struct sk_buff *skb) { struct uecon_ndev_priv *uecpriv; - int len; + __be32 saddr, daddr; + unsigned int len; + __be16 dport; + __u8 tos; + int ret; uecpriv = rcu_dereference_sk_user_data(sk); if (!uecpriv) @@ -100,6 +104,11 @@ static int uecon_ndev_encap_recv(struct sock *sk, struct sk_buff *skb) if (skb->protocol != htons(ETH_P_IP)) goto drop; + saddr = ip_hdr(skb)->saddr; + daddr = ip_hdr(skb)->daddr; + dport = udp_hdr(skb)->source; + tos = ip_hdr(skb)->tos; + /* we assume [ tnl ip hdr ] [ tnl udp hdr ] [ pdc hdr ] [ ses hdr ] */ if (iptunnel_pull_header(skb, sizeof(struct udphdr), htons(ETH_P_802_3), false)) goto drop_count; @@ -109,7 +118,11 @@ static int uecon_ndev_encap_recv(struct sock *sk, struct sk_buff *skb) skb->pkt_type = PACKET_HOST; skb->dev = uecpriv->dev; len = skb->len; - consume_skb(skb); + ret = uet_pds_rx(&uecpriv->context->pds, skb, daddr, saddr, dport, tos); + if (ret < 0) + goto drop_count; + else if (ret == 0) + consume_skb(skb); dev_sw_netstats_rx_add(uecpriv->dev, len); return 0; diff --git a/drivers/ultraeth/uet_context.c b/drivers/ultraeth/uet_context.c index e0d276cb1942..6bdd72344e01 100644 --- a/drivers/ultraeth/uet_context.c +++ b/drivers/ultraeth/uet_context.c @@ -107,6 +107,10 @@ int uet_context_create(int id) if (err) goto ctx_jobs_err; + err = uet_pds_init(&ctx->pds); + if (err) + goto ctx_pds_err; + err = uecon_netdev_init(ctx); if (err) goto ctx_netdev_err; @@ -116,6 +120,8 @@ int uet_context_create(int id) return 0; ctx_netdev_err: + uet_pds_uninit(&ctx->pds); +ctx_pds_err: uet_jobs_uninit(&ctx->job_reg); ctx_jobs_err: uet_context_put_id(ctx); @@ -129,6 +135,7 @@ static void __uet_context_destroy(struct uet_context *ctx) { uet_context_unlink(ctx); uecon_netdev_uninit(ctx); + uet_pds_uninit(&ctx->pds); uet_jobs_uninit(&ctx->job_reg); uet_context_put_id(ctx); kfree(ctx); diff --git a/drivers/ultraeth/uet_job.c b/drivers/ultraeth/uet_job.c index 3a55a0f70749..4a421dd8e86c 100644 --- a/drivers/ultraeth/uet_job.c +++ b/drivers/ultraeth/uet_job.c @@ -55,6 +55,7 @@ static void __job_disassociate(struct uet_job *job) WRITE_ONCE(fep->job_id, 0); RCU_INIT_POINTER(job->fep, NULL); synchronize_rcu(); + uet_pds_clean_job(&fep->context->pds, job->id); } struct uet_job *uet_job_find(struct uet_job_registry *jreg, u32 id) diff --git a/drivers/ultraeth/uet_pdc.c b/drivers/ultraeth/uet_pdc.c new file mode 100644 index 000000000000..47cf4c3dee04 --- /dev/null +++ b/drivers/ultraeth/uet_pdc.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) + +#include +#include + +#include +#include + +/* use the approach as nf nat, try a few rounds starting at random offset */ +static bool uet_pdc_id_get(struct uet_pdc *pdc) +{ + int attempts = UET_PDC_ID_MAX_ATTEMPTS, i; + + pdc->spdcid = get_random_u16(); +try_again: + for (i = 0; i < attempts; i++, pdc->spdcid++) { + if (uet_pds_pdcid_insert(pdc) == 0) + return true; + } + + if (attempts > 16) { + attempts /= 2; + pdc->spdcid = get_random_u16(); + goto try_again; + } + + return false; +} + +struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, + u16 dpdcid, u16 pid_on_fep, u8 mode, + u8 tos, __be16 dport, + const struct uet_pdc_key *key, bool is_inbound) +{ + struct uet_pdc *pdc, *pdc_ins = ERR_PTR(-ENOMEM); + IP_TUNNEL_DECLARE_FLAGS(md_flags) = { }; + int ret __maybe_unused; + + switch (mode) { + case UET_PDC_MODE_RUD: + break; + case UET_PDC_MODE_ROD: + fallthrough; + case UET_PDC_MODE_RUDI: + fallthrough; + case UET_PDC_MODE_UUD: + fallthrough; + default: + return ERR_PTR(-EOPNOTSUPP); + } + + pdc = kzalloc(sizeof(*pdc), GFP_ATOMIC); + if (!pdc) + goto err_alloc; + memcpy(&pdc->key, key, sizeof(*key)); + pdc->pds = pds; + pdc->mode = mode; + pdc->is_initiator = !is_inbound; + + if (!uet_pdc_id_get(pdc)) + goto err_id_get; + + spin_lock_init(&pdc->lock); + + pdc->rx_base_psn = rx_base_psn; + pdc->tx_base_psn = rx_base_psn; + pdc->state = state; + pdc->dpdcid = dpdcid; + pdc->pid_on_fep = pid_on_fep; + pdc->metadata = __ip_tun_set_dst(key->src_ip, key->dst_ip, tos, 0, dport, + md_flags, 0, 0); + if (!pdc->metadata) + goto err_tun_dst; + +#ifdef CONFIG_DST_CACHE + ret = dst_cache_init(&pdc->metadata->u.tun_info.dst_cache, GFP_ATOMIC); + if (ret) { + pdc_ins = ERR_PTR(ret); + goto err_ep_insert; + } +#endif + pdc->metadata->u.tun_info.mode |= IP_TUNNEL_INFO_TX; + + if (is_inbound) { + /* this PDC is a result of packet Rx */ + pdc_ins = pdc; + goto out; + } + + pdc_ins = uet_pds_pdcep_insert(pdc); + if (!pdc_ins) { + pdc_ins = pdc; + } else { + /* someone beat us to it or there was an error, either way + * we free the newly created pdc and drop the ref + */ + goto err_ep_insert; + } + +out: + return pdc_ins; + +err_ep_insert: + dst_release(&pdc->metadata->dst); +err_tun_dst: + uet_pds_pdcid_remove(pdc); +err_id_get: + kfree(pdc); +err_alloc: + goto out; +} + +void uet_pdc_free(struct uet_pdc *pdc) +{ + dst_release(&pdc->metadata->dst); + kfree(pdc); +} + +void uet_pdc_destroy(struct uet_pdc *pdc) +{ + uet_pds_pdcep_remove(pdc); + uet_pds_pdcid_remove(pdc); + uet_pds_pdc_gc_queue(pdc); +} diff --git a/drivers/ultraeth/uet_pds.c b/drivers/ultraeth/uet_pds.c new file mode 100644 index 000000000000..4aec61eeb230 --- /dev/null +++ b/drivers/ultraeth/uet_pds.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) + +#include +#include +#include + +#include +#include + +static const struct rhashtable_params uet_pds_pdcid_rht_params = { + .head_offset = offsetof(struct uet_pdc, pdcid_node), + .key_offset = offsetof(struct uet_pdc, spdcid), + .key_len = sizeof(u16), + .nelem_hint = 2048, + .max_size = UET_PDC_MAX_ID, + .automatic_shrinking = true, +}; + +static const struct rhashtable_params uet_pds_pdcep_rht_params = { + .head_offset = offsetof(struct uet_pdc, pdcep_node), + .key_offset = offsetof(struct uet_pdc, key), + .key_len = sizeof(struct uet_pdc_key), + .nelem_hint = 2048, + .automatic_shrinking = true, +}; + +static void uet_pds_pdc_gc_flush(struct uet_pds *pds) +{ + HLIST_HEAD(deleted_head); + struct hlist_node *tmp; + struct uet_pdc *pdc; + + spin_lock_bh(&pds->gc_lock); + hlist_move_list(&pds->pdc_gc_list, &deleted_head); + spin_unlock_bh(&pds->gc_lock); + + synchronize_rcu(); + + hlist_for_each_entry_safe(pdc, tmp, &deleted_head, gc_node) + uet_pdc_free(pdc); +} + +static void uet_pds_pdc_gc_work(struct work_struct *work) +{ + struct uet_pds *pds = container_of(work, struct uet_pds, pdc_gc_work); + + uet_pds_pdc_gc_flush(pds); +} + +void uet_pds_pdc_gc_queue(struct uet_pdc *pdc) +{ + struct uet_pds *pds = pdc->pds; + + spin_lock_bh(&pds->gc_lock); + if (hlist_unhashed(&pdc->gc_node)) + hlist_add_head(&pdc->gc_node, &pds->pdc_gc_list); + spin_unlock_bh(&pds->gc_lock); + + queue_work(system_long_wq, &pds->pdc_gc_work); +} + +int uet_pds_init(struct uet_pds *pds) +{ + int ret; + + spin_lock_init(&pds->gc_lock); + INIT_HLIST_HEAD(&pds->pdc_gc_list); + INIT_WORK(&pds->pdc_gc_work, uet_pds_pdc_gc_work); + + ret = rhashtable_init(&pds->pdcid_hash, &uet_pds_pdcid_rht_params); + if (ret) + goto err_pdcid_hash; + + ret = rhashtable_init(&pds->pdcep_hash, &uet_pds_pdcep_rht_params); + if (ret) + goto err_pdcep_hash; + + return 0; + +err_pdcep_hash: + rhashtable_destroy(&pds->pdcid_hash); +err_pdcid_hash: + return ret; +} + +struct uet_pdc *uet_pds_pdcep_insert(struct uet_pdc *pdc) +{ + struct uet_pds *pds = pdc->pds; + + return rhashtable_lookup_get_insert_fast(&pds->pdcep_hash, + &pdc->pdcep_node, + uet_pds_pdcep_rht_params); +} + +void uet_pds_pdcep_remove(struct uet_pdc *pdc) +{ + struct uet_pds *pds = pdc->pds; + + rhashtable_remove_fast(&pds->pdcep_hash, &pdc->pdcep_node, + uet_pds_pdcep_rht_params); +} + +int uet_pds_pdcid_insert(struct uet_pdc *pdc) +{ + struct uet_pds *pds = pdc->pds; + + return rhashtable_insert_fast(&pds->pdcid_hash, &pdc->pdcid_node, + uet_pds_pdcid_rht_params); +} + +void uet_pds_pdcid_remove(struct uet_pdc *pdc) +{ + struct uet_pds *pds = pdc->pds; + + rhashtable_remove_fast(&pds->pdcid_hash, &pdc->pdcid_node, + uet_pds_pdcid_rht_params); +} + +static void uet_pds_pdcep_hash_free(void *ptr, void *arg) +{ + struct uet_pdc *pdc = ptr; + + uet_pdc_destroy(pdc); +} + +void uet_pds_uninit(struct uet_pds *pds) +{ + rhashtable_free_and_destroy(&pds->pdcep_hash, uet_pds_pdcep_hash_free, NULL); + /* the above call should also release all PDC ids */ + WARN_ON(atomic_read(&pds->pdcid_hash.nelems)); + rhashtable_destroy(&pds->pdcid_hash); + uet_pds_pdc_gc_flush(pds); + cancel_work_sync(&pds->pdc_gc_work); + rcu_barrier(); +} + +void uet_pds_clean_job(struct uet_pds *pds, u32 job_id) +{ + struct rhashtable_iter iter; + struct uet_pdc *pdc; + + rhashtable_walk_enter(&pds->pdcid_hash, &iter); + rhashtable_walk_start(&iter); + while ((pdc = rhashtable_walk_next(&iter))) { + if (pdc->key.job_id == job_id) + uet_pdc_destroy(pdc); + } + rhashtable_walk_stop(&iter); + rhashtable_walk_exit(&iter); +} + +int uet_pds_rx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, + __be32 remote_fep_addr, __be16 dport, __u8 tos) +{ + if (!pskb_may_pull(skb, sizeof(struct uet_prologue_hdr))) + return -EINVAL; + + return 0; +} diff --git a/include/net/ultraeth/uet_context.h b/include/net/ultraeth/uet_context.h index 8210f69a1571..76077df3bce6 100644 --- a/include/net/ultraeth/uet_context.h +++ b/include/net/ultraeth/uet_context.h @@ -10,6 +10,7 @@ #include #include #include +#include struct uet_context { int id; @@ -19,6 +20,7 @@ struct uet_context { struct net_device *netdev; struct uet_job_registry job_reg; + struct uet_pds pds; }; struct uet_context *uet_context_get_by_id(int id); @@ -27,4 +29,16 @@ void uet_context_put(struct uet_context *ses_pl); int uet_context_create(int id); bool uet_context_destroy(int id); void uet_context_destroy_all(void); + +static inline struct uet_context *pds_context(const struct uet_pds *pds) +{ + return container_of(pds, struct uet_context, pds); +} + +static inline struct net_device *pds_netdev(const struct uet_pds *pds) +{ + struct uet_context *ctx = pds_context(pds); + + return ctx->netdev; +} #endif /* _UET_CONTEXT_H */ diff --git a/include/net/ultraeth/uet_pdc.h b/include/net/ultraeth/uet_pdc.h new file mode 100644 index 000000000000..70f3c6aa03df --- /dev/null +++ b/include/net/ultraeth/uet_pdc.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ + +#ifndef _UECON_PDC_H +#define _UECON_PDC_H + +#include +#include +#include +#include +#include +#include +#include + +#define UET_PDC_ID_MAX_ATTEMPTS 128 +#define UET_PDC_MAX_ID U16_MAX +#define UET_PDC_MPR 128 + +#define UET_SKB_CB(skb) ((struct uet_skb_cb *)&((skb)->cb[0])) + +struct uet_skb_cb { + u32 psn; + __be32 remote_fep_addr; +}; + +enum { + UET_PDC_EP_STATE_CLOSED, + UET_PDC_EP_STATE_SYN_SENT, + UET_PDC_EP_STATE_NEW_ESTABLISHED, + UET_PDC_EP_STATE_ESTABLISHED, + UET_PDC_EP_STATE_QUIESCE, + UET_PDC_EP_STATE_ACK_WAIT, + UET_PDC_EP_STATE_CLOSE_ACK_WAIT +}; + +struct uet_pdc_key { + __be32 src_ip; + __be32 dst_ip; + u32 job_id; +}; + +enum { + UET_PDC_MODE_ROD, + UET_PDC_MODE_RUD, + UET_PDC_MODE_RUDI, + UET_PDC_MODE_UUD +}; + +struct uet_pdc { + struct rhash_head pdcid_node; + struct rhash_head pdcep_node; + struct uet_pdc_key key; + struct uet_pds *pds; + + struct metadata_dst *metadata; + + spinlock_t lock; + u32 psn_start; + u16 state; + u16 spdcid; + u16 dpdcid; + u16 pid_on_fep; + u8 tx_busy; + u8 mode; + bool is_initiator; + + u32 rx_base_psn; + u32 tx_base_psn; + + struct hlist_node gc_node; + struct rcu_head rcu; +}; + +struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, + u16 dpdcid, u16 pid_on_fep, u8 mode, + u8 tos, __be16 dport, + const struct uet_pdc_key *key, bool is_inbound); +void uet_pdc_destroy(struct uet_pdc *pdc); +void uet_pdc_free(struct uet_pdc *pdc); +#endif /* _UECON_PDC_H */ diff --git a/include/net/ultraeth/uet_pds.h b/include/net/ultraeth/uet_pds.h new file mode 100644 index 000000000000..43f5748a318a --- /dev/null +++ b/include/net/ultraeth/uet_pds.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ + +#ifndef _UECON_PDS_H +#define _UECON_PDS_H + +#include +#include +#include +#include + +/** + * struct uet_pds - Packet Delivery Sublayer state structure + * + * @pdcep_hash: a hash table mapping to struct PDC + * @pdcid_hash: a hash table mapping PDC id to struct PDC + * + * @pdcep_hash is used in fast path to find the assigned PDC, @pdcid_hash + * is used when allocating a new PDC + */ +struct uet_pds { + struct rhashtable pdcep_hash; + struct rhashtable pdcid_hash; + + spinlock_t gc_lock; + struct hlist_head pdc_gc_list; + struct work_struct pdc_gc_work; +}; + +struct uet_pdc *uet_pds_pdcep_insert(struct uet_pdc *pdc); +void uet_pds_pdcep_remove(struct uet_pdc *pdc); + +int uet_pds_pdcid_insert(struct uet_pdc *pdc); +void uet_pds_pdcid_remove(struct uet_pdc *pdc); + +int uet_pds_init(struct uet_pds *pds); +void uet_pds_uninit(struct uet_pds *pds); + +void uet_pds_pdc_gc_queue(struct uet_pdc *pdc); +void uet_pds_clean_job(struct uet_pds *pds, u32 job_id); + +int uet_pds_rx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, + __be32 remote_fep_addr, __be16 dport, __u8 tos); + +static inline struct uet_prologue_hdr *pds_prologue_hdr(const struct sk_buff *skb) +{ + return (struct uet_prologue_hdr *)skb_network_header(skb); +} + +static inline struct uet_pds_req_hdr *pds_req_hdr(const struct sk_buff *skb) +{ + return (struct uet_pds_req_hdr *)skb_network_header(skb); +} + +static inline struct uet_pds_ack_hdr *pds_ack_hdr(const struct sk_buff *skb) +{ + return (struct uet_pds_ack_hdr *)skb_network_header(skb); +} + +static inline struct uet_pds_nack_hdr *pds_nack_hdr(const struct sk_buff *skb) +{ + return (struct uet_pds_nack_hdr *)skb_network_header(skb); +} + +static inline struct uet_pds_ack_ext_hdr *pds_ack_ext_hdr(const struct sk_buff *skb) +{ + return (struct uet_pds_ack_ext_hdr *)(pds_ack_hdr(skb) + 1); +} + +static inline struct uet_ses_rsp_hdr *pds_ack_ses_rsp_hdr(const struct sk_buff *skb) +{ + /* TODO: ack_ext_hdr, CC_STATE, etc. */ + return (struct uet_ses_rsp_hdr *)(pds_ack_hdr(skb) + 1); +} + +static inline struct uet_ses_req_hdr *pds_req_ses_req_hdr(const struct sk_buff *skb) +{ + /* TODO: ack_ext_hdr, CC_STATE, etc. */ + return (struct uet_ses_req_hdr *)(pds_req_hdr(skb) + 1); +} + +static inline __be16 pds_ses_rsp_hdr_pack(__u8 opcode, __u8 version, __u8 list, + __u8 ses_rc) +{ + return cpu_to_be16((opcode & UET_SES_RSP_OPCODE_MASK) << + UET_SES_RSP_OPCODE_SHIFT | + (version & UET_SES_RSP_VERSION_MASK) << + UET_SES_RSP_VERSION_SHIFT | + (list & UET_SES_RSP_LIST_MASK) << + UET_SES_RSP_LIST_SHIFT | + (ses_rc & UET_SES_RSP_RC_MASK) << + UET_SES_RSP_RC_SHIFT); +} +#endif /* _UECON_PDS_H */ diff --git a/include/uapi/linux/ultraeth.h b/include/uapi/linux/ultraeth.h index a4ac25455aa0..6f3ee5ac8cf4 100644 --- a/include/uapi/linux/ultraeth.h +++ b/include/uapi/linux/ultraeth.h @@ -9,6 +9,360 @@ #define UET_DEFAULT_PORT 5432 #define UET_SVC_MAX_LEN 64 +/* types used for prologue's type field */ +enum { + UET_PDS_TYPE_RSVD0, + UET_PDS_TYPE_ENC_HDR, + UET_PDS_TYPE_RUD_REQ, + UET_PDS_TYPE_ROD_REQ, + UET_PDS_TYPE_RUDI_REQ, + UET_PDS_TYPE_RUDI_RESPONSE, + UET_PDS_TYPE_UUD_REQ, + UET_PDS_TYPE_ACK, + UET_PDS_TYPE_ACK_CC, + UET_PDS_TYPE_ACK_CCX, + UET_PDS_TYPE_NACK, + UET_PDS_TYPE_CTRL_MSG +}; + +/* ctl_type when type is UET_PDS_CTRL_MSG (control message) */ +enum { + UET_CTL_TYPE_NOOP, + UET_CTL_TYPE_REQ_ACK, + UET_CTL_TYPE_CLEAR, + UET_CTL_TYPE_REQ_CLEAR, + UET_CTL_TYPE_CLOSE, + UET_CTL_TYPE_REQ_CLOSE, + UET_CTL_TYPE_PROBE, + UET_CTL_TYPE_CREDIT, + UET_CTL_TYPE_REQ_CREDIT +}; + +/* next header, 0x06-0x0E reserved */ +enum { + UET_PDS_NEXT_HDR_NONE = 0x00, + UET_PDS_NEXT_HDR_REQ_SMALL = 0x01, + UET_PDS_NEXT_HDR_REQ_MEDIUM = 0x02, + UET_PDS_NEXT_HDR_REQ_STD = 0x03, + UET_PDS_NEXT_HDR_RSP = 0x04, + UET_PDS_NEXT_HDR_RSP_DATA = 0x05, + UET_PDS_NEXT_HDR_RSP_DATA_SMALL = 0x06, + UET_PDS_NEXT_HDR_PDS = 0x0F, +}; + +/* fields(union): type_next_flags, type_ctl_flags */ +#define UET_PROLOGUE_FLAGS_BITS 7 +#define UET_PROLOGUE_FLAGS_MASK 0x7f +#define UET_PROLOGUE_NEXT_BITS 4 +#define UET_PROLOGUE_NEXT_MASK 0x0f +#define UET_PROLOGUE_NEXT_SHIFT UET_PROLOGUE_FLAGS_BITS +#define UET_PROLOGUE_CTL_BITS UET_PROLOGUE_NEXT_BITS +#define UET_PROLOGUE_CTL_SHIFT UET_PROLOGUE_NEXT_SHIFT +#define UET_PROLOGUE_CTL_MASK UET_PROLOGUE_NEXT_MASK +#define UET_PROLOGUE_TYPE_BITS 5 +#define UET_PROLOGUE_TYPE_MASK 0x1f +#define UET_PROLOGUE_TYPE_SHIFT (UET_PROLOGUE_NEXT_SHIFT + UET_PROLOGUE_NEXT_BITS) +struct uet_prologue_hdr { + union { + __be16 type_next_flags; + __be16 type_ctl_flags; + }; +} __attribute__ ((__packed__)); + +static inline __u8 uet_prologue_flags(const struct uet_prologue_hdr *hdr) +{ + return __be16_to_cpu(hdr->type_next_flags) & UET_PROLOGUE_FLAGS_MASK; +} + +static inline __u8 uet_prologue_next_hdr(const struct uet_prologue_hdr *hdr) +{ + return (__be16_to_cpu(hdr->type_next_flags) >> UET_PROLOGUE_NEXT_SHIFT) & + UET_PROLOGUE_NEXT_MASK; +} + +static inline __u8 uet_prologue_ctl_type(const struct uet_prologue_hdr *hdr) +{ + return (__be16_to_cpu(hdr->type_ctl_flags) >> UET_PROLOGUE_CTL_SHIFT) & + UET_PROLOGUE_CTL_MASK; +} + +static inline __u8 uet_prologue_type(const struct uet_prologue_hdr *hdr) +{ + return (__be16_to_cpu(hdr->type_next_flags) >> UET_PROLOGUE_TYPE_SHIFT) & + UET_PROLOGUE_TYPE_MASK; +} + +/* rud/rod request flags */ +enum { + UET_PDS_REQ_FLAG_RSV2 = (1 << 0), + UET_PDS_REQ_FLAG_CC = (1 << 1), + UET_PDS_REQ_FLAG_SYN = (1 << 2), + UET_PDS_REQ_FLAG_AR = (1 << 3), + UET_PDS_REQ_FLAG_RETX = (1 << 4), + UET_PDS_REQ_FLAG_RSV = (1 << 5), + UET_PDS_REQ_FLAG_CRC = (1 << 6), +}; + +/* field: pdc_mode_psn_offset */ +#define UET_PDS_REQ_PSN_OFF_BITS 12 +#define UET_PDS_REQ_PSN_OFF_MASK 0xff1 +#define UET_PDS_REQ_MODE_BITS 4 +#define UET_PDS_REQ_MODE_MASK 0xf +#define UET_PDS_REQ_MODE_SHIFT UET_PDS_REQ_PSN_OFF_BITS +struct uet_pds_req_hdr { + struct uet_prologue_hdr prologue; + __be16 clear_psn_offset; + __be32 psn; + __be16 spdcid; + union { + __be16 pdc_mode_psn_offset; + __be16 dpdcid; + }; +} __attribute__ ((__packed__)); + +static inline __u16 uet_pds_request_psn_offset(const struct uet_pds_req_hdr *req) +{ + return __be16_to_cpu(req->pdc_mode_psn_offset) & UET_PDS_REQ_PSN_OFF_MASK; +} + +static inline __u8 uet_pds_request_pdc_mode(const struct uet_pds_req_hdr *req) +{ + return (__be16_to_cpu(req->pdc_mode_psn_offset) >> UET_PDS_REQ_MODE_SHIFT) & + UET_PDS_REQ_MODE_MASK; +} + +/* rud/rod ack flags */ +enum { + UET_PDS_ACK_FLAG_RSVD = (1 << 0), + UET_PDS_ACK_FLAG_REQ1 = (1 << 1), + UET_PDS_ACK_FLAG_REQ2 = (1 << 2), + UET_PDS_ACK_FLAG_P = (1 << 3), + UET_PDS_ACK_FLAG_RETX = (1 << 4), + UET_PDS_ACK_FLAG_M = (1 << 5), + UET_PDS_ACK_FLAG_CRC = (1 << 6) +}; + +struct uet_pds_ack_hdr { + struct uet_prologue_hdr prologue; + __be16 ack_psn_offset; + __be32 cack_psn; + __be16 spdcid; + __be16 dpdcid; +} __attribute__ ((__packed__)); + +/* ses request op codes */ +enum { + UET_SES_REQ_OP_NOOP = 0x00, + UET_SES_REQ_OP_WRITE = 0x01, + UET_SES_REQ_OP_READ = 0x02, + UET_SES_REQ_OP_ATOMIC = 0x03, + UET_SES_REQ_OP_FETCHING_ATOMIC = 0x04, + UET_SES_REQ_OP_SEND = 0x05, + UET_SES_REQ_OP_RENDEZVOUS_SEND = 0x06, + UET_SES_REQ_OP_DGRAM_SEND = 0x07, + UET_SES_REQ_OP_DEFERRABLE_SEND = 0x08, + UET_SES_REQ_OP_TAGGED_SEND = 0x09, + UET_SES_REQ_OP_RENDEZVOUS_TSEND = 0x0A, + UET_SES_REQ_OP_DEFERRABLE_TSEND = 0x0B, + UET_SES_REQ_OP_DEFERRABLE_RTR = 0x0C, + UET_SES_REQ_OP_TSEND_ATOMIC = 0x0D, + UET_SES_REQ_OP_TSEND_FETCH_ATOMIC = 0x0E, + UET_SES_REQ_OP_MSG_ERROR = 0x0F, + UET_SES_REQ_OP_INC_PUSH = 0x10, +}; + +enum { + UET_SES_REQ_FLAG_SOM = (1 << 0), + UET_SES_REQ_FLAG_EOM = (1 << 1), + UET_SES_REQ_FLAG_HD = (1 << 2), + UET_SES_REQ_FLAG_RELATIVE = (1 << 3), + UET_SES_REQ_FLAG_IE = (1 << 4), + UET_SES_REQ_FLAG_DC = (1 << 5) +}; + +/* field: resv_opcode */ +#define UET_SES_REQ_OPCODE_MASK 0x3f +/* field: flags */ +#define UET_SES_REQ_FLAGS_MASK 0x3f +#define UET_SES_REQ_FLAGS_VERSION_MASK 0x3 +#define UET_SES_REQ_FLAGS_VERSION_SHIFT 6 +/* field: resv_idx */ +#define UET_SES_REQ_INDEX_MASK 0xfff +/* field: idx_gen_job_id */ +#define UET_SES_REQ_JOB_ID_BITS 24 +#define UET_SES_REQ_JOB_ID_MASK 0xffffff +#define UET_SES_REQ_INDEX_GEN_MASK 0xff +#define UET_SES_REQ_INDEX_GEN_SHIFT UET_SES_REQ_JOB_ID_BITS +/* field: resv_pid_on_fep */ +#define UET_SES_REQ_PID_ON_FEP_MASK 0xfff +struct uet_ses_req_hdr { + __u8 resv_opcode; + __u8 flags; + __be16 msg_id; + __be32 idx_gen_job_id; + __be16 resv_pid_on_fep; + __be16 resv_idx; + __be64 buffer_offset; + __be32 initiator; + __be64 match_bits; + __be64 header_data; + __be32 request_len; +} __attribute__ ((__packed__)); + +static inline __u8 uet_ses_req_opcode(const struct uet_ses_req_hdr *sreq) +{ + return sreq->resv_opcode & UET_SES_REQ_OPCODE_MASK; +} + +static inline __u8 uet_ses_req_flags(const struct uet_ses_req_hdr *sreq) +{ + return sreq->flags & UET_SES_REQ_FLAGS_MASK; +} + +static inline __u8 uet_ses_req_version(const struct uet_ses_req_hdr *sreq) +{ + return (sreq->flags >> UET_SES_REQ_FLAGS_VERSION_SHIFT) & + UET_SES_REQ_FLAGS_VERSION_MASK; +} + +static inline __u16 uet_ses_req_index(const struct uet_ses_req_hdr *sreq) +{ + return __be16_to_cpu(sreq->resv_idx) & UET_SES_REQ_INDEX_MASK; +} + +static inline __u32 uet_ses_req_job_id(const struct uet_ses_req_hdr *sreq) +{ + return __be32_to_cpu(sreq->idx_gen_job_id) & UET_SES_REQ_JOB_ID_MASK; +} + +static inline __u8 uet_ses_req_index_gen(const struct uet_ses_req_hdr *sreq) +{ + return (__be32_to_cpu(sreq->idx_gen_job_id) >> UET_SES_REQ_INDEX_GEN_SHIFT) & + UET_SES_REQ_INDEX_GEN_MASK; +} + +static inline __u16 uet_ses_req_pid_on_fep(const struct uet_ses_req_hdr *sreq) +{ + return __be16_to_cpu(sreq->resv_pid_on_fep) & UET_SES_REQ_PID_ON_FEP_MASK; +} + +/* return codes */ +enum { + UET_SES_RSP_RC_NULL = 0x00, + UET_SES_RSP_RC_OK = 0x01, + UET_SES_RSP_RC_BAD_GEN = 0x02, + UET_SES_RSP_RC_DISABLED = 0x03, + UET_SES_RSP_RC_DISABLED_GEN = 0x04, + UET_SES_RSP_RC_NO_MATCH = 0x05, + UET_SES_RSP_RC_UNSUPP_OP = 0x06, + UET_SES_RSP_RC_UNSUPP_SIZE = 0x07, + UET_SES_RSP_RC_AT_INVALID = 0x08, + UET_SES_RSP_RC_AT_PERM = 0x09, + UET_SES_RSP_RC_AT_ATS_ERROR = 0x0A, + UET_SES_RSP_RC_AT_NO_TRANS = 0x0B, + UET_SES_RSP_RC_AT_OUT_OF_RANGE = 0x0C, + UET_SES_RSP_RC_HOST_POISONED = 0x0D, + UET_SES_RSP_RC_HOST_UNSUCC_CMPL = 0x0E, + UET_SES_RSP_RC_AMO_UNSUPP_OP = 0x0F, + UET_SES_RSP_RC_AMO_UNSUPP_DT = 0x10, + UET_SES_RSP_RC_AMO_UNSUPP_SIZE = 0x11, + UET_SES_RSP_RC_AMO_UNALIGNED = 0x12, + UET_SES_RSP_RC_AMO_FP_NAN = 0x13, + UET_SES_RSP_RC_AMO_FP_UNDERFLOW = 0x14, + UET_SES_RSP_RC_AMO_FP_OVERFLOW = 0x15, + UET_SES_RSP_RC_AMO_FP_INEXACT = 0x16, + UET_SES_RSP_RC_PERM_VIOLATION = 0x17, + UET_SES_RSP_RC_OP_VIOLATION = 0x18, + UET_SES_RSP_RC_BAD_INDEX = 0x19, + UET_SES_RSP_RC_BAD_PID = 0x1A, + UET_SES_RSP_RC_BAD_JOB_ID = 0x1B, + UET_SES_RSP_RC_BAD_MKEY = 0x1C, + UET_SES_RSP_RC_BAD_ADDR = 0x1D, + UET_SES_RSP_RC_CANCELLED = 0x1E, + UET_SES_RSP_RC_UNDELIVERABLE = 0x1F, + UET_SES_RSP_RC_UNCOR = 0x20, + UET_SES_RSP_RC_UNCOR_TRNSNT = 0x21, + UET_SES_RSP_RC_TOO_LONG = 0x22, + UET_SES_RSP_RC_INITIATOR_ERR = 0x23, + UET_SES_RSP_RC_DROPPED = 0x24, +}; + +/* ses response list values */ +enum { + UET_SES_RSP_LIST_EXPECTED = 0x00, + UET_SES_RSP_LIST_OVERFLOW = 0x01 +}; + +/* ses response op codes */ +enum { + UET_SES_RSP_OP_DEF_RESP = 0x00, + UET_SES_RSP_OP_RESPONSE = 0x01, + UET_SES_RSP_OP_RESP_W_DATA = 0x02 +}; + +/* field: lst_opcode_ver_rc */ +#define UET_SES_RSP_RC_BITS 6 +#define UET_SES_RSP_RC_MASK 0x3f +#define UET_SES_RSP_RC_SHIFT 0 +#define UET_SES_RSP_VERSION_BITS 2 +#define UET_SES_RSP_VERSION_MASK 0x3 +#define UET_SES_RSP_VERSION_SHIFT (UET_SES_RSP_RC_SHIFT + \ + UET_SES_RSP_RC_BITS) +#define UET_SES_RSP_OPCODE_BITS 6 +#define UET_SES_RSP_OPCODE_MASK 0x3f +#define UET_SES_RSP_OPCODE_SHIFT (UET_SES_RSP_VERSION_SHIFT + \ + UET_SES_RSP_VERSION_BITS) +#define UET_SES_RSP_LIST_BITS 2 +#define UET_SES_RSP_LIST_MASK 0x3 +#define UET_SES_RSP_LIST_SHIFT (UET_SES_RSP_OPCODE_SHIFT + \ + UET_SES_RSP_OPCODE_BITS) +/* field: idx_gen_job_id */ +#define UET_SES_RSP_JOB_ID_BITS 24 +#define UET_SES_RSP_JOB_ID_MASK 0xffffff +#define UET_SES_RSP_INDEX_GEN_MASK 0xff +#define UET_SES_RSP_INDEX_GEN_SHIFT UET_SES_RSP_JOB_ID_BITS +struct uet_ses_rsp_hdr { + __be16 lst_opcode_ver_rc; + __be16 msg_id; + __be32 idx_gen_job_id; + __be32 mod_len; +} __attribute__ ((__packed__)); + +static inline __u8 uet_ses_rsp_rc(const struct uet_ses_rsp_hdr *rsp) +{ + return (__be32_to_cpu(rsp->lst_opcode_ver_rc) >> + UET_SES_RSP_RC_SHIFT) & UET_SES_RSP_RC_MASK; +} + +static inline __u8 uet_ses_rsp_list(const struct uet_ses_rsp_hdr *rsp) +{ + return (__be32_to_cpu(rsp->lst_opcode_ver_rc) >> + UET_SES_RSP_LIST_SHIFT) & UET_SES_RSP_LIST_MASK; +} + +static inline __u8 uet_ses_rsp_version(const struct uet_ses_rsp_hdr *rsp) +{ + return (__be32_to_cpu(rsp->lst_opcode_ver_rc) >> + UET_SES_RSP_VERSION_SHIFT) & UET_SES_RSP_VERSION_MASK; +} + +static inline __u8 uet_ses_rsp_opcode(const struct uet_ses_rsp_hdr *rsp) +{ + return (__be32_to_cpu(rsp->lst_opcode_ver_rc) >> + UET_SES_RSP_OPCODE_SHIFT) & UET_SES_RSP_OPCODE_MASK; +} + +static inline __u32 uet_ses_rsp_job_id(const struct uet_ses_rsp_hdr *rsp) +{ + return __be32_to_cpu(rsp->idx_gen_job_id) & UET_SES_RSP_JOB_ID_MASK; +} + +static inline __u8 uet_ses_rsp_index_gen(const struct uet_ses_req_hdr *rsp) +{ + return (__be32_to_cpu(rsp->idx_gen_job_id) >> UET_SES_RSP_INDEX_GEN_SHIFT) & + UET_SES_RSP_INDEX_GEN_MASK; +} + enum { UET_ADDR_F_VALID_FEP_CAP = (1 << 0), UET_ADDR_F_VALID_ADDR = (1 << 1), From patchwork Thu Mar 6 23:01:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 14005476 X-Patchwork-Delegate: kuba@kernel.org Received: from mail-qk1-f174.google.com (mail-qk1-f174.google.com [209.85.222.174]) (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 873D327CCDD for ; Thu, 6 Mar 2025 23:04:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302254; cv=none; b=UOxmp1A/oMgY3vx+7scaJxmzvBCKVEf9TE7RSBbwMrOJJhJ1xBFi+yI0uNP9J2EvKKaWWNBIHwNgltfgTL9xoYqlnnCo08yE1Fh8lHePYuM5xM3ycruurtA83PBwgux6r+jzKOnBVGO8ylW423dBVUQ30QbB6o3RMuidhpvuIHs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302254; c=relaxed/simple; bh=Gd7gnODU0DKD5ytC3V5mdWFfgw32qZrGg0fJLfcPqKo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bit62KxNAxM0cvZIzX00qlTitPRsC2WrfCCmb+WdMdqtqUOhRXLg3zk5lxDWpcbLDdC97XNiyi2G+DpvEIRQuHp9fpfQexrW9G1rYFnIYC2RTCBcEJF3SAhYgUc2v5+5YntmLlVBxpMDTff70UwlGgKOxOMG82iqmOdDKPoliwc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net; spf=pass smtp.mailfrom=enfabrica.net; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b=OLuAGBKn; arc=none smtp.client-ip=209.85.222.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b="OLuAGBKn" Received: by mail-qk1-f174.google.com with SMTP id af79cd13be357-7c0848d475cso162890385a.2 for ; Thu, 06 Mar 2025 15:04:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enfabrica.net; s=google; t=1741302251; x=1741907051; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VgZ4DFZe+wGVy1zx5dFgA68nl8KtUw/hz4M7r+ARKDs=; b=OLuAGBKnLvF5HZndx8lEW2hZJ+JinMNoiC8O8CXR9DtroLCij4q2UNdqhXaWFE2z9F 9wp5ua5Y8d/UzUWGhWnKttD0lBRtLiymm5vFf6c/phDyGMl3WmkwrAvn+580WFEb7Kvj coMdHoAe96JImzffzYuc9RCxa4ROBfCXJXuPnUubbgg6PajwKgtJZSOzSAl4OCa18Jla eZdyJ9YO1vKbyvr5LBqZhetLGfEItekccLIYYuFtunhgrnOy5ORr2Dh8JB80fCVSdnws Fvk3gU33P9el2BpJKA2EJNBhVjTi871gAmtz1l5zNDG2KREoHj/SEgTo4f4tsDYvVNBf JQLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302251; x=1741907051; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VgZ4DFZe+wGVy1zx5dFgA68nl8KtUw/hz4M7r+ARKDs=; b=d+BPlPgiB2gWDDd6PeV7PC8+D9RqmEdt8FI5aGxTDAAfU80VdUxqtjG2zLIGeSTnxE ZomT9S7hPNA9jXl3x0DchhFLdXXFPgeqr53F0s/pLdJUheBqnWYWGwm/7owr9LzEJ8dK Ne90iReyNEVsJqsi0r12Zl/ewL7BlpkxWkhtwnSZgXpNr5MBtIPwuOOeB3U7l3NUQU12 lxq3jem/8e4i8iWHAZ0RmhksX8AK11UGdw0/NDvvlLv1KiLwGvq2Hi/wrxOPsKwHpazO l7LS5JR9oiZ9G01ziN8dX5GPU0cHsuTSk6xlqMREy4zsbCzoE/9R7wpgEyZTJg5Y7prY 4ALg== X-Gm-Message-State: AOJu0YwtqvlX4CCX7xwuUkxfbyN00CeDtHplmjTJjSMsoqSw/u8Jk0cK MQovK7rxDKOyZR9Nyj+pMJ0dxW7j6TnNrw2U8cpNnhJCQgR7xsFvgeIlWx4AEGLYMKd+MNHgH2h CTHsGmoJZGRDAoaWbQo3/8iP6LOHRB2qgrhBxSJBaiXtqfHhQ9RQupUcbPk7EbGv2rAUyCnu8fX F5df4awDLDhXrNmEfOR9sd1pfDZS+icJ/HsRftWzdKCcA= X-Gm-Gg: ASbGncu/Wkn21VYLWBtkHirHZGQYtprOGX1lx3q2EEryvX9ew/iPs8JOSRDEddEQRKQ RsSE7lwVE/aTa8nGi+FGGpsQDeDjVmeFfl4t5ZrlBUzxATEeysA5PFmVuVTolXTPa/HBOexOq+Z RrdfVyKGfR5l9VeVJRvPw9OA/u4D0H1IvA57yBmvfllFEq6sSs6u1j6Mq0PkVjgSb8pGtaR8CIv Ba+h37TlZ55V8hx1gowiwUM5GflAKkUOgus1mE8YQhEHsed62Pd8bixTy8t42w2/qf63J1iI+9k krZnX1kOT9k72lG+EMxmC9/GdNL/GqFsjKh3oAk8ne7Pu9k21b3uzf9I0xux3w5boW3O X-Google-Smtp-Source: AGHT+IGDKzMhLR7rEwsrTBkYDLjqgXRmC31T7+OmoHH6gaVPQotofQSXrIgpAMXNLZ3UQ8KdA7oiYw== X-Received: by 2002:a05:620a:2722:b0:7c3:c3bb:2538 with SMTP id af79cd13be357-7c4e168c612mr159148085a.14.1741302251145; Thu, 06 Mar 2025 15:04:11 -0800 (PST) Received: from debil.. (78-154-15-142.ip.btc-net.bg. [78.154.15.142]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac256654fa6sm14971966b.93.2025.03.06.15.04.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Mar 2025 15:04:10 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: shrijeet@enfabrica.net, alex.badea@keysight.com, eric.davis@broadcom.com, rip.sohan@amd.com, dsahern@kernel.org, bmt@zurich.ibm.com, roland@enfabrica.net, nikolay@enfabrica.net, winston.liu@keysight.com, dan.mihailescu@keysight.com, kheib@redhat.com, parth.v.parikh@keysight.com, davem@redhat.com, ian.ziemba@hpe.com, andrew.tauferner@cornelisnetworks.com, welch@hpe.com, rakhahari.bhunia@keysight.com, kingshuk.mandal@keysight.com, linux-rdma@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com Subject: [RFC PATCH 07/13] drivers: ultraeth: add request and ack receive support Date: Fri, 7 Mar 2025 01:01:57 +0200 Message-ID: <20250306230203.1550314-8-nikolay@enfabrica.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250306230203.1550314-1-nikolay@enfabrica.net> References: <20250306230203.1550314-1-nikolay@enfabrica.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Add support for receiving request and ack packets. A PDC is automatically created if a request with SYN flag is received. If all is well with the request and it passes all validations, we automatically return an ack. Currently RUD (unordered) type of request is expected. The receive and ack packet sequence numbers are tracked via bitmaps. Signed-off-by: Nikolay Aleksandrov Signed-off-by: Alex Badea --- drivers/ultraeth/uet_pdc.c | 285 +++++++++++++++++++++++++++++++++ drivers/ultraeth/uet_pds.c | 137 +++++++++++++++- include/net/ultraeth/uet_pdc.h | 38 +++++ 3 files changed, 458 insertions(+), 2 deletions(-) diff --git a/drivers/ultraeth/uet_pdc.c b/drivers/ultraeth/uet_pdc.c index 47cf4c3dee04..a0352a925329 100644 --- a/drivers/ultraeth/uet_pdc.c +++ b/drivers/ultraeth/uet_pdc.c @@ -6,6 +6,19 @@ #include #include +static void uet_pdc_xmit(struct uet_pdc *pdc, struct sk_buff *skb) +{ + skb->dev = pds_netdev(pdc->pds); + + if (!dst_hold_safe(&pdc->metadata->dst)) { + kfree_skb(skb); + return; + } + + skb_dst_set(skb, &pdc->metadata->dst); + dev_queue_xmit(skb); +} + /* use the approach as nf nat, try a few rounds starting at random offset */ static bool uet_pdc_id_get(struct uet_pdc *pdc) { @@ -67,6 +80,12 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, pdc->state = state; pdc->dpdcid = dpdcid; pdc->pid_on_fep = pid_on_fep; + pdc->rx_bitmap = bitmap_zalloc(UET_PDC_MPR, GFP_ATOMIC); + if (!pdc->rx_bitmap) + goto err_rx_bitmap; + pdc->ack_bitmap = bitmap_zalloc(UET_PDC_MPR, GFP_ATOMIC); + if (!pdc->ack_bitmap) + goto err_ack_bitmap; pdc->metadata = __ip_tun_set_dst(key->src_ip, key->dst_ip, tos, 0, dport, md_flags, 0, 0); if (!pdc->metadata) @@ -103,6 +122,10 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, err_ep_insert: dst_release(&pdc->metadata->dst); err_tun_dst: + bitmap_free(pdc->ack_bitmap); +err_ack_bitmap: + bitmap_free(pdc->rx_bitmap); +err_rx_bitmap: uet_pds_pdcid_remove(pdc); err_id_get: kfree(pdc); @@ -113,6 +136,8 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, void uet_pdc_free(struct uet_pdc *pdc) { dst_release(&pdc->metadata->dst); + bitmap_free(pdc->ack_bitmap); + bitmap_free(pdc->rx_bitmap); kfree(pdc); } @@ -122,3 +147,263 @@ void uet_pdc_destroy(struct uet_pdc *pdc) uet_pds_pdcid_remove(pdc); uet_pds_pdc_gc_queue(pdc); } + +static void pdc_build_ack(struct uet_pdc *pdc, struct sk_buff *skb, u32 psn, + u8 ack_flags, bool exact_psn) +{ + struct uet_pds_ack_hdr *ack = skb_put(skb, sizeof(*ack)); + + uet_pdc_build_prologue(&ack->prologue, UET_PDS_TYPE_ACK, + UET_PDS_NEXT_HDR_RSP, ack_flags); + if (exact_psn) { + ack->ack_psn_offset = 0; + ack->cack_psn = cpu_to_be32(psn); + } else { + ack->ack_psn_offset = cpu_to_be16(psn - pdc->rx_base_psn); + ack->cack_psn = cpu_to_be32(pdc->rx_base_psn); + } + ack->spdcid = cpu_to_be16(pdc->spdcid); + ack->dpdcid = cpu_to_be16(pdc->dpdcid); +} + +static void uet_pdc_build_ses_ack(struct uet_pdc *pdc, struct sk_buff *skb, + __u8 ses_rc, __be16 msg_id, u32 psn, + u8 ack_flags, bool exact_psn) +{ + struct uet_ses_rsp_hdr *ses_rsp; + __be16 packed; + + pdc_build_ack(pdc, skb, psn, ack_flags, exact_psn); + ses_rsp = skb_put(skb, sizeof(*ses_rsp)); + memset(ses_rsp, 0, sizeof(*ses_rsp)); + packed = pds_ses_rsp_hdr_pack(UET_SES_RSP_OP_RESPONSE, 0, + UET_SES_RSP_LIST_EXPECTED, ses_rc); + ses_rsp->lst_opcode_ver_rc = packed; + ses_rsp->idx_gen_job_id = cpu_to_be32(pdc->key.job_id); + ses_rsp->msg_id = msg_id; +} + +static int uet_pdc_send_ses_ack(struct uet_pdc *pdc, __u8 ses_rc, __be16 msg_id, + u32 psn, u8 ack_flags, bool exact_psn) +{ + struct sk_buff *skb; + + skb = alloc_skb(sizeof(struct uet_ses_rsp_hdr) + + sizeof(struct uet_pds_ack_hdr), GFP_ATOMIC); + if (!skb) + return -ENOBUFS; + + uet_pdc_build_ses_ack(pdc, skb, ses_rc, msg_id, psn, ack_flags, + exact_psn); + uet_pdc_xmit(pdc, skb); + + return 0; +} + +static void uet_pdc_mpr_advance_tx(struct uet_pdc *pdc, u32 bits) +{ + if (!test_bit(0, pdc->ack_bitmap)) + return; + + bitmap_shift_right(pdc->ack_bitmap, pdc->ack_bitmap, bits, UET_PDC_MPR); + pdc->tx_base_psn += bits; + netdev_dbg(pds_netdev(pdc->pds), "%s: advancing tx to %u\n", __func__, + pdc->tx_base_psn); +} + +int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, + __be32 remote_fep_addr) +{ + struct uet_ses_rsp_hdr *ses_rsp = pds_ack_ses_rsp_hdr(skb); + struct uet_pds_ack_hdr *ack = pds_ack_hdr(skb); + s16 ack_psn_offset = be16_to_cpu(ack->ack_psn_offset); + const char *drop_reason = "ack_psn not in MPR window"; + u32 cack_psn = be32_to_cpu(ack->cack_psn); + u32 ack_psn = cack_psn + ack_psn_offset; + int ret = -EINVAL; + u32 psn_bit; + + spin_lock(&pdc->lock); + netdev_dbg(pds_netdev(pdc->pds), "%s: tx_busy: %u pdc: [ tx_base_psn: %u" + " state: %u dpdcid: %u spdcid: %u ]\n" + "ses: [ msg id: %u cack_psn: %u spdcid: %u" + " dpdcid: %u ack_psn: %u ]\n", + __func__, pdc->tx_busy, pdc->tx_base_psn, + pdc->state, pdc->dpdcid, pdc->spdcid, + be16_to_cpu(ses_rsp->msg_id), be32_to_cpu(ack->cack_psn), + be16_to_cpu(ack->spdcid), be16_to_cpu(ack->dpdcid), ack_psn); + + if (psn_mpr_pos(pdc->tx_base_psn, ack_psn) != UET_PDC_MPR_CUR) + goto err_dbg; + + psn_bit = ack_psn - pdc->tx_base_psn; + if (!psn_bit_valid(psn_bit)) { + drop_reason = "ack_psn bit is invalid"; + goto err_dbg; + } + if (test_and_set_bit(psn_bit, pdc->ack_bitmap)) { + drop_reason = "ack_psn bit already set in ack_bitmap"; + goto err_dbg; + } + + /* either using ROD mode or in SYN_SENT state */ + if (pdc->tx_busy) + pdc->tx_busy = false; + /* we can advance only if the oldest pkt got acked */ + if (!psn_bit) + uet_pdc_mpr_advance_tx(pdc, 1); + + ret = 0; + switch (pdc->state) { + case UET_PDC_EP_STATE_SYN_SENT: + case UET_PDC_EP_STATE_NEW_ESTABLISHED: + pdc->dpdcid = be16_to_cpu(ack->spdcid); + pdc->state = UET_PDC_EP_STATE_ESTABLISHED; + fallthrough; + case UET_PDC_EP_STATE_ESTABLISHED: + ret = uet_job_fep_queue_skb(pds_context(pdc->pds), + uet_ses_rsp_job_id(ses_rsp), skb, + remote_fep_addr); + break; + case UET_PDC_EP_STATE_ACK_WAIT: + break; + case UET_PDC_EP_STATE_CLOSE_ACK_WAIT: + break; + } + +out: + spin_unlock(&pdc->lock); + + return ret; +err_dbg: + netdev_dbg(pds_netdev(pdc->pds), "%s: drop reason: [ %s ]\n" + "pdc: [ tx_base_psn: %u state: %u" + " dpdcid: %u spdcid: %u ]\n" + "ses: [ msg id: %u cack_psn: %u spdcid: %u" + " dpdcid: %u ack_psn: %u ]\n", + __func__, drop_reason, pdc->tx_base_psn, + pdc->state, pdc->dpdcid, pdc->spdcid, + be16_to_cpu(ses_rsp->msg_id), be32_to_cpu(ack->cack_psn), + be16_to_cpu(ack->spdcid), be16_to_cpu(ack->dpdcid), ack_psn); + goto out; +} + +static void uet_pdc_mpr_advance_rx(struct uet_pdc *pdc) +{ + if (!test_bit(0, pdc->rx_bitmap)) + return; + + bitmap_shift_right(pdc->rx_bitmap, pdc->rx_bitmap, 1, UET_PDC_MPR); + pdc->rx_base_psn++; + netdev_dbg(pds_netdev(pdc->pds), "%s: advancing rx to %u\n", + __func__, pdc->rx_base_psn); +} + +int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, + __be32 remote_fep_addr, __u8 tos) +{ + struct uet_ses_req_hdr *ses_req = pds_req_ses_req_hdr(skb); + struct uet_pds_req_hdr *req = pds_req_hdr(skb); + u8 req_flags = uet_prologue_flags(&req->prologue), ack_flags = 0; + u32 req_psn = be32_to_cpu(req->psn); + const char *drop_reason = "tx_busy"; + unsigned long psn_bit; + enum mpr_pos psn_pos; + int ret = -EINVAL; + + spin_lock(&pdc->lock); + netdev_dbg(pds_netdev(pdc->pds), "%s: tx_busy: %u pdc: [ tx_base_psn: %u" + " state: %u dpdcid: %u spdcid: %u ]\n" + "req: [ psn: %u spdcid: %u dpdcid: %u prologue flags: 0x%x ]\n" + "ses_req: [ opcode: %u msg id: %u job id: %u " + "pid_on_fep: %u flags: 0x%x ]\n", + __func__, pdc->tx_busy, pdc->tx_base_psn, + pdc->state, pdc->dpdcid, pdc->spdcid, + req_psn, be16_to_cpu(req->spdcid), be16_to_cpu(req->dpdcid), + uet_prologue_flags(&req->prologue), + uet_ses_req_opcode(ses_req), be16_to_cpu(ses_req->msg_id), + uet_ses_req_job_id(ses_req), uet_ses_req_pid_on_fep(ses_req), + uet_ses_req_flags(ses_req)); + + if (unlikely(pdc->tx_busy)) + goto err_dbg; + + if (req_flags & UET_PDS_REQ_FLAG_RETX) + ack_flags |= UET_PDS_ACK_FLAG_RETX; + if (INET_ECN_is_ce(tos)) + ack_flags |= UET_PDS_ACK_FLAG_M; + psn_pos = psn_mpr_pos(pdc->rx_base_psn, req_psn); + switch (psn_pos) { + case UET_PDC_MPR_FUTURE: + drop_reason = "req psn is in a future MPR window"; + goto err_dbg; + case UET_PDC_MPR_PREV: + if ((int)(req_psn - pdc->rx_base_psn) < S16_MIN) { + drop_reason = "req psn is too far in the past"; + goto err_dbg; + } + uet_pdc_send_ses_ack(pdc, UET_SES_RSP_RC_NULL, ses_req->msg_id, + req_psn, ack_flags, true); + netdev_dbg(pds_netdev(pdc->pds), "%s: received a request in previous MPR window (psn %u)\n" + "pdc: [ rx_base_psn: %u state: %u" + " dpdcid: %u spdcid: %u ]\n", + __func__, req_psn, pdc->rx_base_psn, + pdc->state, pdc->dpdcid, pdc->spdcid); + goto out; + case UET_PDC_MPR_CUR: + break; + } + + psn_bit = req_psn - pdc->rx_base_psn; + if (!psn_bit_valid(psn_bit)) { + drop_reason = "req psn bit is invalid"; + goto err_dbg; + } + if (test_and_set_bit(psn_bit, pdc->rx_bitmap)) { + drop_reason = "req psn bit is already set in rx_bitmap"; + goto err_dbg; + } + + ret = 0; + switch (pdc->state) { + case UET_PDC_EP_STATE_SYN_SENT: + /* error */ + break; + case UET_PDC_EP_STATE_ESTABLISHED: + /* Rx request and do an upcall, potentially return an ack */ + ret = uet_job_fep_queue_skb(pds_context(pdc->pds), + uet_ses_req_job_id(ses_req), skb, + remote_fep_addr); + /* TODO: handle errors in sending the error */ + /* TODO: more specific RC codes */ + break; + case UET_PDC_EP_STATE_ACK_WAIT: + break; + case UET_PDC_EP_STATE_CLOSE_ACK_WAIT: + break; + } + + if (ret >= 0) + uet_pdc_send_ses_ack(pdc, UET_SES_RSP_RC_NULL, ses_req->msg_id, + req_psn, ack_flags, false); + /* TODO: NAK */ + + if (!psn_bit) + uet_pdc_mpr_advance_rx(pdc); + +out: + spin_unlock(&pdc->lock); + + return ret; +err_dbg: + netdev_dbg(pds_netdev(pdc->pds), "%s: drop reason: [ %s ]\n" + "pdc: [ rx_base_psn: %u state: %u" + " dpdcid: %u spdcid: %u ]\n" + "ses_req: [ msg id: %u ack_psn: %u spdcid: %u" + " dpdcid: %u ]\n", + __func__, drop_reason, pdc->rx_base_psn, + pdc->state, pdc->dpdcid, pdc->spdcid, + be16_to_cpu(ses_req->msg_id), be32_to_cpu(req->psn), + be16_to_cpu(req->spdcid), be16_to_cpu(req->dpdcid)); + goto out; +} diff --git a/drivers/ultraeth/uet_pds.c b/drivers/ultraeth/uet_pds.c index 4aec61eeb230..abc576e5b6e7 100644 --- a/drivers/ultraeth/uet_pds.c +++ b/drivers/ultraeth/uet_pds.c @@ -149,11 +149,144 @@ void uet_pds_clean_job(struct uet_pds *pds, u32 job_id) rhashtable_walk_exit(&iter); } +static int uet_pds_rx_ack(struct uet_pds *pds, struct sk_buff *skb, + __be32 local_fep_addr, __be32 remote_fep_addr) +{ + struct uet_pds_req_hdr *pds_req = pds_req_hdr(skb); + u16 pdcid = be16_to_cpu(pds_req->dpdcid); + struct uet_pdc *pdc; + + pdc = rhashtable_lookup_fast(&pds->pdcid_hash, &pdcid, + uet_pds_pdcid_rht_params); + if (!pdc) + return -ENOENT; + + return uet_pdc_rx_ack(pdc, skb, remote_fep_addr); +} + +static struct uet_pdc *uet_pds_new_pdc_rx(struct uet_pds *pds, + struct sk_buff *skb, + __be16 dport, + struct uet_pdc_key *key, + u8 mode, u8 state) +{ + struct uet_ses_req_hdr *ses_req = pds_req_ses_req_hdr(skb); + struct uet_pds_req_hdr *req = pds_req_hdr(skb); + + return uet_pdc_create(pds, be32_to_cpu(req->psn), state, + be16_to_cpu(req->spdcid), + uet_ses_req_pid_on_fep(ses_req), + mode, 0, dport, key, true); +} + +static int uet_pds_rx_req(struct uet_pds *pds, struct sk_buff *skb, + __be32 local_fep_addr, __be32 remote_fep_addr, + __be16 dport, __u8 tos) +{ + struct uet_ses_req_hdr *ses_req = pds_req_ses_req_hdr(skb); + struct uet_pds_req_hdr *pds_req = pds_req_hdr(skb); + u16 pdcid = be16_to_cpu(pds_req->dpdcid); + struct uet_pdc_key key = {}; + struct uet_fep *fep; + struct uet_pdc *pdc; + + key.src_ip = local_fep_addr; + key.dst_ip = remote_fep_addr; + key.job_id = uet_ses_req_job_id(ses_req); + + pdc = rhashtable_lookup_fast(&pds->pdcid_hash, &pdcid, + uet_pds_pdcid_rht_params); + /* new flow */ + if (unlikely(!pdc)) { + struct uet_prologue_hdr *prologue = pds_prologue_hdr(skb); + struct uet_context *ctx; + struct uet_job *job; + + if (!(uet_prologue_flags(prologue) & UET_PDS_REQ_FLAG_SYN)) + return -EINVAL; + + ctx = container_of(pds, struct uet_context, pds); + job = uet_job_find(&ctx->job_reg, key.job_id); + if (!job) + return -ENOENT; + fep = rcu_dereference(job->fep); + if (!fep) + return -ECONNREFUSED; + if (fep->addr.in_address.ip != local_fep_addr) + return -ENOENT; + + pdc = uet_pds_new_pdc_rx(pds, skb, dport, &key, + UET_PDC_MODE_RUD, + UET_PDC_EP_STATE_NEW_ESTABLISHED); + if (IS_ERR(pdc)) + return PTR_ERR(pdc); + } + + return uet_pdc_rx_req(pdc, skb, remote_fep_addr, tos); +} + +static bool uet_pds_rx_valid_req_next_hdr(const struct uet_prologue_hdr *prologue) +{ + switch (uet_prologue_next_hdr(prologue)) { + case UET_PDS_NEXT_HDR_REQ_STD: + break; + default: + return false; + } + + return true; +} + +static bool uet_pds_rx_valid_ack_next_hdr(const struct uet_prologue_hdr *prologue) +{ + switch (uet_prologue_next_hdr(prologue)) { + case UET_PDS_NEXT_HDR_RSP: + case UET_PDS_NEXT_HDR_RSP_DATA: + case UET_PDS_NEXT_HDR_RSP_DATA_SMALL: + break; + default: + return false; + } + + return true; +} + int uet_pds_rx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, __be32 remote_fep_addr, __be16 dport, __u8 tos) { + struct uet_prologue_hdr *prologue; + unsigned int offset = 0; + int ret = -EINVAL; + if (!pskb_may_pull(skb, sizeof(struct uet_prologue_hdr))) - return -EINVAL; + return ret; + + prologue = pds_prologue_hdr(skb); + switch (uet_prologue_type(prologue)) { + case UET_PDS_TYPE_ACK: + if (!uet_pds_rx_valid_ack_next_hdr(prologue)) + break; + offset += sizeof(struct uet_pds_ack_hdr) + + sizeof(struct uet_ses_rsp_hdr); + if (!pskb_may_pull(skb, offset)) + break; + + __net_timestamp(skb); + ret = uet_pds_rx_ack(pds, skb, local_fep_addr, remote_fep_addr); + break; + case UET_PDS_TYPE_RUD_REQ: + if (!uet_pds_rx_valid_req_next_hdr(prologue)) + break; + offset = sizeof(struct uet_pds_ack_hdr) + + sizeof(struct uet_ses_req_hdr); + if (!pskb_may_pull(skb, offset)) + break; + ret = uet_pds_rx_req(pds, skb, local_fep_addr, remote_fep_addr, + dport, tos); + break; + default: + break; + } - return 0; + return ret; } diff --git a/include/net/ultraeth/uet_pdc.h b/include/net/ultraeth/uet_pdc.h index 70f3c6aa03df..1a42647489fe 100644 --- a/include/net/ultraeth/uet_pdc.h +++ b/include/net/ultraeth/uet_pdc.h @@ -45,6 +45,12 @@ enum { UET_PDC_MODE_UUD }; +enum mpr_pos { + UET_PDC_MPR_PREV, + UET_PDC_MPR_CUR, + UET_PDC_MPR_FUTURE +}; + struct uet_pdc { struct rhash_head pdcid_node; struct rhash_head pdcep_node; @@ -63,6 +69,9 @@ struct uet_pdc { u8 mode; bool is_initiator; + unsigned long *rx_bitmap; + unsigned long *ack_bitmap; + u32 rx_base_psn; u32 tx_base_psn; @@ -76,4 +85,33 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, const struct uet_pdc_key *key, bool is_inbound); void uet_pdc_destroy(struct uet_pdc *pdc); void uet_pdc_free(struct uet_pdc *pdc); +int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, + __be32 remote_fep_addr, __u8 tos); +int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, + __be32 remote_fep_addr); + +static inline void uet_pdc_build_prologue(struct uet_prologue_hdr *prologue, + u8 type, u8 next, u8 flags) +{ + prologue->type_next_flags = cpu_to_be16((type & UET_PROLOGUE_TYPE_MASK) << + UET_PROLOGUE_TYPE_SHIFT | + (next & UET_PROLOGUE_NEXT_MASK) << + UET_PROLOGUE_NEXT_SHIFT | + (flags & UET_PROLOGUE_FLAGS_MASK)); +} + +static inline enum mpr_pos psn_mpr_pos(u32 base_psn, u32 psn) +{ + if (base_psn > psn) + return UET_PDC_MPR_PREV; + else if (psn - base_psn < UET_PDC_MPR) + return UET_PDC_MPR_CUR; + else + return UET_PDC_MPR_FUTURE; +} + +static inline bool psn_bit_valid(u32 bit) +{ + return bit < UET_PDC_MPR; +} #endif /* _UECON_PDC_H */ From patchwork Thu Mar 6 23:01:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 14005478 X-Patchwork-Delegate: kuba@kernel.org Received: from mail-qv1-f51.google.com (mail-qv1-f51.google.com [209.85.219.51]) (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 3B6BA27F4C8 for ; Thu, 6 Mar 2025 23:04:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302256; cv=none; b=qclDdUMq/CdzDSPMfFl1I5Dbj+vhnWwKL1YPHGS44aPDA2unTS031T7NKPHb1iSpyVJ4Ka4U+n/uBNFMXTkCQoKCt41wLRTb2A8PZxt+q1eBFc5J7n+S51bGMpjyi109gh1MDeQDS9YpaOlaBm49h9ruhTeb8f1EHGetjoo5izM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302256; c=relaxed/simple; bh=Hv09k34nfs1xxqBXl7TDMFKgPOtA4OG/McOv3MJH1jc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bHOhSkA3zupgdE2YGEH6m9kozhgsQMUiGhbp9PROLlDwQtEa6BMx4GVukaOAzQZJUVyHUMPzZguZaSCXhGZ3E2WsfWtxQoPstZq9IDE0ebZ3bx1tSbumR2Yojbp14hg/TqM+LulEZGTUbhkV49PeaTItlS8678om7JaIxu0NxRw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net; spf=pass smtp.mailfrom=enfabrica.net; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b=CBXZCyeB; arc=none smtp.client-ip=209.85.219.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b="CBXZCyeB" Received: by mail-qv1-f51.google.com with SMTP id 6a1803df08f44-6e6c082eac0so10897536d6.0 for ; Thu, 06 Mar 2025 15:04:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enfabrica.net; s=google; t=1741302253; x=1741907053; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=mwf9aKYfLBkH2EO+Yv/vm47l0/6N6yxicdrmpxx6Kbk=; b=CBXZCyeBbiAOgIX/aBW8MLsy1ahwrp5DO9cz5sRTSgV3ISzhb2HBXjbUBzVIM4f1Iy 0uO+keQ/Xbmjjq6nsZ9mNE1LQWb5NTIDLq+qjhhiWBhGkH5JCMAIrGlSQ3QRjWyJ8ddV BypuSNZNKbEnaZfa1Bi82bz3z92t31D0ALq+rV9kjuOeLw+/8iAQVtwOCr275ZEvLCoC yXBDH4eyS/TJPer5kgE3RjNilea3n/rF+/9DFY1yPr/YwXYOgh0cCPBud+45JzmxiMec DYbzL8Z4CS53bb0NDix5lqJsydPw1z5ojPk31Up4ArXk4hfxmkxMq2L101Fv5H8iMzxp QfWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302253; x=1741907053; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=mwf9aKYfLBkH2EO+Yv/vm47l0/6N6yxicdrmpxx6Kbk=; b=fm0vZmby0i+Tp1WO5xXNDMhn1TNj+pUbGyiHe4qt0bfjncMEHMPCUj3iNEozzr1AUD G3gOhXzovVGYAtws7ZKJUYGTc/ZxR44sfjK2pLv/n5RrjAMHBxa3rDq4lbThKGvNMr1G D/loixwByyjouD9iZWTOhhBzLaNIbYedev0db65+4LeAQtDEYDW78jSHhlIw7giQPGrC eQRJ/Ay+f7tKbdMj1Xl4e3mpRPTkQ0o01GgaY08Cj3A2vz2Sk22ThW1VDN9STm1v3TqR PI+MYtcRB43lUCGQdDje6JRnqfqPiiDdzbKJOzo9Aeh0RXbRe3lnY6AFzn0jHYr1JvYq tY0w== X-Gm-Message-State: AOJu0YySGp7oYicqYorbCWQS5P5qVOqhSg3NTIF2PQQIgPKU/z366QL/ 2k1bG+UBwtdUyHPkbFoXezUij1eRulMc9uV7JPvyeLmBdmAyshF/QLCDaVRqWkcmLpvA1ZMfKU7 K8qmbkL3iXputtayr/p8F15S/IYyoSfVqhkp0M1hBto9mkqqhjZ3caWK+0PTlG7pwmApbSlu1dm 3LrcSrzAOIDLafN20sE1Vt1WpT4ulTqrgsrs4LbqPz/30= X-Gm-Gg: ASbGnctW3ZL4HW06SDn7H1uk/pVminQi8CHMFqt64ANR1mS4YpTK29QTadtAN4wA/ET iX/aEeQ4b9Xw56KIHtH1LgdNT3ScZQiwOnjlXm8tGRCj57626rdT/iN0Py8CRBGJeI4L98APQgd AQRPRlWtURKfCU2PC/kCo+llaIfGIkJBjd8H7mBwNgXqdRpZqzyNsqwAV++QT8hgijDL76xN4pX BUZ5uFdPJHBvCXFIubolNYl7/KmruFBjJcQxVyxRayQ6DY5ufst/pSatZRZrzcdA7NWyiaEsu9E 8wiE+oHu2/jODhz8Uh+Op4Yh19jMlfs7eESV9nBwlh9JqXuVxXgRisJnDZTq2XR62Rds X-Google-Smtp-Source: AGHT+IFHoxfqPVbJbyiyNsne45S/SjH8yFhnpBfXPuEHDhvCo7LC1oPeuv2HrkdT1Q70hwCSjB7xmg== X-Received: by 2002:a05:6214:2428:b0:6e6:698f:cb00 with SMTP id 6a1803df08f44-6e9006942bamr13795096d6.42.1741302253065; Thu, 06 Mar 2025 15:04:13 -0800 (PST) Received: from debil.. (78-154-15-142.ip.btc-net.bg. [78.154.15.142]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac256654fa6sm14971966b.93.2025.03.06.15.04.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Mar 2025 15:04:12 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: shrijeet@enfabrica.net, alex.badea@keysight.com, eric.davis@broadcom.com, rip.sohan@amd.com, dsahern@kernel.org, bmt@zurich.ibm.com, roland@enfabrica.net, nikolay@enfabrica.net, winston.liu@keysight.com, dan.mihailescu@keysight.com, kheib@redhat.com, parth.v.parikh@keysight.com, davem@redhat.com, ian.ziemba@hpe.com, andrew.tauferner@cornelisnetworks.com, welch@hpe.com, rakhahari.bhunia@keysight.com, kingshuk.mandal@keysight.com, linux-rdma@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com Subject: [RFC PATCH 08/13] drivers: ultraeth: add request transmit support Date: Fri, 7 Mar 2025 01:01:58 +0200 Message-ID: <20250306230203.1550314-9-nikolay@enfabrica.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250306230203.1550314-1-nikolay@enfabrica.net> References: <20250306230203.1550314-1-nikolay@enfabrica.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Add support for sending request packets, if a PDC doesn't exist yet one gets created and the request carries the SYN flag until the first ack is received. Currently it operates in RUD (unordered) mode. The transmit packet sequence numbers are tracked via a bitmap. Track unacked packets and retransmit them upon a timeout. Signed-off-by: Nikolay Aleksandrov Signed-off-by: Alex Badea --- drivers/ultraeth/uet_pdc.c | 312 ++++++++++++++++++++++++++++++++- drivers/ultraeth/uet_pds.c | 57 ++++++ include/net/ultraeth/uet_pdc.h | 27 +++ include/net/ultraeth/uet_pds.h | 2 + 4 files changed, 389 insertions(+), 9 deletions(-) diff --git a/drivers/ultraeth/uet_pdc.c b/drivers/ultraeth/uet_pdc.c index a0352a925329..dc79305cc3b5 100644 --- a/drivers/ultraeth/uet_pdc.c +++ b/drivers/ultraeth/uet_pdc.c @@ -19,6 +19,191 @@ static void uet_pdc_xmit(struct uet_pdc *pdc, struct sk_buff *skb) dev_queue_xmit(skb); } +static void uet_pdc_mpr_advance_tx(struct uet_pdc *pdc, u32 bits) +{ + if (!test_bit(0, pdc->tx_bitmap) || !test_bit(0, pdc->ack_bitmap)) + return; + + bitmap_shift_right(pdc->tx_bitmap, pdc->tx_bitmap, bits, UET_PDC_MPR); + bitmap_shift_right(pdc->ack_bitmap, pdc->ack_bitmap, bits, UET_PDC_MPR); + pdc->tx_base_psn += bits; + netdev_dbg(pds_netdev(pdc->pds), "%s: advancing tx to %u\n", __func__, + pdc->tx_base_psn); +} + +static void uet_pdc_rtx_skb(struct uet_pdc *pdc, struct sk_buff *skb, ktime_t ts) +{ + struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); + struct uet_prologue_hdr *prologue; + + if (!nskb) + return; + + prologue = (struct uet_prologue_hdr *)nskb->data; + if (!(uet_prologue_flags(prologue) & UET_PDS_REQ_FLAG_RETX)) + uet_pdc_build_prologue(prologue, + uet_prologue_ctl_type(prologue), + uet_prologue_next_hdr(prologue), + uet_prologue_flags(prologue) | + UET_PDS_REQ_FLAG_RETX); + + uet_pdc_xmit(pdc, nskb); + skb->tstamp = ts; + UET_SKB_CB(skb)->rtx_attempts++; +} + +static void uet_pdc_rtx_timer_expired(struct timer_list *t) +{ + u64 smallest_diff = UET_PDC_RTX_DEFAULT_TIMEOUT_NSEC; + struct uet_pdc *pdc = from_timer(pdc, t, rtx_timer); + ktime_t now = ktime_get_real_ns(); + struct sk_buff *skb, *skb_tmp; + + spin_lock(&pdc->lock); + skb = skb_rb_first(&pdc->rtx_queue); + skb_rbtree_walk_from_safe(skb, skb_tmp) { + ktime_t expire = ktime_add(skb->tstamp, + UET_PDC_RTX_DEFAULT_TIMEOUT_NSEC); + + if (ktime_before(now, expire)) { + u64 diff = ktime_to_ns(ktime_sub(expire, now)); + + if (diff < smallest_diff) + smallest_diff = diff; + continue; + } + if (UET_SKB_CB(skb)->rtx_attempts == UET_PDC_RTX_DEFAULT_MAX) { + /* XXX: close connection, count drops etc */ + netdev_dbg(pds_netdev(pdc->pds), "%s: psn: %u too many rtx attempts: %u\n", + __func__, UET_SKB_CB(skb)->psn, + UET_SKB_CB(skb)->rtx_attempts); + /* if dropping the oldest packet move window */ + if (UET_SKB_CB(skb)->psn == pdc->tx_base_psn) + uet_pdc_mpr_advance_tx(pdc, 1); + rb_erase(&skb->rbnode, &pdc->rtx_queue); + consume_skb(skb); + continue; + } + + uet_pdc_rtx_skb(pdc, skb, now); + } + + mod_timer(&pdc->rtx_timer, jiffies + + nsecs_to_jiffies(smallest_diff)); + spin_unlock(&pdc->lock); +} + +static void uet_pdc_rbtree_insert(struct rb_root *root, struct sk_buff *skb) +{ + struct rb_node **p = &root->rb_node; + struct rb_node *parent = NULL; + struct sk_buff *skb1; + + while (*p) { + parent = *p; + skb1 = rb_to_skb(parent); + if (before(UET_SKB_CB(skb)->psn, UET_SKB_CB(skb1)->psn)) + p = &parent->rb_left; + else + p = &parent->rb_right; + } + + rb_link_node(&skb->rbnode, parent, p); + rb_insert_color(&skb->rbnode, root); +} + +static struct sk_buff *uet_pdc_rtx_find(struct uet_pdc *pdc, u32 psn) +{ + struct rb_node *parent, **p = &pdc->rtx_queue.rb_node; + + while (*p) { + struct sk_buff *skb; + + parent = *p; + skb = rb_to_skb(parent); + if (psn == UET_SKB_CB(skb)->psn) + return skb; + + if (before(psn, UET_SKB_CB(skb)->psn)) + p = &parent->rb_left; + else + p = &parent->rb_right; + } + + return NULL; +} + +static void uet_pdc_rtx_remove_skb(struct uet_pdc *pdc, struct sk_buff *skb) +{ + rb_erase(&skb->rbnode, &pdc->rtx_queue); + consume_skb(skb); +} + +static void uet_pdc_ack_psn(struct uet_pdc *pdc, struct sk_buff *ack_skb, + u32 psn, bool ecn_marked) +{ + struct sk_buff *skb = skb_rb_first(&pdc->rtx_queue); + u32 first_psn = skb ? UET_SKB_CB(skb)->psn : 0; + + /* if the oldest PSN got ACKed and it hasn't been retransmitted + * we can move the timer to the next one + */ + if (skb && psn == first_psn) { + struct sk_buff *next = skb_rb_next(skb); + + /* move timer only if first PSN wasn't retransmitted */ + if (next && !UET_SKB_CB(skb)->rtx_attempts) { + ktime_t expire = ktime_add(next->tstamp, + UET_PDC_RTX_DEFAULT_TIMEOUT_NSEC); + ktime_t now = ktime_get_ns(); + + if (ktime_before(expire, now)) { + u64 diff = ktime_to_ns(ktime_sub(expire, now)); + unsigned long diffj = nsecs_to_jiffies(diff); + + mod_timer(&pdc->rtx_timer, jiffies + diffj); + } + } + } else { + skb = uet_pdc_rtx_find(pdc, psn); + } + + if (!skb) + return; + + uet_pdc_rtx_remove_skb(pdc, skb); +} + +static void uet_pdc_rtx_purge(struct uet_pdc *pdc) +{ + struct rb_node *p = rb_first(&pdc->rtx_queue); + + while (p) { + struct sk_buff *skb = rb_to_skb(p); + + p = rb_next(p); + uet_pdc_rtx_remove_skb(pdc, skb); + } +} + +static int uet_pdc_rtx_queue(struct uet_pdc *pdc, struct sk_buff *skb, u32 psn) +{ + struct sk_buff *rtx_skb = skb_clone(skb, GFP_ATOMIC); + + if (unlikely(!rtx_skb)) + return -ENOMEM; + + UET_SKB_CB(rtx_skb)->psn = psn; + UET_SKB_CB(rtx_skb)->rtx_attempts = 0; + uet_pdc_rbtree_insert(&pdc->rtx_queue, rtx_skb); + + if (!timer_pending(&pdc->rtx_timer)) + mod_timer(&pdc->rtx_timer, jiffies + + UET_PDC_RTX_DEFAULT_TIMEOUT_JIFFIES); + + return 0; +} + /* use the approach as nf nat, try a few rounds starting at random offset */ static bool uet_pdc_id_get(struct uet_pdc *pdc) { @@ -69,7 +254,7 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, pdc->pds = pds; pdc->mode = mode; pdc->is_initiator = !is_inbound; - + pdc->rtx_queue = RB_ROOT; if (!uet_pdc_id_get(pdc)) goto err_id_get; @@ -83,9 +268,13 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, pdc->rx_bitmap = bitmap_zalloc(UET_PDC_MPR, GFP_ATOMIC); if (!pdc->rx_bitmap) goto err_rx_bitmap; + pdc->tx_bitmap = bitmap_zalloc(UET_PDC_MPR, GFP_ATOMIC); + if (!pdc->tx_bitmap) + goto err_tx_bitmap; pdc->ack_bitmap = bitmap_zalloc(UET_PDC_MPR, GFP_ATOMIC); if (!pdc->ack_bitmap) goto err_ack_bitmap; + timer_setup(&pdc->rtx_timer, uet_pdc_rtx_timer_expired, 0); pdc->metadata = __ip_tun_set_dst(key->src_ip, key->dst_ip, tos, 0, dport, md_flags, 0, 0); if (!pdc->metadata) @@ -124,6 +313,8 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, err_tun_dst: bitmap_free(pdc->ack_bitmap); err_ack_bitmap: + bitmap_free(pdc->tx_bitmap); +err_tx_bitmap: bitmap_free(pdc->rx_bitmap); err_rx_bitmap: uet_pds_pdcid_remove(pdc); @@ -135,8 +326,11 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, void uet_pdc_free(struct uet_pdc *pdc) { + timer_delete_sync(&pdc->rtx_timer); + uet_pdc_rtx_purge(pdc); dst_release(&pdc->metadata->dst); bitmap_free(pdc->ack_bitmap); + bitmap_free(pdc->tx_bitmap); bitmap_free(pdc->rx_bitmap); kfree(pdc); } @@ -148,6 +342,53 @@ void uet_pdc_destroy(struct uet_pdc *pdc) uet_pds_pdc_gc_queue(pdc); } +static s64 uet_pdc_get_psn(struct uet_pdc *pdc) +{ + unsigned long fzb = find_first_zero_bit(pdc->tx_bitmap, UET_PDC_MPR); + + if (unlikely(fzb == UET_PDC_MPR)) + return -1; + + set_bit(fzb, pdc->tx_bitmap); + + return pdc->tx_base_psn + fzb; +} + +static void uet_pdc_put_psn(struct uet_pdc *pdc, u32 psn) +{ + unsigned long psn_bit = psn - pdc->tx_base_psn; + + clear_bit(psn_bit, pdc->tx_bitmap); +} + +static int uet_pdc_build_req(struct uet_pdc *pdc, + struct sk_buff *skb, u8 type, u8 flags) +{ + struct uet_pds_req_hdr *req; + s64 psn; + + req = skb_push(skb, sizeof(*req)); + uet_pdc_build_prologue(&req->prologue, type, + UET_PDS_NEXT_HDR_REQ_STD, flags); + switch (pdc->state) { + case UET_PDC_EP_STATE_CLOSED: + pdc->psn_start = get_random_u32(); + pdc->tx_base_psn = pdc->psn_start; + pdc->rx_base_psn = pdc->psn_start; + break; + } + + psn = uet_pdc_get_psn(pdc); + if (unlikely(psn == -1)) + return -ENOSPC; + UET_SKB_CB(skb)->psn = psn; + req->psn = cpu_to_be32(psn); + req->spdcid = cpu_to_be16(pdc->spdcid); + req->dpdcid = cpu_to_be16(pdc->dpdcid); + + return 0; +} + static void pdc_build_ack(struct uet_pdc *pdc, struct sk_buff *skb, u32 psn, u8 ack_flags, bool exact_psn) { @@ -200,15 +441,65 @@ static int uet_pdc_send_ses_ack(struct uet_pdc *pdc, __u8 ses_rc, __be16 msg_id, return 0; } -static void uet_pdc_mpr_advance_tx(struct uet_pdc *pdc, u32 bits) +int uet_pdc_tx_req(struct uet_pdc *pdc, struct sk_buff *skb, u8 type) { - if (!test_bit(0, pdc->ack_bitmap)) - return; + struct uet_pds_req_hdr *req; + int ret = 0; - bitmap_shift_right(pdc->ack_bitmap, pdc->ack_bitmap, bits, UET_PDC_MPR); - pdc->tx_base_psn += bits; - netdev_dbg(pds_netdev(pdc->pds), "%s: advancing tx to %u\n", __func__, - pdc->tx_base_psn); + spin_lock_bh(&pdc->lock); + if (pdc->tx_busy) { + ret = -EBUSY; + goto out_unlock; + } + + switch (pdc->state) { + case UET_PDC_EP_STATE_CLOSED: + ret = uet_pdc_build_req(pdc, skb, type, UET_PDS_REQ_FLAG_SYN); + if (ret) + goto out_unlock; + req = (struct uet_pds_req_hdr *)skb->data; + ret = uet_pdc_rtx_queue(pdc, skb, be32_to_cpu(req->psn)); + if (ret) { + uet_pdc_put_psn(pdc, be32_to_cpu(req->psn)); + goto out_unlock; + } + pdc->state = UET_PDC_EP_STATE_SYN_SENT; + pdc->tx_busy = true; + break; + case UET_PDC_EP_STATE_SYN_SENT: + break; + case UET_PDC_EP_STATE_ESTABLISHED: + ret = uet_pdc_build_req(pdc, skb, type, 0); + if (ret) + goto out_unlock; + req = (struct uet_pds_req_hdr *)skb->data; + ret = uet_pdc_rtx_queue(pdc, skb, be32_to_cpu(req->psn)); + if (ret) { + uet_pdc_put_psn(pdc, be32_to_cpu(req->psn)); + goto out_unlock; + } + break; + case UET_PDC_EP_STATE_QUIESCE: + break; + case UET_PDC_EP_STATE_ACK_WAIT: + break; + case UET_PDC_EP_STATE_CLOSE_ACK_WAIT: + break; + default: + WARN_ON(1); + } + +out_unlock: + netdev_dbg(pds_netdev(pdc->pds), "%s: tx_busy: %u pdc: [ tx_base_psn: %u" + " state: %u dpdcid: %u spdcid: %u ] proto 0x%x\n", + __func__, pdc->tx_busy, pdc->tx_base_psn, pdc->state, + pdc->dpdcid, pdc->spdcid, ntohs(skb->protocol)); + spin_unlock_bh(&pdc->lock); + + if (!ret) + uet_pdc_xmit(pdc, skb); + + return ret; } int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, @@ -221,6 +512,7 @@ int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, u32 cack_psn = be32_to_cpu(ack->cack_psn); u32 ack_psn = cack_psn + ack_psn_offset; int ret = -EINVAL; + bool ecn_marked; u32 psn_bit; spin_lock(&pdc->lock); @@ -237,7 +529,7 @@ int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, goto err_dbg; psn_bit = ack_psn - pdc->tx_base_psn; - if (!psn_bit_valid(psn_bit)) { + if (!psn_bit_valid(psn_bit) || !test_bit(psn_bit, pdc->tx_bitmap)) { drop_reason = "ack_psn bit is invalid"; goto err_dbg; } @@ -252,6 +544,8 @@ int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, /* we can advance only if the oldest pkt got acked */ if (!psn_bit) uet_pdc_mpr_advance_tx(pdc, 1); + ecn_marked = !!(uet_prologue_flags(&ack->prologue) & UET_PDS_ACK_FLAG_M); + uet_pdc_ack_psn(pdc, skb, ack_psn, ecn_marked); ret = 0; switch (pdc->state) { diff --git a/drivers/ultraeth/uet_pds.c b/drivers/ultraeth/uet_pds.c index abc576e5b6e7..7efb634de85f 100644 --- a/drivers/ultraeth/uet_pds.c +++ b/drivers/ultraeth/uet_pds.c @@ -290,3 +290,60 @@ int uet_pds_rx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, return ret; } + +static struct uet_pdc *uet_pds_new_pdc_tx(struct uet_pds *pds, + struct sk_buff *skb, + __be16 dport, + struct uet_pdc_key *key, + u8 mode, u8 state) +{ + struct uet_ses_req_hdr *ses_req = (struct uet_ses_req_hdr *)skb->data; + + return uet_pdc_create(pds, 0, state, 0, + uet_ses_req_pid_on_fep(ses_req), + mode, 0, dport, key, false); +} + +int uet_pds_tx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, + __be32 remote_fep_addr, __be16 dport, u32 job_id) +{ + struct uet_ses_req_hdr *ses_req = (struct uet_ses_req_hdr *)skb->data; + u32 req_job_id = uet_ses_req_job_id(ses_req); + struct uet_pdc_key key = {}; + struct uet_pdc *pdc; + + /* sending with wrong SES header job id? */ + if (unlikely(job_id != req_job_id)) + return -EINVAL; + + key.src_ip = local_fep_addr; + key.dst_ip = remote_fep_addr; + key.job_id = job_id; + + pdc = rhashtable_lookup_fast(&pds->pdcep_hash, &key, + uet_pds_pdcep_rht_params); + /* new flow */ + if (unlikely(!pdc)) { + struct uet_context *ctx; + struct uet_job *job; + struct uet_fep *fep; + + ctx = container_of(pds, struct uet_context, pds); + job = uet_job_find(&ctx->job_reg, key.job_id); + if (!job) + return -ENOENT; + fep = rcu_dereference(job->fep); + if (!fep) + return -ECONNREFUSED; + + pdc = uet_pds_new_pdc_tx(pds, skb, dport, &key, + UET_PDC_MODE_RUD, + UET_PDC_EP_STATE_CLOSED); + if (IS_ERR(pdc)) + return PTR_ERR(pdc); + } + + __net_timestamp(skb); + + return uet_pdc_tx_req(pdc, skb, UET_PDS_TYPE_RUD_REQ); +} diff --git a/include/net/ultraeth/uet_pdc.h b/include/net/ultraeth/uet_pdc.h index 1a42647489fe..261afc57ffe1 100644 --- a/include/net/ultraeth/uet_pdc.h +++ b/include/net/ultraeth/uet_pdc.h @@ -13,6 +13,12 @@ #define UET_PDC_ID_MAX_ATTEMPTS 128 #define UET_PDC_MAX_ID U16_MAX +#define UET_PDC_RTX_DEFAULT_TIMEOUT_SEC 30 +#define UET_PDC_RTX_DEFAULT_TIMEOUT_JIFFIES (UET_PDC_RTX_DEFAULT_TIMEOUT_SEC * \ + HZ) +#define UET_PDC_RTX_DEFAULT_TIMEOUT_NSEC (UET_PDC_RTX_DEFAULT_TIMEOUT_SEC * \ + NSEC_PER_SEC) +#define UET_PDC_RTX_DEFAULT_MAX 3 #define UET_PDC_MPR 128 #define UET_SKB_CB(skb) ((struct uet_skb_cb *)&((skb)->cb[0])) @@ -20,6 +26,7 @@ struct uet_skb_cb { u32 psn; __be32 remote_fep_addr; + u8 rtx_attempts; }; enum { @@ -51,6 +58,13 @@ enum mpr_pos { UET_PDC_MPR_FUTURE }; +struct uet_pdc_pkt { + struct sk_buff *skb; + struct timer_list rtx_timer; + u32 psn; + int rtx; +}; + struct uet_pdc { struct rhash_head pdcid_node; struct rhash_head pdcep_node; @@ -69,12 +83,19 @@ struct uet_pdc { u8 mode; bool is_initiator; + int rtx_max; + struct timer_list rtx_timer; + unsigned long rtx_timeout; + unsigned long *rx_bitmap; + unsigned long *tx_bitmap; unsigned long *ack_bitmap; u32 rx_base_psn; u32 tx_base_psn; + struct rb_root rtx_queue; + struct hlist_node gc_node; struct rcu_head rcu; }; @@ -89,6 +110,7 @@ int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, __be32 remote_fep_addr, __u8 tos); int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, __be32 remote_fep_addr); +int uet_pdc_tx_req(struct uet_pdc *pdc, struct sk_buff *skb, u8 type); static inline void uet_pdc_build_prologue(struct uet_prologue_hdr *prologue, u8 type, u8 next, u8 flags) @@ -114,4 +136,9 @@ static inline bool psn_bit_valid(u32 bit) { return bit < UET_PDC_MPR; } + +static inline bool before(u32 seq1, u32 seq2) +{ + return (s32)(seq1-seq2) < 0; +} #endif /* _UECON_PDC_H */ diff --git a/include/net/ultraeth/uet_pds.h b/include/net/ultraeth/uet_pds.h index 43f5748a318a..78624370f18c 100644 --- a/include/net/ultraeth/uet_pds.h +++ b/include/net/ultraeth/uet_pds.h @@ -40,6 +40,8 @@ void uet_pds_clean_job(struct uet_pds *pds, u32 job_id); int uet_pds_rx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, __be32 remote_fep_addr, __be16 dport, __u8 tos); +int uet_pds_tx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, + __be32 remote_fep_addr, __be16 dport, u32 job_id); static inline struct uet_prologue_hdr *pds_prologue_hdr(const struct sk_buff *skb) { From patchwork Thu Mar 6 23:01:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 14005479 X-Patchwork-Delegate: kuba@kernel.org Received: from mail-qv1-f47.google.com (mail-qv1-f47.google.com [209.85.219.47]) (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 32B4627FE85 for ; Thu, 6 Mar 2025 23:04:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302258; cv=none; b=kzzB51ZStTDb6zzTZsg4KiIJQhK21iPQjbe1fFdXQKcZV6VpuLqkbqBvQLSqXBQbpkXnQW0BeTNjiWLlPXkFni4tfeoMsb7FaMytwCzZkh+jQX5UAer1L0K64nOKa98JfrS5uZRnd15svqlC5wQnzWNtBqqJ4bSLaN44D5TaypQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302258; c=relaxed/simple; bh=SzQBH+aJ7uQP95syJXM9qrZRtDlY6w6Q12Y1VuqlJb4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eODryBbQbfX/xwT0vaLQxD7z5ZXrK4DOXwRliObjzhGUiStIocFb0Y1DPXS4AaKC4KM9AewyMhAIEio4I/uzMpFRJOX1B02N5drMEED3/a5zTOzgvoQbGAy6Vc9I/8Bqt3bIv+5tKBy1sBw67EiIFtNx2G/cKkwTYUdip1sLDts= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net; spf=pass smtp.mailfrom=enfabrica.net; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b=JKz/tWxO; arc=none smtp.client-ip=209.85.219.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b="JKz/tWxO" Received: by mail-qv1-f47.google.com with SMTP id 6a1803df08f44-6dd049b5428so11999686d6.2 for ; Thu, 06 Mar 2025 15:04:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enfabrica.net; s=google; t=1741302255; x=1741907055; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tbiaBeimFuoiyQMyCyzRbpsj0biLaKIOphHeUsu9H70=; b=JKz/tWxOxui6zhHIyqPu6buPu67w+cf+AjBmH4hH2Wro8QhH+i88tOtgPMuLE3/c98 +FEbqIySg5/3oAS2ga2fdVyqyTINUDN8dhNd++JydyJfllk67q/SP9uR5vqhNrl7kaVd NtvWF52iywvNRVVsNr1zDFbQBS7BjCDLnepkFtfM51gESox3Ia0098Yw3tuXTb3u76Qc ibKgoxJT9+foIFyGSv3yR0hubQxX9C82YVTKQ2G8MnwkjTf1QkdMPQLBnoUkOxl8xjfh ufT5k5xSkHuLjTBCwVDyBJd128hxBvYA8Wlp3uIuT8T5lUXq2n76YJfpFsxiHR1rlYJH HdLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302255; x=1741907055; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tbiaBeimFuoiyQMyCyzRbpsj0biLaKIOphHeUsu9H70=; b=Hk8gwxrCpkI8AOFGAvNsD5yWU2BNEBivVMyXODFar9jTKUNp0SEGP6FJZeyJmi8qUD GIdgXzjV16NAc3JiK9L2FWzuLOFpL9vJwo43C4aZ3/8WtPEj6tf/Vqd2IYgwmGStmNNm 3HIl+gphqHE/eV8yjcF5SxjetrxePlUbvkeUrKMtJfX/csGkx4trN0JfXE+q9y/AZo3u 8JaiNt1Ae+X2jkqrH4ivPf8+bRno01WIwXBblf3guyeECIoEO6cr33nc05Me64L+wV4Z E34GGP/9ZZz29/Kfa2L71/nkVrV0d7ur86xWtIE0QJcT5bNi7Y0KxrDnsQjbaAdV/yit Gw1w== X-Gm-Message-State: AOJu0YyyYlOxIHsfOIokf3LNq9+3ru0cq8KpoTuLtfzYELAf6/jEVsvr olgojbRAq5RleJAkcKQy4146DDipZrOCojZ88ENgWhVerHDUe87rpiOBY6JPw/NswlGx2aD58za R8AuJewIwLrqZWFXAq71OZeQ7bh152FJlQe1czt/h/YYObS8KGFe4y71QIWNAm0r7cBZAmVDNg3 c9ZZKJWmDnZkjVtYDFj8ho+nXf6B3N/yJ31tyo7gEmA6Q= X-Gm-Gg: ASbGnctMvMFzdJpuerCz39kX2faYQhyiEdCwxZLxG75X7gaVeD78mJqzgp+tqjeU+Lu egykakqMziuTWc6fBrj+VwdOcCp4AxmFDeTKZKIxl9RCpQ1qHob6ZQI62i7d/Ztb0Yp0cGhg5mr U97oQnXVAfXHQzJyE47Jx3sEI45iwtvSg3CeQQ9hNO3AJi7qZ/82NNFRUEIBQ8JTfTbH8vqZ3rF C4V9F3TZTm/ykhHgbO/SCZNzgW+iEszpIsfBENI+nJDGsGKjjK385bU73XWKohwT9lIyu/FoykB yAd9klwCxhz76qZWtO48CmMCP1YG2V+7uP65eFnZXvSUZJCahQqt84s+xfiWVmJYpEKf X-Google-Smtp-Source: AGHT+IFO4ljE3Jnq8tK8vQH0OpdIT3/hzxnbcFQQ4i0RMAXe96e1At61yaCm/Ax7yEb66ZweInmCRQ== X-Received: by 2002:a05:6214:528a:b0:6e8:feb2:bad9 with SMTP id 6a1803df08f44-6e900670d1cmr11171096d6.30.1741302254847; Thu, 06 Mar 2025 15:04:14 -0800 (PST) Received: from debil.. (78-154-15-142.ip.btc-net.bg. [78.154.15.142]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac256654fa6sm14971966b.93.2025.03.06.15.04.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Mar 2025 15:04:14 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: shrijeet@enfabrica.net, alex.badea@keysight.com, eric.davis@broadcom.com, rip.sohan@amd.com, dsahern@kernel.org, bmt@zurich.ibm.com, roland@enfabrica.net, nikolay@enfabrica.net, winston.liu@keysight.com, dan.mihailescu@keysight.com, kheib@redhat.com, parth.v.parikh@keysight.com, davem@redhat.com, ian.ziemba@hpe.com, andrew.tauferner@cornelisnetworks.com, welch@hpe.com, rakhahari.bhunia@keysight.com, kingshuk.mandal@keysight.com, linux-rdma@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com Subject: [RFC PATCH 09/13] drivers: ultraeth: add support for coalescing ack Date: Fri, 7 Mar 2025 01:01:59 +0200 Message-ID: <20250306230203.1550314-10-nikolay@enfabrica.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250306230203.1550314-1-nikolay@enfabrica.net> References: <20250306230203.1550314-1-nikolay@enfabrica.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC This patch adds Rx support for coalescing ack based on the PDS spec. It is controlled by two per-FEP variables that can be set when the FEP requests to be associated to a job: - ack_gen_trigger: number of bytes that will trigger an ACK - ack_gen_min_pkt_add: minimum number of bytes to add on each packet The default values are ack_gen_trigger = 16KB and ack_gen_min_pkt_add = 1KB as per the spec. Signed-off-by: Nikolay Aleksandrov Signed-off-by: Alex Badea --- drivers/ultraeth/uet_pdc.c | 119 ++++++++++++++++++++++++--------- drivers/ultraeth/uet_pds.c | 18 +++-- include/net/ultraeth/uet_job.h | 2 + include/net/ultraeth/uet_pdc.h | 7 +- include/uapi/linux/ultraeth.h | 2 + 5 files changed, 111 insertions(+), 37 deletions(-) diff --git a/drivers/ultraeth/uet_pdc.c b/drivers/ultraeth/uet_pdc.c index dc79305cc3b5..55b893ac5479 100644 --- a/drivers/ultraeth/uet_pdc.c +++ b/drivers/ultraeth/uet_pdc.c @@ -19,9 +19,9 @@ static void uet_pdc_xmit(struct uet_pdc *pdc, struct sk_buff *skb) dev_queue_xmit(skb); } -static void uet_pdc_mpr_advance_tx(struct uet_pdc *pdc, u32 bits) +static void __uet_pdc_mpr_advance_tx(struct uet_pdc *pdc, u32 bits) { - if (!test_bit(0, pdc->tx_bitmap) || !test_bit(0, pdc->ack_bitmap)) + if (WARN_ON_ONCE(bits >= UET_PDC_MPR)) return; bitmap_shift_right(pdc->tx_bitmap, pdc->tx_bitmap, bits, UET_PDC_MPR); @@ -31,6 +31,15 @@ static void uet_pdc_mpr_advance_tx(struct uet_pdc *pdc, u32 bits) pdc->tx_base_psn); } +static void uet_pdc_mpr_advance_tx(struct uet_pdc *pdc, u32 cack_psn) +{ + /* cumulative ack, clear all prior and including cack_psn */ + if (cack_psn > pdc->tx_base_psn) + __uet_pdc_mpr_advance_tx(pdc, cack_psn - pdc->tx_base_psn); + else if (test_bit(0, pdc->tx_bitmap) && test_bit(0, pdc->ack_bitmap)) + __uet_pdc_mpr_advance_tx(pdc, 1); +} + static void uet_pdc_rtx_skb(struct uet_pdc *pdc, struct sk_buff *skb, ktime_t ts) { struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); @@ -227,7 +236,8 @@ static bool uet_pdc_id_get(struct uet_pdc *pdc) struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, u16 dpdcid, u16 pid_on_fep, u8 mode, - u8 tos, __be16 dport, + u8 tos, __be16 dport, u32 ack_gen_trigger, + u32 ack_gen_min_pkt_add, const struct uet_pdc_key *key, bool is_inbound) { struct uet_pdc *pdc, *pdc_ins = ERR_PTR(-ENOMEM); @@ -254,6 +264,8 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, pdc->pds = pds; pdc->mode = mode; pdc->is_initiator = !is_inbound; + pdc->ack_gen_trigger = ack_gen_trigger; + pdc->ack_gen_min_pkt_add = ack_gen_min_pkt_add; pdc->rtx_queue = RB_ROOT; if (!uet_pdc_id_get(pdc)) goto err_id_get; @@ -541,11 +553,25 @@ int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, /* either using ROD mode or in SYN_SENT state */ if (pdc->tx_busy) pdc->tx_busy = false; - /* we can advance only if the oldest pkt got acked */ - if (!psn_bit) - uet_pdc_mpr_advance_tx(pdc, 1); ecn_marked = !!(uet_prologue_flags(&ack->prologue) & UET_PDS_ACK_FLAG_M); - uet_pdc_ack_psn(pdc, skb, ack_psn, ecn_marked); + /* we can advance only if the oldest pkt got acked or we got + * a cumulative ack clearing >= 1 older packets + */ + if (!psn_bit || cack_psn > pdc->tx_base_psn) { + if (cack_psn >= pdc->tx_base_psn) { + u32 i; + + for (i = 0; i <= cack_psn - pdc->tx_base_psn; i++) + uet_pdc_ack_psn(pdc, skb, cack_psn - i, + ecn_marked); + } + + uet_pdc_mpr_advance_tx(pdc, cack_psn); + } + + /* minor optimization, this can happen only if they are != */ + if (cack_psn != ack_psn) + uet_pdc_ack_psn(pdc, skb, ack_psn, ecn_marked); ret = 0; switch (pdc->state) { @@ -584,13 +610,39 @@ int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, static void uet_pdc_mpr_advance_rx(struct uet_pdc *pdc) { - if (!test_bit(0, pdc->rx_bitmap)) + unsigned long fzb = find_first_zero_bit(pdc->rx_bitmap, UET_PDC_MPR); + u32 old_psn = pdc->rx_base_psn; + + if (fzb == 0) return; - bitmap_shift_right(pdc->rx_bitmap, pdc->rx_bitmap, 1, UET_PDC_MPR); - pdc->rx_base_psn++; - netdev_dbg(pds_netdev(pdc->pds), "%s: advancing rx to %u\n", - __func__, pdc->rx_base_psn); + bitmap_shift_right(pdc->rx_bitmap, pdc->rx_bitmap, fzb, UET_PDC_MPR); + pdc->rx_base_psn += fzb; + netdev_dbg(pds_netdev(pdc->pds), "%s: advancing rx from %u to %u (%lu)\n", + __func__, old_psn, pdc->rx_base_psn, fzb); +} + +static void uet_pdc_rx_req_handle_ack(struct uet_pdc *pdc, unsigned int len, + __be16 msg_id, u8 req_flags, u32 req_psn, + u8 ack_flags, bool first_ack) +{ + pdc->ack_gen_count += max(pdc->ack_gen_min_pkt_add, len); + if (first_ack || + (req_flags & (UET_PDS_REQ_FLAG_AR | UET_PDS_REQ_FLAG_RETX)) || + pdc->ack_gen_count >= pdc->ack_gen_trigger) { + /* first advance so if the current psn == rx_base_psn + * we will clear it with the cumulative ack + */ + uet_pdc_mpr_advance_rx(pdc); + pdc->ack_gen_count = 0; + /* req_psn is inside the cumulative ack range, so + * it is covered by it + */ + if (unlikely(req_psn < pdc->rx_base_psn)) + req_psn = pdc->rx_base_psn; + uet_pdc_send_ses_ack(pdc, UET_SES_RSP_RC_NULL, msg_id, req_psn, + ack_flags, false); + } } int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, @@ -601,7 +653,9 @@ int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, u8 req_flags = uet_prologue_flags(&req->prologue), ack_flags = 0; u32 req_psn = be32_to_cpu(req->psn); const char *drop_reason = "tx_busy"; - unsigned long psn_bit; + __be16 msg_id = ses_req->msg_id; + unsigned int len = skb->len; + bool first_ack = false; enum mpr_pos psn_pos; int ret = -EINVAL; @@ -648,22 +702,31 @@ int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, break; } - psn_bit = req_psn - pdc->rx_base_psn; - if (!psn_bit_valid(psn_bit)) { - drop_reason = "req psn bit is invalid"; - goto err_dbg; - } - if (test_and_set_bit(psn_bit, pdc->rx_bitmap)) { - drop_reason = "req psn bit is already set in rx_bitmap"; - goto err_dbg; - } - - ret = 0; switch (pdc->state) { case UET_PDC_EP_STATE_SYN_SENT: /* error */ break; + case UET_PDC_EP_STATE_NEW_ESTABLISHED: + /* special state when a connection is new, we need to + * send first ack immediately + */ + pdc->state = UET_PDC_EP_STATE_ESTABLISHED; + first_ack = true; + fallthrough; case UET_PDC_EP_STATE_ESTABLISHED: + if (!first_ack) { + unsigned long psn_bit = req_psn - pdc->rx_base_psn - 1; + + if (!psn_bit_valid(psn_bit)) { + drop_reason = "req psn bit is invalid"; + goto err_dbg; + } + if (test_and_set_bit(psn_bit, pdc->rx_bitmap)) { + drop_reason = "req psn bit is already set in rx_bitmap"; + goto err_dbg; + } + } + /* Rx request and do an upcall, potentially return an ack */ ret = uet_job_fep_queue_skb(pds_context(pdc->pds), uet_ses_req_job_id(ses_req), skb, @@ -678,12 +741,8 @@ int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, } if (ret >= 0) - uet_pdc_send_ses_ack(pdc, UET_SES_RSP_RC_NULL, ses_req->msg_id, - req_psn, ack_flags, false); - /* TODO: NAK */ - - if (!psn_bit) - uet_pdc_mpr_advance_rx(pdc); + uet_pdc_rx_req_handle_ack(pdc, len, msg_id, req_flags, + req_psn, ack_flags, first_ack); out: spin_unlock(&pdc->lock); diff --git a/drivers/ultraeth/uet_pds.c b/drivers/ultraeth/uet_pds.c index 7efb634de85f..52122998079d 100644 --- a/drivers/ultraeth/uet_pds.c +++ b/drivers/ultraeth/uet_pds.c @@ -166,7 +166,8 @@ static int uet_pds_rx_ack(struct uet_pds *pds, struct sk_buff *skb, static struct uet_pdc *uet_pds_new_pdc_rx(struct uet_pds *pds, struct sk_buff *skb, - __be16 dport, + __be16 dport, u32 ack_gen_trigger, + u32 ack_gen_min_pkt_add, struct uet_pdc_key *key, u8 mode, u8 state) { @@ -176,7 +177,8 @@ static struct uet_pdc *uet_pds_new_pdc_rx(struct uet_pds *pds, return uet_pdc_create(pds, be32_to_cpu(req->psn), state, be16_to_cpu(req->spdcid), uet_ses_req_pid_on_fep(ses_req), - mode, 0, dport, key, true); + mode, 0, dport, ack_gen_trigger, + ack_gen_min_pkt_add, key, true); } static int uet_pds_rx_req(struct uet_pds *pds, struct sk_buff *skb, @@ -215,7 +217,8 @@ static int uet_pds_rx_req(struct uet_pds *pds, struct sk_buff *skb, if (fep->addr.in_address.ip != local_fep_addr) return -ENOENT; - pdc = uet_pds_new_pdc_rx(pds, skb, dport, &key, + pdc = uet_pds_new_pdc_rx(pds, skb, dport, fep->ack_gen_trigger, + fep->ack_gen_min_pkt_add, &key, UET_PDC_MODE_RUD, UET_PDC_EP_STATE_NEW_ESTABLISHED); if (IS_ERR(pdc)) @@ -293,7 +296,8 @@ int uet_pds_rx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, static struct uet_pdc *uet_pds_new_pdc_tx(struct uet_pds *pds, struct sk_buff *skb, - __be16 dport, + __be16 dport, u32 ack_gen_trigger, + u32 ack_gen_min_pkt_add, struct uet_pdc_key *key, u8 mode, u8 state) { @@ -301,7 +305,8 @@ static struct uet_pdc *uet_pds_new_pdc_tx(struct uet_pds *pds, return uet_pdc_create(pds, 0, state, 0, uet_ses_req_pid_on_fep(ses_req), - mode, 0, dport, key, false); + mode, 0, dport, ack_gen_trigger, + ack_gen_min_pkt_add, key, false); } int uet_pds_tx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, @@ -336,7 +341,8 @@ int uet_pds_tx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, if (!fep) return -ECONNREFUSED; - pdc = uet_pds_new_pdc_tx(pds, skb, dport, &key, + pdc = uet_pds_new_pdc_tx(pds, skb, dport, fep->ack_gen_trigger, + fep->ack_gen_min_pkt_add, &key, UET_PDC_MODE_RUD, UET_PDC_EP_STATE_CLOSED); if (IS_ERR(pdc)) diff --git a/include/net/ultraeth/uet_job.h b/include/net/ultraeth/uet_job.h index fac1f0752a78..555706a21e96 100644 --- a/include/net/ultraeth/uet_job.h +++ b/include/net/ultraeth/uet_job.h @@ -21,6 +21,8 @@ struct uet_fep { struct uet_context *context; struct sk_buff_head rxq; struct fep_address addr; + u32 ack_gen_trigger; + u32 ack_gen_min_pkt_add; u32 job_id; }; diff --git a/include/net/ultraeth/uet_pdc.h b/include/net/ultraeth/uet_pdc.h index 261afc57ffe1..8a87fc0bc869 100644 --- a/include/net/ultraeth/uet_pdc.h +++ b/include/net/ultraeth/uet_pdc.h @@ -94,6 +94,10 @@ struct uet_pdc { u32 rx_base_psn; u32 tx_base_psn; + u32 ack_gen_trigger; + u32 ack_gen_min_pkt_add; + u32 ack_gen_count; + struct rb_root rtx_queue; struct hlist_node gc_node; @@ -102,7 +106,8 @@ struct uet_pdc { struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, u16 dpdcid, u16 pid_on_fep, u8 mode, - u8 tos, __be16 dport, + u8 tos, __be16 dport, u32 ack_gen_trigger, + u32 ack_gen_min_pkt_add, const struct uet_pdc_key *key, bool is_inbound); void uet_pdc_destroy(struct uet_pdc *pdc); void uet_pdc_free(struct uet_pdc *pdc); diff --git a/include/uapi/linux/ultraeth.h b/include/uapi/linux/ultraeth.h index 6f3ee5ac8cf4..cc39bf970e08 100644 --- a/include/uapi/linux/ultraeth.h +++ b/include/uapi/linux/ultraeth.h @@ -8,6 +8,8 @@ #define UET_DEFAULT_PORT 5432 #define UET_SVC_MAX_LEN 64 +#define UET_DEFAULT_ACK_GEN_TRIGGER (1 << 14) +#define UET_DEFAULT_ACK_GEN_MIN_PKT_ADD (1 << 10) /* types used for prologue's type field */ enum { From patchwork Thu Mar 6 23:02:00 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 14005480 X-Patchwork-Delegate: kuba@kernel.org Received: from mail-qv1-f52.google.com (mail-qv1-f52.google.com [209.85.219.52]) (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 354DC2803FD for ; Thu, 6 Mar 2025 23:04:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302260; cv=none; b=eDnGACZTP3rlYJGKFdpl+VJQ3Vojw9M8r9oyQLFoNSoIpi1pOvp+u0QtHz3+Zf/K1TiwpVx93Kl/Xn43H0wqNMdz43fLyhbvjyKf3TFZlew9UnxYHLNZgQfYllqvzjqVP7E0ZFIe7LVS+TRkfGsLDo1GDTjth4/t4+EJDWJqGyU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302260; c=relaxed/simple; bh=8zoJVMPNc2FcN+4s7xjapXpTwku8ERNAOulLVuTwkis=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G1ipSp//w5rohyey2THx+LttWJgPVFR5Cb4m5aQixsmrLSBtpAf1HstxNq0lZBulXpFvDxCAtzq6rrCX6yYXSCH0RS5kk6mH1fupKI83ji23E2GXU9uWF3lg8IHTlVssKW5Ph7Mh64vHvBI3+l6ULYt2doJtYHoBWphvuDCY5JE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net; spf=pass smtp.mailfrom=enfabrica.net; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b=S7PASkt1; arc=none smtp.client-ip=209.85.219.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b="S7PASkt1" Received: by mail-qv1-f52.google.com with SMTP id 6a1803df08f44-6e8fb8ad525so8226166d6.3 for ; Thu, 06 Mar 2025 15:04:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enfabrica.net; s=google; t=1741302257; x=1741907057; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=iK4c5koKFv1LWAiQEBPg2eanOfUAKl1IQ+bM1zpj/YY=; b=S7PASkt1v+wU1hrJp67RK/pmk+ULSaNnddrZa6vZENx9B1mCbDnEC+SNeay2fhmjUx PuHEInp63tNXRrZjMK6HZDGNQ3xmF3pm795M9IgB5nbtoZDtocP+W/4KndeDQ+5obMOW eYxJqErfQbgZ+ljOEbCJ42zEP0S7fkHgi9oj9zQiLAOuqoqZFUHdGypqR4j2wNGvsdjf Dibltc3wL77IXhsrW/XnAJf9AoN9J+j4095XiPHdHeOuHZ7DfF8cmiVxSvYWjsLDjnP0 zcyVR0uBViyGX2NewdzoHiecTAYPQPD1qROi35LLJD2E3mXALJYVd1Fu7E49Zfbqnv3r /h+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302257; x=1741907057; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=iK4c5koKFv1LWAiQEBPg2eanOfUAKl1IQ+bM1zpj/YY=; b=pCG1mlRdUsLhyAjY+9+3er6+nIyFf5dqoQQY3pruBprgQgRXc1zRLNU9GRp/6T4FH3 3atxsEQyy1mgtrt+SsEhPT7bIEQsvQknPnGVRB01O4mbF7ZZmiSoeLacIojANMznD57c PjZgVjBV0R9UACx3mQBtoRUutaI60LQlgQ5K/g9E4EKlaCGPMRQR0fwM/UoFMHZ8IQXT EoIb8XuUC5A4UfMio31bnFtjSep0BCPYwvarZ9vIadS9qz4moX3/dWi+1wvPkKH8LwiH Tqu6BDIw+m8i+h8R7R2myVp+bQ9iztgzwp6AQzmSjvJAaq082jfj6q7r0uXAmUeQdjmz gDIg== X-Gm-Message-State: AOJu0YzhJbyMMBYEb0IqD5O4nIr+oTzwbtozeoUekJFKI9mVfiBrs0/B VjQ6ObFX7Cbj6YR4+BwuUdbXtPtYEPqsj46RIr6rprBx1bMHcFE6qf6VxVsZtSWQopsxCkDGkMJ 9iJPFMZ5cHNU5dF/sgD1CV2Ob7K+RWWjzWlzPwHxB/jrCkzaZwmHCHfbzoYgrjZF4ZEZ+FMvRN3 A97uya6GgzhRAT6CIaPbwbtW2JF3V4AcQjUdlFJJgpdas= X-Gm-Gg: ASbGncuMyVG1u8mbv8UMbQZpmV3IjyYG+pEja/zUwn0fWpoiXewiSmrR3fu8AleKGHZ GWzwErQg5PRFT96Pi4Ob7+rS04nVLcFEiy4b3mF4I3W8RQUARBPYtqErIlXg/hu981Yy8p9zoqb OBvXTYA2OWlUuNTYXseOiOjJXGkO9P1XJU7d4sc7FbObWIeSbFYO4wshy7BHfG4Ps5uZFaki9tu 11oHXHDXhDAljpRlCMUDYDOwX+m0M4MGV0rx41c6Uvl0gJLkkO0TP0oJHoYHj/Ea/rSownwhI+R fiAmwObqgRUvladeRueTbvcFdT1gCMIk2OTt+EpLx8sDel4aQdjnlNL93qxd10GOoUsY X-Google-Smtp-Source: AGHT+IHxTfaUjmuCoF7ih1GrTDipQZTYiCzwagxprA1b0yB9ai/NIjpk6yNwjcfOnnxMdiGhDrPEYQ== X-Received: by 2002:ad4:5beb:0:b0:6e8:ed7f:1a79 with SMTP id 6a1803df08f44-6e9006773e7mr18910576d6.32.1741302256701; Thu, 06 Mar 2025 15:04:16 -0800 (PST) Received: from debil.. (78-154-15-142.ip.btc-net.bg. [78.154.15.142]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac256654fa6sm14971966b.93.2025.03.06.15.04.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Mar 2025 15:04:16 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: shrijeet@enfabrica.net, alex.badea@keysight.com, eric.davis@broadcom.com, rip.sohan@amd.com, dsahern@kernel.org, bmt@zurich.ibm.com, roland@enfabrica.net, nikolay@enfabrica.net, winston.liu@keysight.com, dan.mihailescu@keysight.com, kheib@redhat.com, parth.v.parikh@keysight.com, davem@redhat.com, ian.ziemba@hpe.com, andrew.tauferner@cornelisnetworks.com, welch@hpe.com, rakhahari.bhunia@keysight.com, kingshuk.mandal@keysight.com, linux-rdma@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com Subject: [RFC PATCH 10/13] drivers: ultraeth: add sack support Date: Fri, 7 Mar 2025 01:02:00 +0200 Message-ID: <20250306230203.1550314-11-nikolay@enfabrica.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250306230203.1550314-1-nikolay@enfabrica.net> References: <20250306230203.1550314-1-nikolay@enfabrica.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Add SACK support, we choose to send SACK (and extended header) when we have to send an ACK but cannot advance CACK. The logic is a bit complicated because the spec says we have to align CACK and SACK_BASE to 8 which could effectively move CACK back so we have to fill in for those bits as 1s in the SACK bitmap Signed-off-by: Nikolay Aleksandrov Signed-off-by: Alex Badea --- drivers/ultraeth/uet_pdc.c | 100 ++++++++++++++++++++++++++++++--- drivers/ultraeth/uet_pds.c | 3 + include/net/ultraeth/uet_pdc.h | 10 ++++ include/uapi/linux/ultraeth.h | 40 +++++++++++++ 4 files changed, 146 insertions(+), 7 deletions(-) diff --git a/drivers/ultraeth/uet_pdc.c b/drivers/ultraeth/uet_pdc.c index 55b893ac5479..e9469edd9014 100644 --- a/drivers/ultraeth/uet_pdc.c +++ b/drivers/ultraeth/uet_pdc.c @@ -401,13 +401,55 @@ static int uet_pdc_build_req(struct uet_pdc *pdc, return 0; } +static void pdc_build_sack(struct uet_pdc *pdc, + struct uet_pds_ack_ext_hdr *ack_ext) +{ + u32 sack_base = pdc->lowest_unack_psn, shift; + unsigned long bit, start_bit; + s16 sack_psn_offset; + u64 sack_bitmap; + + if (sack_base + UET_PDC_SACK_BITS > pdc->max_rcv_psn) + sack_base = max(pdc->max_rcv_psn - UET_PDC_SACK_BITS, + pdc->rx_base_psn); + sack_base &= UET_PDC_SACK_MASK; + sack_psn_offset = (s16)(sack_base - + (pdc->rx_base_psn & UET_PDC_SACK_MASK)); + if (sack_base == pdc->rx_base_psn) { + shift = 1; + sack_bitmap = 1; + bit = 0; + } else if (sack_base < pdc->rx_base_psn) { + shift = pdc->rx_base_psn - sack_base; + sack_bitmap = U64_MAX >> (64 - shift); + bit = 0; + } else { + shift = 0; + sack_bitmap = 0; + bit = sack_base - pdc->rx_base_psn; + } + + start_bit = bit; + for_each_set_bit_from(bit, pdc->rx_bitmap, UET_PDC_MPR) { + shift += (bit - start_bit); + if (shift >= UET_PDC_SACK_BITS) + break; + sack_bitmap |= BIT(shift); + } + + pdc->lowest_unack_psn += UET_PDC_SACK_BITS; + ack_ext->sack_psn_offset = cpu_to_be16(sack_psn_offset); + ack_ext->sack_bitmap = cpu_to_be64(sack_bitmap); +} + static void pdc_build_ack(struct uet_pdc *pdc, struct sk_buff *skb, u32 psn, u8 ack_flags, bool exact_psn) { + u8 type = pdc_should_sack(pdc) ? UET_PDS_TYPE_ACK_CC : UET_PDS_TYPE_ACK; struct uet_pds_ack_hdr *ack = skb_put(skb, sizeof(*ack)); - uet_pdc_build_prologue(&ack->prologue, UET_PDS_TYPE_ACK, - UET_PDS_NEXT_HDR_RSP, ack_flags); + uet_pdc_build_prologue(&ack->prologue, type, UET_PDS_NEXT_HDR_RSP, + ack_flags); if (exact_psn) { ack->ack_psn_offset = 0; ack->cack_psn = cpu_to_be32(psn); @@ -417,6 +459,13 @@ static void pdc_build_ack(struct uet_pdc *pdc, struct sk_buff *skb, u32 psn, } ack->spdcid = cpu_to_be16(pdc->spdcid); ack->dpdcid = cpu_to_be16(pdc->dpdcid); + + if (pdc_should_sack(pdc)) { + struct uet_pds_ack_ext_hdr *ack_ext = skb_put(skb, + sizeof(*ack_ext)); + + pdc_build_sack(pdc, ack_ext); + } } static void uet_pdc_build_ses_ack(struct uet_pdc *pdc, struct sk_buff *skb, @@ -439,10 +488,12 @@ static void uet_pdc_build_ses_ack(struct uet_pdc *pdc, struct sk_buff *skb, static int uet_pdc_send_ses_ack(struct uet_pdc *pdc, __u8 ses_rc, __be16 msg_id, u32 psn, u8 ack_flags, bool exact_psn) { + unsigned int skb_size = sizeof(struct uet_ses_rsp_hdr) + + sizeof(struct uet_pds_ack_hdr); struct sk_buff *skb; - skb = alloc_skb(sizeof(struct uet_ses_rsp_hdr) + - sizeof(struct uet_pds_ack_hdr), GFP_ATOMIC); + skb_size += pdc_should_sack(pdc) ? sizeof(struct uet_pds_ack_ext_hdr) : 0; + skb = alloc_skb(skb_size, GFP_ATOMIC); if (!skb) return -ENOBUFS; @@ -514,6 +565,30 @@ int uet_pdc_tx_req(struct uet_pdc *pdc, struct sk_buff *skb, u8 type) return ret; } +static void uet_pdc_rx_sack(struct uet_pdc *pdc, struct sk_buff *skb, + u32 cack_psn, struct uet_pds_ack_ext_hdr *ext_ack, + bool ecn_marked) +{ + unsigned long bit, *sack_bitmap = (unsigned long *)&ext_ack->sack_bitmap; + u32 sack_base_psn = cack_psn + + (s16)be16_to_cpu(ext_ack->sack_psn_offset); + + while ((bit = find_next_bit(sack_bitmap, 64, 0)) != 64) { + /* skip bits that were already acked */ + if (sack_base_psn + bit <= pdc->tx_base_psn) { + if (sack_base_psn + bit == pdc->tx_base_psn) + __uet_pdc_mpr_advance_tx(pdc, 1); + continue; + } + if (!psn_bit_valid((sack_base_psn + bit) - pdc->tx_base_psn)) + break; + if (test_and_set_bit((sack_base_psn + bit) - pdc->tx_base_psn, + pdc->ack_bitmap)) + continue; + uet_pdc_ack_psn(pdc, skb, sack_base_psn + bit, ecn_marked); + } +} + int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, __be32 remote_fep_addr) { @@ -521,10 +596,11 @@ int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, struct uet_pds_ack_hdr *ack = pds_ack_hdr(skb); s16 ack_psn_offset = be16_to_cpu(ack->ack_psn_offset); const char *drop_reason = "ack_psn not in MPR window"; + struct uet_pds_ack_ext_hdr *ext_ack = NULL; u32 cack_psn = be32_to_cpu(ack->cack_psn); u32 ack_psn = cack_psn + ack_psn_offset; + bool is_sack = false, ecn_marked; int ret = -EINVAL; - bool ecn_marked; u32 psn_bit; spin_lock(&pdc->lock); @@ -545,9 +621,16 @@ int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, drop_reason = "ack_psn bit is invalid"; goto err_dbg; } + if (uet_prologue_type(&ack->prologue) == UET_PDS_TYPE_ACK_CC) { + ext_ack = pds_ack_ext_hdr(skb); + is_sack = !!ext_ack->sack_bitmap; + } if (test_and_set_bit(psn_bit, pdc->ack_bitmap)) { - drop_reason = "ack_psn bit already set in ack_bitmap"; - goto err_dbg; + /* SACK packets can include already acked packets */ + if (!is_sack) { + drop_reason = "ack_psn bit already set in ack_bitmap"; + goto err_dbg; + } } /* either using ROD mode or in SYN_SENT state */ @@ -573,6 +656,9 @@ int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, if (cack_psn != ack_psn) uet_pdc_ack_psn(pdc, skb, ack_psn, ecn_marked); + if (is_sack) + uet_pdc_rx_sack(pdc, skb, cack_psn, ext_ack, ecn_marked); + ret = 0; switch (pdc->state) { case UET_PDC_EP_STATE_SYN_SENT: diff --git a/drivers/ultraeth/uet_pds.c b/drivers/ultraeth/uet_pds.c index 52122998079d..436b63189800 100644 --- a/drivers/ultraeth/uet_pds.c +++ b/drivers/ultraeth/uet_pds.c @@ -266,6 +266,9 @@ int uet_pds_rx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, prologue = pds_prologue_hdr(skb); switch (uet_prologue_type(prologue)) { + case UET_PDS_TYPE_ACK_CC: + offset += sizeof(struct uet_pds_ack_ext_hdr); + fallthrough; case UET_PDS_TYPE_ACK: if (!uet_pds_rx_valid_ack_next_hdr(prologue)) break; diff --git a/include/net/ultraeth/uet_pdc.h b/include/net/ultraeth/uet_pdc.h index 8a87fc0bc869..d6710f92fb16 100644 --- a/include/net/ultraeth/uet_pdc.h +++ b/include/net/ultraeth/uet_pdc.h @@ -20,6 +20,8 @@ NSEC_PER_SEC) #define UET_PDC_RTX_DEFAULT_MAX 3 #define UET_PDC_MPR 128 +#define UET_PDC_SACK_BITS 64 +#define UET_PDC_SACK_MASK (U64_MAX << 3) #define UET_SKB_CB(skb) ((struct uet_skb_cb *)&((skb)->cb[0])) @@ -93,6 +95,8 @@ struct uet_pdc { u32 rx_base_psn; u32 tx_base_psn; + u32 lowest_unack_psn; + u32 max_rcv_psn; u32 ack_gen_trigger; u32 ack_gen_min_pkt_add; @@ -146,4 +150,10 @@ static inline bool before(u32 seq1, u32 seq2) { return (s32)(seq1-seq2) < 0; } + +static inline bool pdc_should_sack(const struct uet_pdc *pdc) +{ + return pdc->lowest_unack_psn > pdc->rx_base_psn && + pdc->lowest_unack_psn < pdc->max_rcv_psn; +} #endif /* _UECON_PDC_H */ diff --git a/include/uapi/linux/ultraeth.h b/include/uapi/linux/ultraeth.h index cc39bf970e08..3b8e95d7ed7b 100644 --- a/include/uapi/linux/ultraeth.h +++ b/include/uapi/linux/ultraeth.h @@ -152,6 +152,46 @@ struct uet_pds_ack_hdr { __be16 dpdcid; } __attribute__ ((__packed__)); +/* ext ack CC flags */ +enum { + UET_PDS_ACK_EXT_CC_F_RSVD = (1 << 0) +}; + +/* field: cc_type_mpr_sack_off */ +#define UET_PDS_ACK_EXT_MPR_BITS 8 +#define UET_PDS_ACK_EXT_MPR_MASK 0xff +#define UET_PDS_ACK_EXT_CC_FLAGS_BITS 4 +#define UET_PDS_ACK_EXT_CC_FLAGS_MASK 0xf +#define UET_PDS_ACK_EXT_CC_FLAGS_SHIFT UET_PDS_ACK_EXT_MPR_BITS +#define UET_PDS_ACK_EXT_CC_TYPE_BITS 4 +#define UET_PDS_ACK_EXT_CC_TYPE_MASK 0xf +#define UET_PDS_ACK_EXT_CC_TYPE_SHIFT (UET_PDS_ACK_EXT_CC_FLAGS_SHIFT + \ + UET_PDS_ACK_EXT_CC_FLAGS_BITS) +/* header used for ACK_CC */ +struct uet_pds_ack_ext_hdr { + __be16 cc_type_flags_mpr; + __be16 sack_psn_offset; + __be64 sack_bitmap; + __be64 ack_cc_state; +} __attribute__ ((__packed__)); + +static inline __u8 uet_pds_ack_ext_mpr(const struct uet_pds_ack_ext_hdr *ack) +{ + return __be16_to_cpu(ack->cc_type_flags_mpr) & UET_PDS_ACK_EXT_MPR_MASK; +} + +static inline __u8 uet_pds_ack_ext_cc_flags(const struct uet_pds_ack_ext_hdr *ack) +{ + return (__be16_to_cpu(ack->cc_type_flags_mpr) >> UET_PDS_ACK_EXT_CC_FLAGS_SHIFT) & + UET_PDS_ACK_EXT_CC_FLAGS_MASK; +} + +static inline __u8 uet_pds_ack_ext_cc_type(const struct uet_pds_ack_ext_hdr *ack) +{ + return (__be16_to_cpu(ack->cc_type_flags_mpr) >> UET_PDS_ACK_EXT_CC_TYPE_SHIFT) & + UET_PDS_ACK_EXT_CC_TYPE_MASK; +} + /* ses request op codes */ enum { UET_SES_REQ_OP_NOOP = 0x00, From patchwork Thu Mar 6 23:02:01 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 14005481 X-Patchwork-Delegate: kuba@kernel.org Received: from mail-qv1-f50.google.com (mail-qv1-f50.google.com [209.85.219.50]) (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 13E97280A3F for ; Thu, 6 Mar 2025 23:04:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302263; cv=none; b=RiFzirPxHukvyuMpxeM2y/yWEkCJiycj4PC0YSRVl2WMV6u9HJVn9gYbLz7vZ3PVW/UuBN4eo3SG4FQdGQixu8DPCmCQUqzlS4PVInRaBe/Tw01boqylCB3zAegp/CmsBMntbdKc17LeFI7Yg6uAXS7dfQR8C75LhR7TDmSrYkM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302263; c=relaxed/simple; bh=yndAeAn2xqhE/kdxFO1U65LUqw0DkYwAykXl65heU9E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rhQcFjaeJLTxlBuz23KEHSyz+pPOZIdJJPUGOA1F0x+Z3NXbyQxHyThsxC/RHrECFrBPSwp3k6b4rE/D1cgxTC87a3sGxjpOgqcMU2vofJHJA+EaI7jo/uJRraDY9S1O2wKPW+OSfCkwiUFVTjUd+IZ1xMmZn2QXIs+gn+zoaBY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net; spf=pass smtp.mailfrom=enfabrica.net; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b=dTEI3D0Z; arc=none smtp.client-ip=209.85.219.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b="dTEI3D0Z" Received: by mail-qv1-f50.google.com with SMTP id 6a1803df08f44-6e8fc176825so6465156d6.0 for ; Thu, 06 Mar 2025 15:04:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enfabrica.net; s=google; t=1741302258; x=1741907058; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=w3PHcgpSmIYXkI7a7aJYg2x9bZpSnT5ilYLACdMs2bU=; b=dTEI3D0ZV7+PXNzoEaAJhfFWH81t3Q2/I0lPtjxyzxq0k87Dp4z+7Zcj2cyJyojpho mH98t2gYQ9o+BIZAwYZGQRX74AMmXhP6+HYHx6otc6u4UQ+NDsFgSa61gds/9/EjH0po vUzD+LzLCFKaUGdda53OoyvC/ssVIV7nW9WpAzMZLSE+K581Zb09Tazag7+xhKqqWkjk pE0yo/iDw0iynfSnwlU37q7kPC+GT3cQxtJTWodb/FAhgWBNY3C4uVINyMLOq3Y/9KTw 5T1jihl058Sem/dPBdAlLSa9UnxMuZTgRhP4AMn2JkoYMt9B163uLrTBdxQaX9pNiEE7 zxWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302258; x=1741907058; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=w3PHcgpSmIYXkI7a7aJYg2x9bZpSnT5ilYLACdMs2bU=; b=s48GfE2L9j8qXmPZR0H/znEdR17yzV91ldj3HlIXR8kAbReLQYg71mk8DfNniX2Fwt JZ9DRW+ST3orezUt3Te1Hx5S/Or0PFJVjNZ7w2mM64KLRZpzR0UwL//27fu3/b12EPtC gjaQekR574fvklElNz90XEGmjDGZfodrNEd6ocz/RBkQstrIA90rZfcE+x9/d84GLY7v 9soJa+ZGkfL6J9aT8RM5ifbK9W/5yvywPL1cqvhChBbYNl+uJ648thuztuWGT7muIUp9 az9mTknkOqaxISATP1Q0LgTmz5EPoZwpV7Ae0XglN2zBw8x0HKBP5N5tsBgAIUEw8qDz aAfw== X-Gm-Message-State: AOJu0Yxnc9CQIH5r4se2yTeMhdGttRgV2srmZ11+Qq+W8QB0sgcSg8mQ eLoNb/CyJRQEQFjP9pkeDf4b95WU46NnJV1OrYJZy5gZYbIroAbjvJgiy7tsy3Unl9lTXZPir4Q Ghfhz91CLo+0sbOIto6JanXWSdJAGa4XlEmrbnG19rZ351XtRuE5rEJMaPaeaQQ8qXNxv3v3sNf 0TMiSu21G1bafd61iesGW/6NmpmnFqCYDqPaqsA4weTHU= X-Gm-Gg: ASbGncu6adCjRNHQLGERPtdKTL0pQVBSkVADe/zgNwjW1nDAyonLN5gfRXHkvUf2xkI FrpVOuNP7JCV9GY7+PbW0maTyivFtrtUmraiFKVLHaSw1vIzUETXfp10oLW9SHsJvP1X0zqnCie X4FHu3co5qCR9HWofl+xM8E6dszR7W/Ri5Pg6Cltl0/v2/4ooOu3MwMYPf3Cvk3bNP6TZl/55Gt XbuYzkyL1ZDwZkQQ1ExtjUGPUP0gk/3BbRKuxc/RL8nYHPxyZ6CPE8URrGWpeEwfhnsQQFz6sec nIRubU94BWe3NDdKb06nCTGypsVmGOa+TPf8yg9wH+IhlfqA+J7VyMC8we0dn3YuV6O+ X-Google-Smtp-Source: AGHT+IEP6gNfr2d6Yjp8CS+OJ5EZK0Vk3IFPkEP7ZiqxgMfDyCp/7Wk5kV7i1EgxyX2bXgdbhi2zEQ== X-Received: by 2002:a05:6214:2428:b0:6e8:f166:b19c with SMTP id 6a1803df08f44-6e900695416mr14903086d6.41.1741302258461; Thu, 06 Mar 2025 15:04:18 -0800 (PST) Received: from debil.. (78-154-15-142.ip.btc-net.bg. [78.154.15.142]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac256654fa6sm14971966b.93.2025.03.06.15.04.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Mar 2025 15:04:17 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: shrijeet@enfabrica.net, alex.badea@keysight.com, eric.davis@broadcom.com, rip.sohan@amd.com, dsahern@kernel.org, bmt@zurich.ibm.com, roland@enfabrica.net, nikolay@enfabrica.net, winston.liu@keysight.com, dan.mihailescu@keysight.com, kheib@redhat.com, parth.v.parikh@keysight.com, davem@redhat.com, ian.ziemba@hpe.com, andrew.tauferner@cornelisnetworks.com, welch@hpe.com, rakhahari.bhunia@keysight.com, kingshuk.mandal@keysight.com, linux-rdma@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com Subject: [RFC PATCH 11/13] drivers: ultraeth: add nack support Date: Fri, 7 Mar 2025 01:02:01 +0200 Message-ID: <20250306230203.1550314-12-nikolay@enfabrica.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250306230203.1550314-1-nikolay@enfabrica.net> References: <20250306230203.1550314-1-nikolay@enfabrica.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Add nack header format with codes and helpers which allow sending of NACKs, they construct the NACK packet dynamically and don't rely on a pre-existing PDC. Send back NACK packets if an error occurred when receiving a request. The following events trigger NACKs: - DPDCID not found and SYN not set (UET_PDS_NACK_INV_DPDCID) - DPDCID not found and job/fep are invalid (UET_PDS_NACK_NO_RESOURCE) - DPDCID not found and local FEP address mismatches (UET_PDS_NACK_PDC_HDR_MISMATCH) - DPDCID is found but mode doesn't match (UET_PDS_NACK_PDC_MODE_MISMATCH) - DPDCID is found but PSN is wrong (UET_PDS_NACK_PSN_OOR_WINDOW or UET_PDS_NACK_INVALID_SYN if packet is with SYN) Process received PDC_FATAL NACKs, the rest are silently ignored. Signed-off-by: Nikolay Aleksandrov Signed-off-by: Alex Badea --- drivers/ultraeth/uet_pdc.c | 79 ++++++++++++++++++++++++++-- drivers/ultraeth/uet_pds.c | 95 ++++++++++++++++++++++++++++++++-- include/net/ultraeth/uet_pdc.h | 3 ++ include/net/ultraeth/uet_pds.h | 10 ++++ include/uapi/linux/ultraeth.h | 55 ++++++++++++++++++++ 5 files changed, 235 insertions(+), 7 deletions(-) diff --git a/drivers/ultraeth/uet_pdc.c b/drivers/ultraeth/uet_pdc.c index e9469edd9014..4f19bc68b570 100644 --- a/drivers/ultraeth/uet_pdc.c +++ b/drivers/ultraeth/uet_pdc.c @@ -6,6 +6,21 @@ #include #include +struct metadata_dst *uet_pdc_dst(const struct uet_pdc_key *key, __be16 dport, + u8 tos) +{ + IP_TUNNEL_DECLARE_FLAGS(md_flags) = { }; + struct metadata_dst *mdst; + + mdst = __ip_tun_set_dst(key->src_ip, key->dst_ip, tos, 0, dport, + md_flags, 0, 0); + if (!mdst) + return NULL; + mdst->u.tun_info.mode |= IP_TUNNEL_INFO_TX; + + return mdst; +} + static void uet_pdc_xmit(struct uet_pdc *pdc, struct sk_buff *skb) { skb->dev = pds_netdev(pdc->pds); @@ -241,7 +256,6 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, const struct uet_pdc_key *key, bool is_inbound) { struct uet_pdc *pdc, *pdc_ins = ERR_PTR(-ENOMEM); - IP_TUNNEL_DECLARE_FLAGS(md_flags) = { }; int ret __maybe_unused; switch (mode) { @@ -287,8 +301,7 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, if (!pdc->ack_bitmap) goto err_ack_bitmap; timer_setup(&pdc->rtx_timer, uet_pdc_rtx_timer_expired, 0); - pdc->metadata = __ip_tun_set_dst(key->src_ip, key->dst_ip, tos, 0, dport, - md_flags, 0, 0); + pdc->metadata = uet_pdc_dst(key, dport, tos); if (!pdc->metadata) goto err_tun_dst; @@ -731,6 +744,19 @@ static void uet_pdc_rx_req_handle_ack(struct uet_pdc *pdc, unsigned int len, } } +static bool uet_pdc_req_validate_mode(const struct uet_pdc *pdc, + const struct uet_pds_req_hdr *req) +{ + switch (uet_prologue_type(&req->prologue)) { + case UET_PDS_TYPE_RUD_REQ: + return pdc->mode == UET_PDC_MODE_RUD; + case UET_PDS_TYPE_ROD_REQ: + return pdc->mode == UET_PDC_MODE_ROD; + } + + return false; +} + int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, __be32 remote_fep_addr, __u8 tos) { @@ -743,6 +769,7 @@ int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, unsigned int len = skb->len; bool first_ack = false; enum mpr_pos psn_pos; + __u8 nack_code = 0; int ret = -EINVAL; spin_lock(&pdc->lock); @@ -761,6 +788,11 @@ int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, if (unlikely(pdc->tx_busy)) goto err_dbg; + if (!uet_pdc_req_validate_mode(pdc, req)) { + drop_reason = "pdc mode doesn't match request"; + nack_code = UET_PDS_NACK_PDC_MODE_MISMATCH; + goto err_dbg; + } if (req_flags & UET_PDS_REQ_FLAG_RETX) ack_flags |= UET_PDS_ACK_FLAG_RETX; @@ -770,10 +802,15 @@ int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, switch (psn_pos) { case UET_PDC_MPR_FUTURE: drop_reason = "req psn is in a future MPR window"; + if (req_flags & UET_PDS_REQ_FLAG_SYN) + nack_code = UET_PDS_NACK_INVALID_SYN; + else + nack_code = UET_PDS_NACK_PSN_OOR_WINDOW; goto err_dbg; case UET_PDC_MPR_PREV: if ((int)(req_psn - pdc->rx_base_psn) < S16_MIN) { drop_reason = "req psn is too far in the past"; + nack_code = UET_PDS_NACK_PSN_OOR_WINDOW; goto err_dbg; } uet_pdc_send_ses_ack(pdc, UET_SES_RSP_RC_NULL, ses_req->msg_id, @@ -805,6 +842,7 @@ int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, if (!psn_bit_valid(psn_bit)) { drop_reason = "req psn bit is invalid"; + nack_code = UET_PDS_NACK_PSN_OOR_WINDOW; goto err_dbg; } if (test_and_set_bit(psn_bit, pdc->rx_bitmap)) { @@ -844,5 +882,40 @@ int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, pdc->state, pdc->dpdcid, pdc->spdcid, be16_to_cpu(ses_req->msg_id), be32_to_cpu(req->psn), be16_to_cpu(req->spdcid), be16_to_cpu(req->dpdcid)); + + if (nack_code) + uet_pds_send_nack(pdc->pds, &pdc->key, + pdc->metadata->u.tun_info.key.tp_dst, 0, + cpu_to_be16(pdc->spdcid), + cpu_to_be16(pdc->dpdcid), + nack_code, req->psn, + pds_req_to_nack_flags(req_flags)); goto out; } + +void uet_pdc_rx_nack(struct uet_pdc *pdc, struct sk_buff *skb) +{ + struct uet_pds_nack_hdr *nack = pds_nack_hdr(skb); + u32 nack_psn = be32_to_cpu(nack->nack_psn_pkt_id); + + spin_lock(&pdc->lock); + netdev_dbg(pds_netdev(pdc->pds), "%s: NACK pdc: [ spdcid: %u dpdcid: %u rx_base_psn %u ] " + "nack header: [ nack_code: %u vendor_code: %u nack_psn: %u ]\n", + __func__, pdc->spdcid, pdc->dpdcid, pdc->rx_base_psn, + nack->nack_code, nack->vendor_code, nack_psn); + if (psn_mpr_pos(pdc->rx_base_psn, nack_psn) != UET_PDC_MPR_CUR) + goto out; + switch (nack->nack_code) { + /* PDC_FATAL codes */ + case UET_PDS_NACK_CLOSING_IN_ERR: + case UET_PDS_NACK_INV_DPDCID: + case UET_PDS_NACK_NO_RESOURCE: + case UET_PDS_NACK_PDC_HDR_MISMATCH: + case UET_PDS_NACK_INVALID_SYN: + case UET_PDS_NACK_PDC_MODE_MISMATCH: + uet_pdc_destroy(pdc); + break; + } +out: + spin_unlock(&pdc->lock); +} diff --git a/drivers/ultraeth/uet_pds.c b/drivers/ultraeth/uet_pds.c index 436b63189800..c144b6df8327 100644 --- a/drivers/ultraeth/uet_pds.c +++ b/drivers/ultraeth/uet_pds.c @@ -149,6 +149,46 @@ void uet_pds_clean_job(struct uet_pds *pds, u32 job_id) rhashtable_walk_exit(&iter); } +static void uet_pds_build_nack(struct sk_buff *skb, __be16 spdcid, __be16 dpdcid, + u8 nack_code, __be32 nack_psn, u8 flags) +{ + struct uet_pds_nack_hdr *nack = skb_put(skb, sizeof(*nack)); + + uet_pdc_build_prologue(&nack->prologue, UET_PDS_TYPE_NACK, + UET_PDS_NEXT_HDR_NONE, flags); + nack->nack_code = nack_code; + nack->vendor_code = 0; + nack->nack_psn_pkt_id = nack_psn; + nack->spdcid = spdcid; + nack->dpdcid = dpdcid; + nack->payload = 0; +} + +void uet_pds_send_nack(struct uet_pds *pds, const struct uet_pdc_key *key, + __be16 dport, u8 tos, __be16 spdcid, __be16 dpdcid, + __u8 nack_code, __be32 nack_psn, __u8 flags) +{ + struct metadata_dst *mdst; + struct sk_buff *skb; + + if (WARN_ON_ONCE(!key)) + return; + + skb = alloc_skb(sizeof(struct uet_pds_nack_hdr), GFP_ATOMIC); + if (!skb) + return; + + skb->dev = pds_netdev(pds); + uet_pds_build_nack(skb, spdcid, dpdcid, nack_code, nack_psn, flags); + mdst = uet_pdc_dst(key, dport, tos); + if (!mdst) { + kfree_skb(skb); + return; + } + skb_dst_set(skb, &mdst->dst); + dev_queue_xmit(skb); +} + static int uet_pds_rx_ack(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, __be32 remote_fep_addr) { @@ -164,6 +204,20 @@ static int uet_pds_rx_ack(struct uet_pds *pds, struct sk_buff *skb, return uet_pdc_rx_ack(pdc, skb, remote_fep_addr); } +static void uet_pds_rx_nack(struct uet_pds *pds, struct sk_buff *skb) +{ + struct uet_pds_nack_hdr *nack = pds_nack_hdr(skb); + u16 pdcid = be16_to_cpu(nack->dpdcid); + struct uet_pdc *pdc; + + pdc = rhashtable_lookup_fast(&pds->pdcid_hash, &pdcid, + uet_pds_pdcid_rht_params); + if (!pdc) + return; + + uet_pdc_rx_nack(pdc, skb); +} + static struct uet_pdc *uet_pds_new_pdc_rx(struct uet_pds *pds, struct sk_buff *skb, __be16 dport, u32 ack_gen_trigger, @@ -201,21 +255,45 @@ static int uet_pds_rx_req(struct uet_pds *pds, struct sk_buff *skb, /* new flow */ if (unlikely(!pdc)) { struct uet_prologue_hdr *prologue = pds_prologue_hdr(skb); + __u8 req_flags = uet_prologue_flags(prologue); struct uet_context *ctx; struct uet_job *job; - if (!(uet_prologue_flags(prologue) & UET_PDS_REQ_FLAG_SYN)) + if (!(uet_prologue_flags(prologue) & UET_PDS_REQ_FLAG_SYN)) { + uet_pds_send_nack(pds, &key, dport, 0, 0, + pds_req->spdcid, + UET_PDS_NACK_INV_DPDCID, pds_req->psn, + pds_req_to_nack_flags(req_flags)); return -EINVAL; + } ctx = container_of(pds, struct uet_context, pds); job = uet_job_find(&ctx->job_reg, key.job_id); - if (!job) + if (!job) { + uet_pds_send_nack(pds, &key, dport, 0, 0, + pds_req->spdcid, + UET_PDS_NACK_NO_RESOURCE, + pds_req->psn, + pds_req_to_nack_flags(req_flags)); return -ENOENT; + } fep = rcu_dereference(job->fep); - if (!fep) + if (!fep) { + uet_pds_send_nack(pds, &key, dport, 0, 0, + pds_req->spdcid, + UET_PDS_NACK_NO_RESOURCE, + pds_req->psn, + pds_req_to_nack_flags(req_flags)); return -ECONNREFUSED; - if (fep->addr.in_address.ip != local_fep_addr) + } + if (fep->addr.in_address.ip != local_fep_addr) { + uet_pds_send_nack(pds, &key, dport, 0, 0, + pds_req->spdcid, + UET_PDS_NACK_PDC_HDR_MISMATCH, + pds_req->psn, + pds_req_to_nack_flags(req_flags)); return -ENOENT; + } pdc = uet_pds_new_pdc_rx(pds, skb, dport, fep->ack_gen_trigger, fep->ack_gen_min_pkt_add, &key, @@ -290,6 +368,15 @@ int uet_pds_rx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, ret = uet_pds_rx_req(pds, skb, local_fep_addr, remote_fep_addr, dport, tos); break; + case UET_PDS_TYPE_NACK: + if (uet_prologue_next_hdr(prologue) != UET_PDS_NEXT_HDR_NONE) + break; + offset += sizeof(struct uet_pds_nack_hdr); + if (!pskb_may_pull(skb, offset)) + break; + ret = 0; + uet_pds_rx_nack(pds, skb); + break; default: break; } diff --git a/include/net/ultraeth/uet_pdc.h b/include/net/ultraeth/uet_pdc.h index d6710f92fb16..60aecc15d0f1 100644 --- a/include/net/ultraeth/uet_pdc.h +++ b/include/net/ultraeth/uet_pdc.h @@ -120,6 +120,9 @@ int uet_pdc_rx_req(struct uet_pdc *pdc, struct sk_buff *skb, int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, __be32 remote_fep_addr); int uet_pdc_tx_req(struct uet_pdc *pdc, struct sk_buff *skb, u8 type); +void uet_pdc_rx_nack(struct uet_pdc *pdc, struct sk_buff *skb); +struct metadata_dst *uet_pdc_dst(const struct uet_pdc_key *key, __be16 dport, + u8 tos); static inline void uet_pdc_build_prologue(struct uet_prologue_hdr *prologue, u8 type, u8 next, u8 flags) diff --git a/include/net/ultraeth/uet_pds.h b/include/net/ultraeth/uet_pds.h index 78624370f18c..4e9794a4d3de 100644 --- a/include/net/ultraeth/uet_pds.h +++ b/include/net/ultraeth/uet_pds.h @@ -7,6 +7,7 @@ #include #include #include +#include /** * struct uet_pds - Packet Delivery Sublayer state structure @@ -43,6 +44,10 @@ int uet_pds_rx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, int uet_pds_tx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, __be32 remote_fep_addr, __be16 dport, u32 job_id); +void uet_pds_send_nack(struct uet_pds *pds, const struct uet_pdc_key *key, + __be16 dport, u8 tos, __be16 spdcid, __be16 dpdcid, + __u8 nack_code, __be32 nack_psn, __u8 flags); + static inline struct uet_prologue_hdr *pds_prologue_hdr(const struct sk_buff *skb) { return (struct uet_prologue_hdr *)skb_network_header(skb); @@ -92,4 +97,9 @@ static inline __be16 pds_ses_rsp_hdr_pack(__u8 opcode, __u8 version, __u8 list, (ses_rc & UET_SES_RSP_RC_MASK) << UET_SES_RSP_RC_SHIFT); } + +static inline __u8 pds_req_to_nack_flags(__u8 req_flags) +{ + return req_flags & UET_PDS_REQ_FLAG_RETX ? UET_PDS_NACK_FLAG_RETX : 0; +} #endif /* _UECON_PDS_H */ diff --git a/include/uapi/linux/ultraeth.h b/include/uapi/linux/ultraeth.h index 3b8e95d7ed7b..53d2124bc285 100644 --- a/include/uapi/linux/ultraeth.h +++ b/include/uapi/linux/ultraeth.h @@ -192,6 +192,61 @@ static inline __u8 uet_pds_ack_ext_cc_type(const struct uet_pds_ack_ext_hdr *ack UET_PDS_ACK_EXT_CC_TYPE_MASK; } +/* NACK codes */ +enum { + UET_PDS_NACK_TRIMMED = 0x01, + UET_PDS_NACK_TRIMMED_LASTHOP = 0x02, + UET_PDS_NACK_TRIMMED_ACK = 0x03, + UET_PDS_NACK_NO_PDC_AVAIL = 0x04, + UET_PDS_NACK_NO_CCC_AVAIL = 0x05, + UET_PDS_NACK_NO_BITMAP = 0x06, + UET_PDS_NACK_NO_PKT_BUFFER = 0x07, + UET_PDS_NACK_NO_GTD_DEL_AVAIL = 0x08, + UET_PDS_NACK_NO_SES_MSG_AVAIL = 0x09, + UET_PDS_NACK_NO_RESOURCE = 0x0A, + UET_PDS_NACK_PSN_OOR_WINDOW = 0x0B, + UET_PDS_NACK_FIRST_ROD_OOO = 0x0C, + UET_PDS_NACK_ROD_OOO = 0x0D, + UET_PDS_NACK_INV_DPDCID = 0x0E, + UET_PDS_NACK_PDC_HDR_MISMATCH = 0x0F, + UET_PDS_NACK_CLOSING = 0x10, + UET_PDS_NACK_CLOSING_IN_ERR = 0x11, + UET_PDS_NACK_PKT_NOT_RCVD = 0x12, + UET_PDS_NACK_GTD_RESP_UNAVAIL = 0x13, + UET_PDS_NACK_ACK_WITH_DATA = 0x14, + UET_PDS_NACK_INVALID_SYN = 0x15, + UET_PDS_NACK_PDC_MODE_MISMATCH = 0x16, + UET_PDS_NACK_NEW_START_PSN = 0x17, + UET_PDS_NACK_RCVD_SES_PROCG = 0x18, + UET_PDS_NACK_UNEXP_EVENT = 0x19, + UET_PDS_NACK_RCVR_INFER_LOSS = 0x1A, + /* 0x1B - 0xFC reserved for UET */ + UET_PDS_NACK_EXP_NACK_NORMAL = 0xFD, + UET_PDS_NACK_T_EXP_NACK_ERR = 0xFE, + UET_PDS_NACK_EXP_NACK_FATAL = 0xFF +}; + +/* NACK flags */ +enum { + UET_PDS_NACK_FLAG_RSV21 = (1 << 0), + UET_PDS_NACK_FLAG_RSV22 = (1 << 1), + UET_PDS_NACK_FLAG_RSV23 = (1 << 2), + UET_PDS_NACK_FLAG_NT = (1 << 3), + UET_PDS_NACK_FLAG_RETX = (1 << 4), + UET_PDS_NACK_FLAG_M = (1 << 5), + UET_PDS_NACK_FLAG_RSV = (1 << 6) +}; + +struct uet_pds_nack_hdr { + struct uet_prologue_hdr prologue; + __u8 nack_code; + __u8 vendor_code; + __be32 nack_psn_pkt_id; + __be16 spdcid; + __be16 dpdcid; + __be32 payload; +} __attribute__ ((__packed__)); + /* ses request op codes */ enum { UET_SES_REQ_OP_NOOP = 0x00, From patchwork Thu Mar 6 23:02:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 14005482 X-Patchwork-Delegate: kuba@kernel.org Received: from mail-qv1-f50.google.com (mail-qv1-f50.google.com [209.85.219.50]) (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 A76BC280A48 for ; Thu, 6 Mar 2025 23:04:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302263; cv=none; b=kidiZHb35As6wzRev5mVNdUoUaI+Neiu9InV9zoXg1F5kKbWkAh04sryasAOnTnaey61zpUDyZqgq+zgeThoKzxj3ageTizcxjwAvuvG8e8xPi515GcIZC6ZbLV3w6SxtDG3IQ8FGQcOzFa/8C9BXcN6YxA4xgL32IXyGPIBonw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302263; c=relaxed/simple; bh=U+FPMklqxEGNp2Jz2YOQHOK3M9eUniBywFkk8/Zi9sM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ev5v5VzyfzAdzZXONNh8V0vpDZYZhpNfZ+ClRjdAjCnIOUg7LXSQFVFhVZT9+zQ2xMX81aPssRAIg8+9/793Va1NCqQ7Scg6DPO+Brw7ydvf0GtBsRcIKRrXc/z9e+ogxvYkbAo+wgaFE/OK4KQPBSdLf5LmLeoZ4YOSoNc3Uj8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net; spf=pass smtp.mailfrom=enfabrica.net; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b=HoG9zcVx; arc=none smtp.client-ip=209.85.219.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b="HoG9zcVx" Received: by mail-qv1-f50.google.com with SMTP id 6a1803df08f44-6e900a7ce55so2927146d6.3 for ; Thu, 06 Mar 2025 15:04:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enfabrica.net; s=google; t=1741302260; x=1741907060; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=m+rCZYlWGR67Iaw52JnPGDdtrZf11iJpZMP2VpzGX40=; b=HoG9zcVx/xUWKFqEWJiw6UttF6ymwtx/u9A73dUhyXqSL0SZUfxqil5m+WpfXs7st5 lawykT2IcO2m7GR2nDttugihQdxR/EMjkXXrWJxYSRcZX9Rf9LOOUMWSBkWan6bQmamE rcIvOH06GngayNZuImiYgYnWDzHikZBDHoYiX8j8qdcR4FbBsUcyNFftErA9evocDR1K WxogIwkEch/Yj+Az3jlPp05CoO9JSB5kxaUsA78ECkyB++DByyBSUJymJJ8NklhWc+W8 qfL3svFEVWEX4eoWGYZelh5zzscTyY1h66/JypBiuMfkcmQj8NEOmcp9E9cnJWxu4i8Y S2iA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302260; x=1741907060; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=m+rCZYlWGR67Iaw52JnPGDdtrZf11iJpZMP2VpzGX40=; b=Goj6sPmVR1CXVUrgr01D9AGK19NlYvEhrkkz5Js9fE0VvacFkgi0kAIgH2HQNPOxWh fwZGppGz5zyjPIysP9O8K/jsXjQYKBmE8EdC5nzgtH177m7igV27Pr7wP78nreGAFg1b nEFyPBl1nPeyzVk83ncdQdFsVvkfakrJyttO1cae1GyGSl6KHyI5uMKdMNCDJSIRApM7 W9Yh44dAxnvb8EfFYyMYNeGyKZwIK1kve4qop6rf5j8uQ8Xbd0M9R4IZHt0XTFAymsKo y6vk8yPCOy5XAi4zIynwz5h9Yh4YiCpP/hDzSlIkTaxRsC8I/niiqhff0Q2NkrO82fkY KVyQ== X-Gm-Message-State: AOJu0Yxv/sB8uYkGvHLPTebLa6+htzOxFcO+ae1Iu+AdLU6SYHivDEqq Ai5G5k7bFoa+Vr+WLWuV6o7Q2r2+2MqHfeYlT/RVSRYtgxA4ipkWDxpo6AIXG4wHT7f3l0hrYbt qGrg1Bieu8cTRcagbnSzlkmMArrwMMs60TyQGrUqfMi77FKgo3nPRbhrOzo+EWeB7NuAlNyQKZH auQeql/U6f2i2SQKeg6osoztO0hyOhCIk4yY+u5oKs X-Gm-Gg: ASbGncsHsYHHzUXMi9wSKnIjZhVdmbNrhaeTNaKAjNRMVwG03VY6pTh1wI+qWYsuczu ZDuiNxF+1ts2HLn+DeD5XIip7JFBNmyFH3O0HrpiQR1sUboK9+BCIGtk5I8WhWS/vlAskMv3zG3 8wapLzn04F1Mddy9oz/K5z+cFT3jmQw3/KRCknPspJWfO0c4YRqsJuB5B/cJZK1Z2j24bXyY4Bc Asw5DvKiXQQ+tgZPZ9n/PZtDiNQQbisQt+kgWSYtAJCxlnRKmsG+MQhgSyo3tgR2fLvqDtDSYC8 ZcZRp+B3+wy8cJTw31i9BNLJcxgtx8F2ik/UV9T1KyHn1sIIb+muy8ECQTaC8kGixmQm X-Google-Smtp-Source: AGHT+IHYUL0eFaJJG6TuOC6v3Ofnweklcysj2NJ5wYSFYobjV1Zs2nYbzXnhIeDgP/IOJzICKGJlFA== X-Received: by 2002:a05:6214:ca6:b0:6e8:fa33:2965 with SMTP id 6a1803df08f44-6e90061fa6emr13558416d6.14.1741302260275; Thu, 06 Mar 2025 15:04:20 -0800 (PST) Received: from debil.. (78-154-15-142.ip.btc-net.bg. [78.154.15.142]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac256654fa6sm14971966b.93.2025.03.06.15.04.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Mar 2025 15:04:19 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: shrijeet@enfabrica.net, alex.badea@keysight.com, eric.davis@broadcom.com, rip.sohan@amd.com, dsahern@kernel.org, bmt@zurich.ibm.com, roland@enfabrica.net, nikolay@enfabrica.net, winston.liu@keysight.com, dan.mihailescu@keysight.com, kheib@redhat.com, parth.v.parikh@keysight.com, davem@redhat.com, ian.ziemba@hpe.com, andrew.tauferner@cornelisnetworks.com, welch@hpe.com, rakhahari.bhunia@keysight.com, kingshuk.mandal@keysight.com, linux-rdma@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com Subject: [RFC PATCH 12/13] drivers: ultraeth: add initiator and target idle timeout support Date: Fri, 7 Mar 2025 01:02:02 +0200 Message-ID: <20250306230203.1550314-13-nikolay@enfabrica.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250306230203.1550314-1-nikolay@enfabrica.net> References: <20250306230203.1550314-1-nikolay@enfabrica.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Add control packet header structure and a helper that builds a control packet and transmits it. Currently it supports only CLOSE types, use it to implement initiator and target timeout support by using the close state machine. Upon initiator timeout we move to either ACK_WAIT (if pending acks) or CLOSE_ACK_WAIT state, in the latter case we also send a control message with CLOSE type. Upon target timeout we issue a REQ_CLOSE control message and if it isn't answered in the timeout period we send a NACK CLOSING_IN_ERR and close the PDC. Signed-off-by: Nikolay Aleksandrov Signed-off-by: Alex Badea --- drivers/ultraeth/uet_pdc.c | 241 ++++++++++++++++++++++++++++++--- drivers/ultraeth/uet_pds.c | 40 +++++- include/net/ultraeth/uet_pdc.h | 12 +- include/net/ultraeth/uet_pds.h | 5 + include/uapi/linux/ultraeth.h | 19 +++ 5 files changed, 293 insertions(+), 24 deletions(-) diff --git a/drivers/ultraeth/uet_pdc.c b/drivers/ultraeth/uet_pdc.c index 4f19bc68b570..5967095867dc 100644 --- a/drivers/ultraeth/uet_pdc.c +++ b/drivers/ultraeth/uet_pdc.c @@ -21,6 +21,14 @@ struct metadata_dst *uet_pdc_dst(const struct uet_pdc_key *key, __be16 dport, return mdst; } +void uet_pdc_rx_refresh(struct uet_pdc *pdc) +{ + unsigned long rx_jiffies = jiffies; + + if (rx_jiffies != READ_ONCE(pdc->rx_last_jiffies)) + WRITE_ONCE(pdc->rx_last_jiffies, rx_jiffies); +} + static void uet_pdc_xmit(struct uet_pdc *pdc, struct sk_buff *skb) { skb->dev = pds_netdev(pdc->pds); @@ -97,10 +105,19 @@ static void uet_pdc_rtx_timer_expired(struct timer_list *t) continue; } if (UET_SKB_CB(skb)->rtx_attempts == UET_PDC_RTX_DEFAULT_MAX) { + struct uet_prologue_hdr *prologue; + /* XXX: close connection, count drops etc */ - netdev_dbg(pds_netdev(pdc->pds), "%s: psn: %u too many rtx attempts: %u\n", + prologue = (struct uet_prologue_hdr *)skb->data; + netdev_dbg(pds_netdev(pdc->pds), "%s: psn: %u type: %u too many rtx attempts: %u\n", __func__, UET_SKB_CB(skb)->psn, + uet_prologue_type(prologue), UET_SKB_CB(skb)->rtx_attempts); + if (uet_prologue_type(prologue) == UET_PDS_TYPE_CTRL_MSG && + uet_prologue_ctl_type(prologue) == UET_CTL_TYPE_CLOSE) { + uet_pdc_destroy(pdc); + goto out_unlock; + } /* if dropping the oldest packet move window */ if (UET_SKB_CB(skb)->psn == pdc->tx_base_psn) uet_pdc_mpr_advance_tx(pdc, 1); @@ -114,6 +131,7 @@ static void uet_pdc_rtx_timer_expired(struct timer_list *t) mod_timer(&pdc->rtx_timer, jiffies + nsecs_to_jiffies(smallest_diff)); +out_unlock: spin_unlock(&pdc->lock); } @@ -228,6 +246,154 @@ static int uet_pdc_rtx_queue(struct uet_pdc *pdc, struct sk_buff *skb, u32 psn) return 0; } +static s64 uet_pdc_get_psn(struct uet_pdc *pdc) +{ + unsigned long fzb = find_first_zero_bit(pdc->tx_bitmap, UET_PDC_MPR); + + if (unlikely(fzb == UET_PDC_MPR)) + return -1; + + set_bit(fzb, pdc->tx_bitmap); + + return pdc->tx_base_psn + fzb; +} + +static void uet_pdc_put_psn(struct uet_pdc *pdc, u32 psn) +{ + unsigned long psn_bit = psn - pdc->tx_base_psn; + + clear_bit(psn_bit, pdc->tx_bitmap); +} + +static int uet_pdc_tx_ctl(struct uet_pdc *pdc, u8 ctl_type, u8 flags, + __be32 psn, __be32 payload) +{ + struct uet_pds_ctl_hdr *ctl; + struct sk_buff *skb; + int ret; + + /* both CLOSE types need to be retransmitted and need a new PSN */ + switch (ctl_type) { + case UET_CTL_TYPE_CLOSE: + case UET_CTL_TYPE_REQ_CLOSE: + /* payload & psn must be 0 */ + if (payload || psn) + return -EINVAL; + /* AR must be set */ + flags |= UET_PDS_CTL_FLAG_AR; + break; + default: + WARN_ON(1); + return -EINVAL; + } + + skb = alloc_skb(sizeof(struct uet_pds_ctl_hdr), GFP_ATOMIC); + if (!skb) + return -ENOBUFS; + ctl = skb_put(skb, sizeof(*ctl)); + uet_pdc_build_prologue(&ctl->prologue, UET_PDS_TYPE_CTRL_MSG, + ctl_type, flags); + if (!psn) { + s64 psn_new = uet_pdc_get_psn(pdc); + + if (psn_new == -1) { + kfree_skb(skb); + return -ENOSPC; + } + psn = cpu_to_be32(psn_new); + } + ctl->psn = psn; + ctl->spdcid = cpu_to_be16(pdc->spdcid); + ctl->dpdcid_pdc_info_offset = cpu_to_be16(pdc->dpdcid); + ctl->payload = payload; + + ret = uet_pdc_rtx_queue(pdc, skb, be32_to_cpu(psn)); + if (ret) { + uet_pdc_put_psn(pdc, be32_to_cpu(psn)); + kfree_skb(skb); + return ret; + } + uet_pdc_xmit(pdc, skb); + + return 0; +} + +static void uet_pdc_close(struct uet_pdc *pdc) +{ + u8 state; + int ret; + + /* we have already transmitted the close control packet */ + if (pdc->state > UET_PDC_EP_STATE_ACK_WAIT) + return; + + if (!RB_EMPTY_ROOT(&pdc->rtx_queue)) { + if (pdc->state == UET_PDC_EP_STATE_ACK_WAIT) + return; + state = UET_PDC_EP_STATE_ACK_WAIT; + } else { + u8 ctl_type, ctl_flags = 0; + + if (pdc->is_initiator) { + ctl_type = UET_CTL_TYPE_CLOSE; + state = UET_PDC_EP_STATE_CLOSE_ACK_WAIT; + ctl_flags = UET_PDS_CTL_FLAG_AR; + } else { + ctl_type = UET_CTL_TYPE_REQ_CLOSE; + state = UET_PDC_EP_STATE_CLOSE_WAIT; + } + ret = uet_pdc_tx_ctl(pdc, ctl_type, ctl_flags, 0, 0); + if (ret) + return; + } + + pdc->state = state; +} + +static void uet_pdc_timeout_timer_expired(struct timer_list *t) +{ + struct uet_pdc *pdc = from_timer(pdc, t, timeout_timer); + unsigned long now = jiffies, last_rx; + bool rearm_timer = true; + + last_rx = READ_ONCE(pdc->rx_last_jiffies); + if (time_after_eq(last_rx, now) || + time_after_eq(last_rx + UET_PDC_IDLE_TIMEOUT_JIFFIES, now)) + goto rearm_timeout; + spin_lock(&pdc->lock); + switch (pdc->state) { + case UET_PDC_EP_STATE_ACK_WAIT: + uet_pdc_close(pdc); + fallthrough; + case UET_PDC_EP_STATE_CLOSE_WAIT: + case UET_PDC_EP_STATE_CLOSE_ACK_WAIT: + /* we waited too long for the last acks */ + if (time_before_eq(last_rx + (UET_PDC_IDLE_TIMEOUT_JIFFIES * 2), + now)) { + if (!pdc->is_initiator) + uet_pds_send_nack(pdc->pds, &pdc->key, + pdc->metadata->u.tun_info.key.tp_dst, + 0, + cpu_to_be16(pdc->spdcid), + cpu_to_be16(pdc->dpdcid), + UET_PDS_NACK_CLOSING_IN_ERR, + cpu_to_be32(pdc->rx_base_psn + 1), + 0); + uet_pdc_destroy(pdc); + rearm_timer = false; + } + break; + default: + uet_pdc_close(pdc); + break; + } + spin_unlock(&pdc->lock); +rearm_timeout: + if (rearm_timer) + mod_timer(&pdc->timeout_timer, + now + UET_PDC_IDLE_TIMEOUT_JIFFIES); +} + /* use the approach as nf nat, try a few rounds starting at random offset */ static bool uet_pdc_id_get(struct uet_pdc *pdc) { @@ -301,6 +467,7 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, if (!pdc->ack_bitmap) goto err_ack_bitmap; timer_setup(&pdc->rtx_timer, uet_pdc_rtx_timer_expired, 0); + timer_setup(&pdc->timeout_timer, uet_pdc_timeout_timer_expired, 0); pdc->metadata = uet_pdc_dst(key, dport, tos); if (!pdc->metadata) goto err_tun_dst; @@ -331,6 +498,9 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, } out: + mod_timer(&pdc->timeout_timer, + jiffies + UET_PDC_IDLE_TIMEOUT_JIFFIES); + return pdc_ins; err_ep_insert: @@ -351,6 +521,7 @@ struct uet_pdc *uet_pdc_create(struct uet_pds *pds, u32 rx_base_psn, u8 state, void uet_pdc_free(struct uet_pdc *pdc) { + timer_delete_sync(&pdc->timeout_timer); timer_delete_sync(&pdc->rtx_timer); uet_pdc_rtx_purge(pdc); dst_release(&pdc->metadata->dst); @@ -367,25 +538,6 @@ void uet_pdc_destroy(struct uet_pdc *pdc) uet_pds_pdc_gc_queue(pdc); } -static s64 uet_pdc_get_psn(struct uet_pdc *pdc) -{ - unsigned long fzb = find_first_zero_bit(pdc->tx_bitmap, UET_PDC_MPR); - - if (unlikely(fzb == UET_PDC_MPR)) - return -1; - - set_bit(fzb, pdc->tx_bitmap); - - return pdc->tx_base_psn + fzb; -} - -static void uet_pdc_put_psn(struct uet_pdc *pdc, u32 psn) -{ - unsigned long psn_bit = psn - pdc->tx_base_psn; - - clear_bit(psn_bit, pdc->tx_bitmap); -} - static int uet_pdc_build_req(struct uet_pdc *pdc, struct sk_buff *skb, u8 type, u8 flags) { @@ -685,8 +837,17 @@ int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, remote_fep_addr); break; case UET_PDC_EP_STATE_ACK_WAIT: + ret = uet_job_fep_queue_skb(pds_context(pdc->pds), + uet_ses_rsp_job_id(ses_rsp), skb, + remote_fep_addr); + if (!RB_EMPTY_ROOT(&pdc->rtx_queue) || ret < 0) + break; + uet_pdc_close(pdc); + ret = 1; break; case UET_PDC_EP_STATE_CLOSE_ACK_WAIT: + uet_pdc_destroy(pdc); + ret = 0; break; } @@ -919,3 +1080,43 @@ void uet_pdc_rx_nack(struct uet_pdc *pdc, struct sk_buff *skb) out: spin_unlock(&pdc->lock); } + +int uet_pdc_rx_ctl(struct uet_pdc *pdc, struct sk_buff *skb, + __be32 remote_fep_addr) +{ + struct uet_pds_ctl_hdr *ctl = pds_ctl_hdr(skb); + u32 ctl_psn = be32_to_cpu(ctl->psn); + int ret = -EINVAL; + + spin_lock(&pdc->lock); + netdev_dbg(pds_netdev(pdc->pds), "%s: CTRL pdc: [ spdcid: %u dpdcid: %u rx_base_psn %u ] " + "ctrl header: [ ctl_type: %u psn: %u ]\n", + __func__, pdc->spdcid, pdc->dpdcid, pdc->rx_base_psn, + uet_prologue_ctl_type(&ctl->prologue), ctl_psn); + if (psn_mpr_pos(pdc->rx_base_psn, ctl_psn) != UET_PDC_MPR_CUR) + goto out; + switch (uet_prologue_ctl_type(&ctl->prologue)) { + case UET_CTL_TYPE_CLOSE: + /* only the initiator can send CLOSE */ + if (pdc->is_initiator) + break; + ret = 0; + uet_pdc_send_ses_ack(pdc, UET_SES_RSP_RC_NULL, 0, + be32_to_cpu(ctl->psn), + 0, true); + uet_pdc_destroy(pdc); + break; + case UET_CTL_TYPE_REQ_CLOSE: + /* only the target can send REQ_CLOSE */ + if (!pdc->is_initiator) + break; + uet_pdc_close(pdc); + break; + default: + break; + } +out: + spin_unlock(&pdc->lock); + + return ret; +} diff --git a/drivers/ultraeth/uet_pds.c b/drivers/ultraeth/uet_pds.c index c144b6df8327..9ab0a088b308 100644 --- a/drivers/ultraeth/uet_pds.c +++ b/drivers/ultraeth/uet_pds.c @@ -195,13 +195,18 @@ static int uet_pds_rx_ack(struct uet_pds *pds, struct sk_buff *skb, struct uet_pds_req_hdr *pds_req = pds_req_hdr(skb); u16 pdcid = be16_to_cpu(pds_req->dpdcid); struct uet_pdc *pdc; + int ret; pdc = rhashtable_lookup_fast(&pds->pdcid_hash, &pdcid, uet_pds_pdcid_rht_params); if (!pdc) return -ENOENT; - return uet_pdc_rx_ack(pdc, skb, remote_fep_addr); + ret = uet_pdc_rx_ack(pdc, skb, remote_fep_addr); + if (ret >= 0) + uet_pdc_rx_refresh(pdc); + + return ret; } static void uet_pds_rx_nack(struct uet_pds *pds, struct sk_buff *skb) @@ -218,6 +223,26 @@ static void uet_pds_rx_nack(struct uet_pds *pds, struct sk_buff *skb) uet_pdc_rx_nack(pdc, skb); } +static int uet_pds_rx_ctl(struct uet_pds *pds, struct sk_buff *skb, + __be32 remote_fep_addr) +{ + struct uet_pds_ctl_hdr *ctl = pds_ctl_hdr(skb); + u16 pdcid = be16_to_cpu(ctl->dpdcid_pdc_info_offset); + struct uet_pdc *pdc; + int ret; + + pdc = rhashtable_lookup_fast(&pds->pdcid_hash, &pdcid, + uet_pds_pdcid_rht_params); + if (!pdc) + return -ENOENT; + + ret = uet_pdc_rx_ctl(pdc, skb, remote_fep_addr); + if (ret >= 0) + uet_pdc_rx_refresh(pdc); + + return ret; +} + static struct uet_pdc *uet_pds_new_pdc_rx(struct uet_pds *pds, struct sk_buff *skb, __be16 dport, u32 ack_gen_trigger, @@ -245,6 +270,7 @@ static int uet_pds_rx_req(struct uet_pds *pds, struct sk_buff *skb, struct uet_pdc_key key = {}; struct uet_fep *fep; struct uet_pdc *pdc; + int ret; key.src_ip = local_fep_addr; key.dst_ip = remote_fep_addr; @@ -303,7 +329,11 @@ static int uet_pds_rx_req(struct uet_pds *pds, struct sk_buff *skb, return PTR_ERR(pdc); } - return uet_pdc_rx_req(pdc, skb, remote_fep_addr, tos); + ret = uet_pdc_rx_req(pdc, skb, remote_fep_addr, tos); + if (ret >= 0) + uet_pdc_rx_refresh(pdc); + + return ret; } static bool uet_pds_rx_valid_req_next_hdr(const struct uet_prologue_hdr *prologue) @@ -368,6 +398,12 @@ int uet_pds_rx(struct uet_pds *pds, struct sk_buff *skb, __be32 local_fep_addr, ret = uet_pds_rx_req(pds, skb, local_fep_addr, remote_fep_addr, dport, tos); break; + case UET_PDS_TYPE_CTRL_MSG: + offset += sizeof(struct uet_pds_ctl_hdr); + if (!pskb_may_pull(skb, offset)) + break; + ret = uet_pds_rx_ctl(pds, skb, remote_fep_addr); + break; case UET_PDS_TYPE_NACK: if (uet_prologue_next_hdr(prologue) != UET_PDS_NEXT_HDR_NONE) break; diff --git a/include/net/ultraeth/uet_pdc.h b/include/net/ultraeth/uet_pdc.h index 60aecc15d0f1..02d2d5716c48 100644 --- a/include/net/ultraeth/uet_pdc.h +++ b/include/net/ultraeth/uet_pdc.h @@ -22,6 +22,8 @@ #define UET_PDC_MPR 128 #define UET_PDC_SACK_BITS 64 #define UET_PDC_SACK_MASK (U64_MAX << 3) +#define UET_PDC_IDLE_TIMEOUT_SEC 60 +#define UET_PDC_IDLE_TIMEOUT_JIFFIES (UET_PDC_IDLE_TIMEOUT_SEC * HZ) #define UET_SKB_CB(skb) ((struct uet_skb_cb *)&((skb)->cb[0])) @@ -38,7 +40,8 @@ enum { UET_PDC_EP_STATE_ESTABLISHED, UET_PDC_EP_STATE_QUIESCE, UET_PDC_EP_STATE_ACK_WAIT, - UET_PDC_EP_STATE_CLOSE_ACK_WAIT + UET_PDC_EP_STATE_CLOSE_ACK_WAIT, + UET_PDC_EP_STATE_CLOSE_WAIT }; struct uet_pdc_key { @@ -88,7 +91,7 @@ struct uet_pdc { int rtx_max; struct timer_list rtx_timer; unsigned long rtx_timeout; - + unsigned long rx_last_jiffies; unsigned long *rx_bitmap; unsigned long *tx_bitmap; unsigned long *ack_bitmap; @@ -102,6 +105,8 @@ struct uet_pdc { u32 ack_gen_min_pkt_add; u32 ack_gen_count; + struct timer_list timeout_timer; + struct rb_root rtx_queue; struct hlist_node gc_node; @@ -121,8 +126,11 @@ int uet_pdc_rx_ack(struct uet_pdc *pdc, struct sk_buff *skb, __be32 remote_fep_addr); int uet_pdc_tx_req(struct uet_pdc *pdc, struct sk_buff *skb, u8 type); void uet_pdc_rx_nack(struct uet_pdc *pdc, struct sk_buff *skb); +int uet_pdc_rx_ctl(struct uet_pdc *pdc, struct sk_buff *skb, + __be32 remote_fep_addr); struct metadata_dst *uet_pdc_dst(const struct uet_pdc_key *key, __be16 dport, u8 tos); +void uet_pdc_rx_refresh(struct uet_pdc *pdc); static inline void uet_pdc_build_prologue(struct uet_prologue_hdr *prologue, u8 type, u8 next, u8 flags) diff --git a/include/net/ultraeth/uet_pds.h b/include/net/ultraeth/uet_pds.h index 4e9794a4d3de..fc2414cc2de8 100644 --- a/include/net/ultraeth/uet_pds.h +++ b/include/net/ultraeth/uet_pds.h @@ -73,6 +73,11 @@ static inline struct uet_pds_ack_ext_hdr *pds_ack_ext_hdr(const struct sk_buff * return (struct uet_pds_ack_ext_hdr *)(pds_ack_hdr(skb) + 1); } +static inline struct uet_pds_ctl_hdr *pds_ctl_hdr(const struct sk_buff *skb) +{ + return (struct uet_pds_ctl_hdr *)skb_network_header(skb); +} + static inline struct uet_ses_rsp_hdr *pds_ack_ses_rsp_hdr(const struct sk_buff *skb) { /* TODO: ack_ext_hdr, CC_STATE, etc. */ diff --git a/include/uapi/linux/ultraeth.h b/include/uapi/linux/ultraeth.h index 53d2124bc285..c1d5457073e1 100644 --- a/include/uapi/linux/ultraeth.h +++ b/include/uapi/linux/ultraeth.h @@ -247,6 +247,25 @@ struct uet_pds_nack_hdr { __be32 payload; } __attribute__ ((__packed__)); +/* control packet flags */ +enum { + UET_PDS_CTL_FLAG_RSV21 = (1 << 0), + UET_PDS_CTL_FLAG_RSV22 = (1 << 1), + UET_PDS_CTL_FLAG_SYN = (1 << 2), + UET_PDS_CTL_FLAG_AR = (1 << 3), + UET_PDS_CTL_FLAG_RETX = (1 << 4), + UET_PDS_CTL_FLAG_RSV11 = (1 << 5), + UET_PDS_CTL_FLAG_RSV12 = (1 << 6), +}; + +struct uet_pds_ctl_hdr { + struct uet_prologue_hdr prologue; + __be32 psn; + __be16 spdcid; + __be16 dpdcid_pdc_info_offset; + __be32 payload; +} __attribute__ ((__packed__)); + /* ses request op codes */ enum { UET_SES_REQ_OP_NOOP = 0x00, From patchwork Thu Mar 6 23:02:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 14005483 X-Patchwork-Delegate: kuba@kernel.org Received: from mail-qv1-f51.google.com (mail-qv1-f51.google.com [209.85.219.51]) (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 74FF0280A50 for ; Thu, 6 Mar 2025 23:04:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302265; cv=none; b=hsgmGF9s/p/JXPBZxucaEKYCIZiHI2vH3gR3ifJU3UqO/XJ0DFLO0xslM4MwSDT0PatsouGwHYRPfLnRchPJsl1Gh3aR0bCOKh+iElomH3SeEhKUrT47i1o+VUzO+zAaGRGmvfPvhdpKcLOcZH304urVNDPxH4opufXxGIkslcM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302265; c=relaxed/simple; bh=VlTJWrfskKiMJ0jPrrZCGioBK+EUcD/4Mq939WrXGtM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RZQINMND1iUs5xl/YvNWFLwGIz3vavpCPoze0ecujCydD9kbLWw8os+3PWzJB/7tc5DE/UjappxeO0pXE68+3P/3oK7bYa1W1Va/spr1+sO3qYpAFscLFwASaUrP1baOdKGA9eYAj1cAYp2ogIp7iEzqRc/PEGG3E3zE0YP64+s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net; spf=pass smtp.mailfrom=enfabrica.net; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b=hUCnDA17; arc=none smtp.client-ip=209.85.219.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enfabrica.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=enfabrica.net header.i=@enfabrica.net header.b="hUCnDA17" Received: by mail-qv1-f51.google.com with SMTP id 6a1803df08f44-6dcd4f1aaccso19785626d6.2 for ; Thu, 06 Mar 2025 15:04:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enfabrica.net; s=google; t=1741302262; x=1741907062; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+TFGwcWhVCnTXz5ntSIwjluyAOC28ms1ec0UlWPS2kE=; b=hUCnDA17oM+nxjRjNYefTc9kU+HxAiw7SVXD3V045UwHPZ4pl8RzZxhhpoBIbE2ajX aBBMm15OPKLqFpthyRGO7YBrhXmayKPl2fTSKAGLVvO/AeLLqMu06nqO2tyzg2LcCEYp QsHW6/nKBj5mUWut8xTSU09Y+Zpuxl13/tVPQDsETHn8ifrCXxIlAE6uaVHi55GUVpQn t11gQQZRix+6bVmOjJd6yZRsyz7DVSUO1/Thb5147Q4ECST/Tol3QlMFsKNtgXPf27KR 7gMv8vPu5CyLvhDP7lXblUcnU3OY0ZmbWpgI1NsC45e+HqAn42owOnO6+EClJqQxhzlB 3GCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302262; x=1741907062; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+TFGwcWhVCnTXz5ntSIwjluyAOC28ms1ec0UlWPS2kE=; b=mnSLY0qkcWqanZoFr8KcB4H3dq7VfGRaUq+ORWlcDhAe0ivY8riQ+OeESifoj3gI7l A1f5nKWbrx0aUNNjB5uB8KPHEa4vxVy8uIR/G54/uDQATwlAjjGhBkrWlyLWE+YxVqx1 CSRC8DUtqMryITu0Vopr8Yq+A8mwuX/NNQJclPBnk7HTnR2bgFkeejllLNaGdFvuA1lW h5zg86sC5SlpuzRTbDswpoXbmizeU2qtJ+c72rUY7uEn6Mj5Zeh8nw76g2FvUX+BjVtv IJtLjDCKHrfgFFEvABQZqGZSdGm1d/Kqf6oncRMJYpLpYucQgG4M7LUmDb82b+7AEl1t UrJg== X-Gm-Message-State: AOJu0YyMclu52uxVjBflMBOpbaYzu+u8p7j9KDCbtbpF7XdA0bhFTeYQ vSApiT1hdCVil3KfHCS6/Jz1xNhRpZHXUHLxiUDmbU+jJXWLbIBmfaeeZWHtU4r+242WNzaJ0cg PKryHsBxsFqBzCcba6F7sYf68UJeLlyNxqJVl4PwQl6uAQjsScF9d6pEUbVYnzaoBnPk8SkVpvd +P/CJcGOoxMT+e5kqkgsEKFu1euM6jFZhlJWgg7cXr X-Gm-Gg: ASbGnctc9RWCKOW+rOEVvso7+073LCnzhDA1zpRyHURwTRZKW+1EFeGIyyi9QSUzCEn S/3BMFvTTeiVYMgJr0e2lTx0KChVQ8DJPJUH7EtPg7SUOo5EGq7oZRoPbf1iM+JdfSo/WptPywb 6IGVgCRdQGfuGYTmsAAisOJMBNl3iv++RYG2hnqHcEe1MtfLp2vbo6w5m4gjffnautgz2pFFmbx vRxH3hl1E31EadDtXIzzlUoSsETRDfjScwzmRKFdkcBPAMqjSqoS1B+N1ZZEv1snrLmKX7Car5h mDrqiK9cZFaAc5+J+ivPj6cp7HavIpxmK1S78i5T4ISUUaAhaSlVzsfKK474gwKeDfsQ X-Google-Smtp-Source: AGHT+IGl6OtlqTz58lYmGOcKPuPseJIz0NnomobhDiNmx6hs+qVTfcOzr6tA/falt0FtKrpp3jjUmQ== X-Received: by 2002:a05:6214:326:b0:6e8:fee2:aae4 with SMTP id 6a1803df08f44-6e9006ad479mr12029116d6.28.1741302262036; Thu, 06 Mar 2025 15:04:22 -0800 (PST) Received: from debil.. (78-154-15-142.ip.btc-net.bg. [78.154.15.142]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac256654fa6sm14971966b.93.2025.03.06.15.04.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Mar 2025 15:04:21 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: shrijeet@enfabrica.net, alex.badea@keysight.com, eric.davis@broadcom.com, rip.sohan@amd.com, dsahern@kernel.org, bmt@zurich.ibm.com, roland@enfabrica.net, nikolay@enfabrica.net, winston.liu@keysight.com, dan.mihailescu@keysight.com, kheib@redhat.com, parth.v.parikh@keysight.com, davem@redhat.com, ian.ziemba@hpe.com, andrew.tauferner@cornelisnetworks.com, welch@hpe.com, rakhahari.bhunia@keysight.com, kingshuk.mandal@keysight.com, linux-rdma@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com Subject: [RFC PATCH 13/13] HACK: drivers: ultraeth: add char device Date: Fri, 7 Mar 2025 01:02:03 +0200 Message-ID: <20250306230203.1550314-14-nikolay@enfabrica.net> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250306230203.1550314-1-nikolay@enfabrica.net> References: <20250306230203.1550314-1-nikolay@enfabrica.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Alex Badea Add a character device so we can send and receive packets from user-space. It also implements a private ioctl for associating with a job. This patch is just a quick hack to allow using the Ultra Ethernet software device from user-space until proper user<->kernel APIs are defined. Signed-off-by: Alex Badea Signed-off-by: Nikolay Aleksandrov --- Documentation/netlink/specs/ultraeth.yaml | 9 + drivers/ultraeth/Makefile | 2 +- drivers/ultraeth/uet_chardev.c | 264 ++++++++++++++++++++++ drivers/ultraeth/uet_context.c | 31 ++- include/net/ultraeth/uet_chardev.h | 11 + include/net/ultraeth/uet_context.h | 3 + include/uapi/linux/ultraeth.h | 21 ++ include/uapi/linux/ultraeth_nl.h | 3 + 8 files changed, 342 insertions(+), 2 deletions(-) create mode 100644 drivers/ultraeth/uet_chardev.c create mode 100644 include/net/ultraeth/uet_chardev.h diff --git a/Documentation/netlink/specs/ultraeth.yaml b/Documentation/netlink/specs/ultraeth.yaml index 847f748efa52..3dc10e52131e 100644 --- a/Documentation/netlink/specs/ultraeth.yaml +++ b/Documentation/netlink/specs/ultraeth.yaml @@ -22,6 +22,15 @@ attribute-sets: - name: netdev-name type: string + - + name: chardev-name + type: string + - + name: chardev-major + type: s32 + - + name: chardev-minor + type: s32 - name: contexts attributes: diff --git a/drivers/ultraeth/Makefile b/drivers/ultraeth/Makefile index f2d6a8569dbf..bee8e7aa00bb 100644 --- a/drivers/ultraeth/Makefile +++ b/drivers/ultraeth/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_ULTRAETH) += ultraeth.o ultraeth-objs := uet_main.o uet_context.o uet_netlink.o uet_job.o \ - uecon.o uet_pdc.o uet_pds.o + uecon.o uet_pdc.o uet_pds.o uet_chardev.o diff --git a/drivers/ultraeth/uet_chardev.c b/drivers/ultraeth/uet_chardev.c new file mode 100644 index 000000000000..f02f2c1e1afd --- /dev/null +++ b/drivers/ultraeth/uet_chardev.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#define MAX_PDS_HDRLEN 64 /* -ish? */ + +static int uet_char_open(struct inode *inode, struct file *file) +{ + struct uet_context *ctx; + struct uet_fep *fep; + int rv; + + ctx = uet_context_get_by_minor(iminor(inode)); + if (!ctx) + return -ENOENT; + + fep = kzalloc(sizeof(*fep), GFP_KERNEL); + if (!fep) { + rv = -ENOMEM; + goto err_alloc; + } + + fep->context = ctx; + fep->ack_gen_min_pkt_add = UET_DEFAULT_ACK_GEN_MIN_PKT_ADD; + fep->ack_gen_trigger = UET_DEFAULT_ACK_GEN_TRIGGER; + skb_queue_head_init(&fep->rxq); + file->private_data = fep; + rv = nonseekable_open(inode, file); + if (rv < 0) + goto err_open; + + return rv; + +err_open: + kfree(fep); +err_alloc: + uet_context_put(ctx); + + return rv; +} + +static int uet_char_release(struct inode *inode, struct file *file) +{ + struct uet_fep *fep = file->private_data; + + uet_job_reg_disassociate(&fep->context->job_reg, fep->job_id); + skb_queue_purge(&fep->rxq); + uet_context_put(fep->context); + kfree(fep); + + return 0; +} + +static long uet_char_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct uet_fep *fep = file->private_data; + void __user *p = (void __user *)arg; + int ret = 0; + + switch (cmd) { + case UET_ADDR_REQ: { + struct uet_job_addr_req areq; + + if (copy_from_user(&areq, p, sizeof(areq))) + return -EFAULT; + // XXX: validate address + + areq.service_name[UET_SVC_MAX_LEN - 1] = '\0'; + memcpy(&fep->addr.in_address, &areq.address, + sizeof(fep->addr.in_address)); + + ret = uet_job_reg_associate(&fep->context->job_reg, fep, + areq.service_name); + if (!ret) { + if (areq.ack_gen_trigger > 0) + fep->ack_gen_trigger = areq.ack_gen_trigger; + if (areq.ack_gen_min_pkt_add > 0) + fep->ack_gen_min_pkt_add = areq.ack_gen_min_pkt_add; + } + break; + } + default: + return -EOPNOTSUPP; + } + + return ret; +} + +static ssize_t uet_char_read(struct file *file, char __user *ubuf, + size_t usize, loff_t *off) +{ + struct uet_fep *fep = file->private_data; + struct uet_prologue_hdr *prologue; + struct uet_pds_meta meta = {}; + struct sk_buff *skb = NULL; + int ret = -ENOTCONN; + int hdrlen = 0; + size_t userlen; + + pr_debug("%s file=%p fep=%p size=%zu\n", __func__, file, fep, usize); + + ret = -EAGAIN; + skb = skb_dequeue(&fep->rxq); + if (!skb) + goto out_err; + + ret = skb_linearize(skb); + if (ret) + goto out_err; + + prologue = pds_prologue_hdr(skb); + meta.next_hdr = uet_prologue_next_hdr(prologue); + meta.addr = UET_SKB_CB(skb)->remote_fep_addr; + switch (meta.next_hdr) { + case UET_PDS_NEXT_HDR_RSP_DATA: + case UET_PDS_NEXT_HDR_RSP_DATA_SMALL: + /* TODO */ + ret = -EOPNOTSUPP; + goto out_err; + case UET_PDS_NEXT_HDR_RSP: + hdrlen = sizeof(struct uet_pds_ack_hdr); + break; + default: + hdrlen = sizeof(struct uet_pds_req_hdr); + break; + } + userlen = sizeof(meta) + skb->len - hdrlen; + if (userlen > usize) { + ret = -EMSGSIZE; + goto out_err; + } + + if (copy_to_user(ubuf, &meta, sizeof(meta))) { + ret = -EFAULT; + goto out_err; + } + if (copy_to_user(ubuf + sizeof(meta), skb->data + hdrlen, skb->len - hdrlen)) { + ret = -EFAULT; + goto out_err; + } + + consume_skb(skb); + ret = userlen; + + return ret; + +out_err: + kfree_skb(skb); + + return ret; +} + +static ssize_t uet_char_write(struct file *file, const char __user *ubuf, + size_t usize, loff_t *off) +{ + struct uet_fep *fep = file->private_data; + struct sk_buff *skb = NULL; + struct uet_pds_meta *meta; + struct uet_job *job; + __be32 daddr, saddr; + int ret = -ENODEV; + __be16 dport; + void *buf; + + pr_debug("%s file=%p fep=%p size=%zu\n", __func__, file, fep, usize); + + rcu_read_lock(); + job = uet_job_find(&fep->context->job_reg, fep->job_id); + if (!job) + goto out_err; + + ret = -ENOMEM; + skb = alloc_skb(MAX_HEADER + MAX_PDS_HDRLEN + usize, GFP_ATOMIC); + if (!skb) + goto out_err; + skb_reserve(skb, MAX_HEADER + MAX_PDS_HDRLEN); + buf = skb_put(skb, usize); + ret = -EFAULT; + if (copy_from_user(buf, ubuf, usize)) + goto out_err; + + print_hex_dump_bytes("pds tx ", DUMP_PREFIX_OFFSET, skb->data, skb->len); + + meta = skb_pull_data(skb, sizeof(*meta)); + if (!meta) { + ret = -EINVAL; + goto out_err; + } + /* TODO: IPv6 */ + /* TODO: per-packet daddr */ + saddr = fep->addr.in_address.ip; + daddr = meta->addr; + dport = meta->port; + + switch (meta->next_hdr) { + case UET_PDS_NEXT_HDR_RSP_DATA: + case UET_PDS_NEXT_HDR_RSP_DATA_SMALL: + ret = -EOPNOTSUPP; /* TODO */ + goto out_err; + case UET_PDS_NEXT_HDR_RSP: + ret = 0; /* FIXME: ACK PSN would be wrong */ + break; + default: + ret = uet_pds_tx(&fep->context->pds, skb, saddr, daddr, dport, + job->id); + break; + } + + if (ret < 0) + goto out_err; + rcu_read_unlock(); + + return usize; + +out_err: + rcu_read_unlock(); + kfree_skb(skb); + + return ret; +} + +static const struct file_operations uet_char_ops = { + .owner = THIS_MODULE, + .open = uet_char_open, + .release = uet_char_release, + .read = uet_char_read, + .write = uet_char_write, + .unlocked_ioctl = uet_char_ioctl, +}; + +#define UET_CHAR_MAX_NAME 20 + +int uet_char_init(struct miscdevice *cdev, int id) +{ + int ret = -ENOMEM; + + cdev->minor = MISC_DYNAMIC_MINOR; + cdev->name = kzalloc(UET_CHAR_MAX_NAME, GFP_KERNEL); + if (!cdev->name) + return ret; + snprintf((char *)cdev->name, UET_CHAR_MAX_NAME, "ultraeth%d", id); + cdev->fops = &uet_char_ops; + + ret = misc_register(cdev); + if (ret) + kfree(cdev->name); + + return ret; +} + +void uet_char_uninit(struct miscdevice *cdev) +{ + kfree(cdev->name); + misc_deregister(cdev); +} diff --git a/drivers/ultraeth/uet_context.c b/drivers/ultraeth/uet_context.c index 6bdd72344e01..7bddc810503b 100644 --- a/drivers/ultraeth/uet_context.c +++ b/drivers/ultraeth/uet_context.c @@ -2,6 +2,7 @@ #include #include +#include #include "uet_netlink.h" #define MAX_CONTEXT_ID 256 @@ -78,6 +79,24 @@ struct uet_context *uet_context_get_by_id(int id) return ctx; } +struct uet_context *uet_context_get_by_minor(int minor) +{ + struct uet_context *ctx; + + mutex_lock(&uet_context_lock); + list_for_each_entry(ctx, &uet_context_list, list) { + if (ctx->cdev.minor == minor) { + refcount_inc(&ctx->refcnt); + goto out; + } + } + ctx = NULL; +out: + mutex_unlock(&uet_context_lock); + + return ctx; +} + void uet_context_put(struct uet_context *ctx) { if (refcount_dec_and_test(&ctx->refcnt)) @@ -111,6 +130,10 @@ int uet_context_create(int id) if (err) goto ctx_pds_err; + err = uet_char_init(&ctx->cdev, ctx->id); + if (err) + goto ctx_char_err; + err = uecon_netdev_init(ctx); if (err) goto ctx_netdev_err; @@ -120,6 +143,8 @@ int uet_context_create(int id) return 0; ctx_netdev_err: + uet_char_uninit(&ctx->cdev); +ctx_char_err: uet_pds_uninit(&ctx->pds); ctx_pds_err: uet_jobs_uninit(&ctx->job_reg); @@ -135,6 +160,7 @@ static void __uet_context_destroy(struct uet_context *ctx) { uet_context_unlink(ctx); uecon_netdev_uninit(ctx); + uet_char_uninit(&ctx->cdev); uet_pds_uninit(&ctx->pds); uet_jobs_uninit(&ctx->job_reg); uet_context_put_id(ctx); @@ -183,7 +209,10 @@ static int __nl_ctx_fill_one(struct sk_buff *skb, if (nla_put_s32(skb, ULTRAETH_A_CONTEXT_ID, ctx->id) || nla_put_s32(skb, ULTRAETH_A_CONTEXT_NETDEV_IFINDEX, ctx->netdev->ifindex) || - nla_put_string(skb, ULTRAETH_A_CONTEXT_NETDEV_NAME, ctx->netdev->name)) + nla_put_string(skb, ULTRAETH_A_CONTEXT_NETDEV_NAME, ctx->netdev->name) || + nla_put_string(skb, ULTRAETH_A_CONTEXT_CHARDEV_NAME, ctx->cdev.name) || + nla_put_s32(skb, ULTRAETH_A_CONTEXT_CHARDEV_MAJOR, MISC_MAJOR) || + nla_put_s32(skb, ULTRAETH_A_CONTEXT_CHARDEV_MINOR, ctx->cdev.minor)) goto out_err; genlmsg_end(skb, hdr); diff --git a/include/net/ultraeth/uet_chardev.h b/include/net/ultraeth/uet_chardev.h new file mode 100644 index 000000000000..963b3e247630 --- /dev/null +++ b/include/net/ultraeth/uet_chardev.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ + +#ifndef _UECON_CHARDEV_H +#define _UECON_CHAR_H + +#include + +int uet_char_init(struct miscdevice *cdev, int id); +void uet_char_uninit(struct miscdevice *cdev); + +#endif /* _UECON_CHARDEV_H */ diff --git a/include/net/ultraeth/uet_context.h b/include/net/ultraeth/uet_context.h index 76077df3bce6..06a5c7f252ac 100644 --- a/include/net/ultraeth/uet_context.h +++ b/include/net/ultraeth/uet_context.h @@ -11,6 +11,7 @@ #include #include #include +#include struct uet_context { int id; @@ -21,9 +22,11 @@ struct uet_context { struct net_device *netdev; struct uet_job_registry job_reg; struct uet_pds pds; + struct miscdevice cdev; }; struct uet_context *uet_context_get_by_id(int id); +struct uet_context *uet_context_get_by_minor(int minor); void uet_context_put(struct uet_context *ses_pl); int uet_context_create(int id); diff --git a/include/uapi/linux/ultraeth.h b/include/uapi/linux/ultraeth.h index c1d5457073e1..2843bb710f1e 100644 --- a/include/uapi/linux/ultraeth.h +++ b/include/uapi/linux/ultraeth.h @@ -512,4 +512,25 @@ struct fep_address { __u16 padding; __u8 version; }; + +/* char device hacks */ +#define UET_IOCTL_MAGIC 'u' +#define UET_ADDR_REQ _IO(UET_IOCTL_MAGIC, 1) + +struct uet_job_addr_req { + struct fep_in_address address; + char service_name[UET_SVC_MAX_LEN]; + __u32 ack_gen_trigger; + __u32 ack_gen_min_pkt_add; + __u8 flags; +}; + +struct uet_pds_meta { + __u8 next_hdr:4; + __u8 reserved1:4; + __u8 reserved2; + __be16 port; + /* XXX: fep_address */ + __be32 addr; +} __attribute__((packed)); #endif /* _UAPI_LINUX_ULTRAETH_H */ diff --git a/include/uapi/linux/ultraeth_nl.h b/include/uapi/linux/ultraeth_nl.h index 515044022906..884fa165adb6 100644 --- a/include/uapi/linux/ultraeth_nl.h +++ b/include/uapi/linux/ultraeth_nl.h @@ -13,6 +13,9 @@ enum { ULTRAETH_A_CONTEXT_ID = 1, ULTRAETH_A_CONTEXT_NETDEV_IFINDEX, ULTRAETH_A_CONTEXT_NETDEV_NAME, + ULTRAETH_A_CONTEXT_CHARDEV_NAME, + ULTRAETH_A_CONTEXT_CHARDEV_MAJOR, + ULTRAETH_A_CONTEXT_CHARDEV_MINOR, __ULTRAETH_A_CONTEXT_MAX, ULTRAETH_A_CONTEXT_MAX = (__ULTRAETH_A_CONTEXT_MAX - 1)