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: 14005485 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 6250927C167 for ; Thu, 6 Mar 2025 23:04:00 +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=1741302242; cv=none; b=W8qYdhGvNJCmjkNLNwj9EuNZRhZlWtRtLdnIJCc0qz3tlpeugc9taTCZ0+jDE0Rcskcoev9uXOSXLYL7u8SLIBG4wyRZO2Wpm92MvjI5WnBwUSDgYphBXGvzGrYBnMfF5VKwU8MFIZvQARN8Anih0l2NNzbrM2uH1jGeUgcklHI= 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.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="JAg5nyfN" Received: by mail-qv1-f54.google.com with SMTP id 6a1803df08f44-6e8fce04655so6483006d6.3 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=HHy4tcgO2ylbR/mtocUKo6J6LHKNMMKxzp9xJKmRdzCF4n27oyhGYBxgK6xwb9rOlY KRvY3AEp9TPW3id1CNI9j+ttnTnrC9wi0xWniuE5tG99BxJ3eg7cF1kuI+ycZYxjgSax +35GebSI05lDD/HG98tK3XVfv/R4TIZ4XkISgqq8kwEmJH9pO1c4sWvThfHnEqrC+ng+ 2KGgsP0dvaiFHD4Y7H8oMIcnkQI8G24WUTQLQ2bFDL9QPKXPGMFLV2tYlOMjfNYjVV2r FIu/vuYG2mnV6xIZBg0WoBbz4QeYvAydIaQomgQsRuAoTXqQU4mbUv92B6FtCPRS3aBx 9P7w== X-Forwarded-Encrypted: i=1; AJvYcCW9DnXjVCxClUDLFOltibUTV0AdA8oOt7IRLcix8wf/AhNxz7TZnziaD1yUJLfzPAmmy72+UsqsvzBp@vger.kernel.org X-Gm-Message-State: AOJu0YyYcUsoOB0Ml6ERj/yuAovAodJX8NehhLjlqakeMD5c13vh9Fan Qn2UZXs1DKIlM+csRlC//LndCfEnZe0YJ9WcxFmtgmNF++W8WNzd/ENrg6XRFZ8= X-Gm-Gg: ASbGnctEe2ktoK09pbeeufRr4ykm2tXtYr1mCFZvbQVE97VsJX09D1yweL8FNTsWOGx MAifTI1Q7Bwjl17bNRYp7Py0GFDURc9h/kDWJIz4MWa7IqnUxq85HxwNxORdp8oKQ3RpNA7VeOA 2g5rPzVOFFVJrfRLsPq4iMMGsdW5P83Dtj8E/3mPDyIFgcyL7JY4mkRmHzKzqbJFFR6IJF/rhJh qxMoW67ojR6MP4yWsw4SbfeUawKerHEiiZ2A/22khXRdTcE+l3Yu0PsHSHvPG+7hj96jf2z0dhu VQS7PREXs/XikMXIDyzxwAspNixJ7QcJkv4ww+feVND3iF0skN4CHR1ATnEZXMBPxb/3 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: linux-rdma@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: 14005486 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 DB58727C167 for ; Thu, 6 Mar 2025 23:04:02 +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=1741302244; cv=none; b=gU1XFibRdYA149CrHuwSCFkl+cPuKirkgDaITMg9hV2lyZVxtgc4DWzZzwPh/TMo++JV9tKr++WfI4pNMiWrhPR2W2jPART5VjaOFUJRSqV80D4Z2C1ucsNBsnbRpdVyzgvB+lkrJAf2OfsvUnrXpXheB6kv/5itNieyuzH3CKI= 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.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="IXIVWwc5" Received: by mail-qv1-f47.google.com with SMTP id 6a1803df08f44-6e8efefec89so10075156d6.3 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=e0tDAFRcVtogUiQ6rPN8y3V/S3tUJw7T9kl8USA/1nHj5fPXJUH8uqMP0PdS+5jGYI fPJk0WwMbTB0lLeC60aEuFSSrycewh8y294LW+ZpuXMLAcdf2XefOvW33ObBUFdgMKYa FKv3EzUsJh7KrcRmQtiGbBapfZnJoGliXQRbwq3gTnJHPSp1XbgbMG4me3CtIceK96fq zULtXUab2a9AaRQ1mBt6SurqGh3osN3tEDS7FY8NHGblS0CzwXmyx7SpdPTaBzAkLFXP Czd0gMicvBwd5xa2aFXobbTOjEX09hjcjLUMo36zXzsL1+sTDIiNoRAbUo0vQdkmnLXs nFMA== X-Forwarded-Encrypted: i=1; AJvYcCUg2A33xS5Izm4icDEJV1qowpusiYF8WhEoRSapZHIj+8kpuefuD1rRl1dOvC/wLnFG1fOXcdVnrxil@vger.kernel.org X-Gm-Message-State: AOJu0YxxohG15/I8zzrB+rRSdZxhcwTYhDDCfBSnQoZfPvz+Fjmm5h0i 8w5iIdeOfUgFj2xJBo936jpNVdagHHBUYndYZiPk8+bY9ZQzyNX+ZBBfH7/STi0= X-Gm-Gg: ASbGnctqCvbKq6R1Q0kzQO4Zgj+AiXl0qmPCD/tCxfGgPPWAMcGg65wNvkQunNyW8Kx q+UHLW9o1XJNBwfdMynBNls2dWFh9uYxQ2nbw3iSeXTFUc9teOoGy2hahGBRj/mJZCSYnXWEXR4 /IIfxGYnCRawgTUtzlPgopCZgwA1zFBKPySnqx6sOKgOXuadqRRQFeaYDV8p1SYPUVbGLqH39Vj 093rJaunTBz2mzqiYXtVMdrLSmaGfpxz4Smtt09bK2oh6R62Ms/uTmLIo5MIyd0/ozqyGM5ufME sJUlpFSGIonLeSJW+3VgTIe2UHjLqP7kwOIT6SYLnAk9EDbtNh0b/4nxHn4iZuv2T6jx 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: linux-rdma@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: 14005487 Received: from mail-qk1-f181.google.com (mail-qk1-f181.google.com [209.85.222.181]) (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 C0A3B27D791 for ; Thu, 6 Mar 2025 23:04:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302246; cv=none; b=YN31jQlJnvSdGTbwkb6BzsWlSqZ+N/YStuSqT9dqSlQH6VjNSzr8muuWeb53G6pICZ3ou2AZ2jAzdsAjs/xJZ1ga8REM+T0N/32D8xQGsNn656cwXdAGE5bwTSkuMXSyBB4PV91Ekmc3Ks6Sp+pEU5kErp1SEOkH65bsfJeeJDQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302246; c=relaxed/simple; bh=9t+BWyeKo3lXUFD7OKztQ3S+oioUT+EA4xokMzKS89o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=onTe0my18Yf//L2xr6AMOTxJrRyZljKBdHCqERzab/56jHWd9GQXJ32XjPUA2yMDvMuuWoOea1eD7QjZA+e8BB+Q0IieKPRjYLRLvra2aD8ntNy6s/spGMmiS45oJR8+kDn7l7CHoMq+GltBD6H9CJRmdDX3WOLW9qyecMyIsI8= 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=XCcg56bW; arc=none smtp.client-ip=209.85.222.181 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="XCcg56bW" Received: by mail-qk1-f181.google.com with SMTP id af79cd13be357-7c3d1664ed5so145626085a.2 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=1741302243; x=1741907043; 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=XCcg56bWKC6CfmsWUU6oxSXDVohNRQlgqwOoFOwOW3Yhqcl/XXmJr6r4X6xgSce+yM j0i785+r+ohA9d5FDMiyJ1SjGJtJH3uHd7oBINhMt3T00mt4POBSmu9b9K3QJ3vOyFRU 7FV4FXIwfh7qIjY5xPUPgnAMUa5zmJf+FgmMjYrh3l09ckcKs4hWVPxriYsQRfuSomYJ g9xN8lzHWlv3uf1ZVGctQEyP91CF5QE9teXsahWEiVpTQH4m5XA1okEZUp+CwH4IJOhJ YmX922QmpIz8KWWzMRxoO+mAGOWxC3U/64nRz0DjXuf6+s+WhQURiQG1W7XB3h9PoWCl 4yRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302243; x=1741907043; 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=IzFhDPYP3l1IcoU6zbMq/jOiDZ7VxS7qlKbGTIPHCDsIGb02qeokJDzl+9pV1Lj2Yp CRQWzxeQU0XrasvTaVezsZxKs6l9DXFl/uftMg18f6+zRJ9pLGrLWRGTGOkakhDNPy8E 7Jo4ld9gRxPuf5hgu0zQL9d1U7JGALgvSXGWbPmdjfSK2YUYyKdbosAFE4Sd+LunyfQA 5WlOl786IIU0RJC8iX0LVQkdWci19soqGLH6XroMHda5nAupwdvegEFCgQJxcly+R57e uBQr4887UK5z1Pvw8QHyP/agaTV0sxtA5jYv7ynegIonZ4iHSeqzmm776h5BmW8hjSXy 6AIQ== X-Forwarded-Encrypted: i=1; AJvYcCU1LO4ZTaGUmKuTNpyyFQDW1NtOvnHPN53MGbt+reborHnn7DXAeuS04SNXn0zU3v/UjOdEXs69+Lyy@vger.kernel.org X-Gm-Message-State: AOJu0Ywm5WlaSl/edlpzUbDfNTTrB35KIIX99o3aGYKkWBo0I+mPJQC3 1oNlMVFFxNrlgDrwwJrF12uxGQuTwp+fdugcLriTdH7tAhpLNO00WFf8w9fKqQk= X-Gm-Gg: ASbGncsZNnnIviv1SLaQ/IzayJs4/xk4HM3DjaSszS88e/kIwoV7cv2hu2rK8vsdDGx 7K5jwkfMO5N0CkpISLIWCa6Pu22hP4cqVQQnb0ftzBEnD7chvBkUb6gWAKbWXN1M9GEY4Coj5Ua iHxzmIdfduLZ0hotYW5Ejd/T8IGyYrJ41dHG4qeiYJwIyLBiRDQFAhgD1n+ORMkZlz15bKhOBj1 Ii9jSqD/pd2zPUFPzx5WWIapWk7NhgOBeI1pPUjvRFiksxLSa829grv9YylOin9NzonQSqSqYRE g/qMAj08bD6OWWOdCMgyVIWYV+miACjbVaka5pJg6jRy90Klr0lNGBCy3TTtjgm1jH0i 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: linux-rdma@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: 14005488 Received: from mail-qk1-f172.google.com (mail-qk1-f172.google.com [209.85.222.172]) (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 DBF871FBEA6 for ; Thu, 6 Mar 2025 23:04:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302249; cv=none; b=ogyHWCS2wIFrryegoVPqYTu4Vy+TrN+GJ+vE62buIzmVRrfgTbxcpf2bGgi6ptOPzb+9/nNDeoWwt6SaMruwBbycE6V0VCKFjvk7gxdylRupIn3fG/uKV+I8RfD23pSRblgiD35Md3AIu1lMj4aqZ7w8i59t4F2fgBLATHsXizk= 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.172 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-f172.google.com with SMTP id af79cd13be357-7c081915cf3so164073085a.1 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=JHcYihtsS+XTfuDSOZkdiFyBYjGKe2joFl8eYp2Flwc099Y3GogRxetUXnghzIpCvB t5k59FbuQcVoVgYbwVYvpWgi5QQ9JUMFaJCajfXKqNBHo9mtnjp8t+HB5yEUxsqa0YsM F+OoRtpu9B+LXJyB2o3I/MEoPcTA6YBpGVx977rgsnp6H2aM/MawMpe/9/bSild/Mcib 8Vf8Ke6SldbDDz0YXC+EVN8XtFd03qHi5OSDJazMLh4OIv4rN9qqgZE88RYBUtgYMDDM EvHfq91O/v1DiR3/yy8Llv9XtPZhr/MafjhADOV+r+h27tWLeArjzUoLBEGxSUX2HZmL bRXQ== X-Forwarded-Encrypted: i=1; AJvYcCUebS68B4l93dAzl9PAvdeXIqmzy0A1JgBYqCRo7HJm0iUuU9+Jxkq68pb2efcWtDykPQ6El+LWvjaS@vger.kernel.org X-Gm-Message-State: AOJu0Yz6nQyn9fKiRjbn33OBI/56b4uWS5jMF/QJwjpF1cGel/Yg/6Qu uuJouEPut1mjTFLaL9DV1QJ3TGqC8hD+08Fw5mch8VjVcVrK7ksoABCADTdfFe0= X-Gm-Gg: ASbGncvsH5LCyMFIefsdK4XUBxZKK8bclcnQ+1oiSX2wgibUJFpjg+j4MkLl8tpjwBA T8WRLZRZpSWYrme2F0f/HtfBVoFTDwY5srHAdVLD8RpfjNvU3uZkJJDyNGfqwsa9e08TOTt9GCb YuelbFQ79+My/xvPQe4TFfi3llZRJuzFiAozS0K67h90NA2sMZFAOnwUS4yYVaMmD06gO8GIg2G IKrNrbNQRoxliUG8BCSUItWFqyJYf5Xdk4JCXu/zeLh+LJ1DdvEVXHCKieA85x9mYc/oSSt+1Ej +f1KzkIFroVeRthUjEokTgguDIOON2o42CdnpdNRxqhsDFkbC4YyLGDJm+HPjVSfKy24 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: linux-rdma@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: 14005489 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 82E3F27E1CF for ; Thu, 6 Mar 2025 23:04:08 +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=1741302250; cv=none; b=H+5aNHvp5zwP6+isoIV08qvu1M5D1CTWP6mjlwPWMIpcj7IrAO9yXlhqKmN2ttfKw3/OIjsVI1ELaIMnFicH4FdZOfyYvax+eIsaokqzD9/AuhMkNANkxV9KdHCMMQGmhdwOih/NM9PcV6hwQAg7B5DxXRdGQRXH0yVJ7tv/fvg= 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.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="iHOUfJy/" Received: by mail-qv1-f53.google.com with SMTP id 6a1803df08f44-6e8fce04655so6484146d6.3 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=h5QD5vod+Ll/tK4Wq7+JCyfxqlmEMwOakoG3HToNt5uffMdQgov2ig1OTW72pvnQ5T ssydoUjzPaerVIbQW0Qwo10x2slnQWE6aIoqoqio5r/ArEHTsIkgqIHGPIOa25ETrEQF TmTXWbBP1vrb77Xp9ZnPOXV4nSINX6NzhNVhzGPYn6YfOpz8UgPJL5SSUwOW12bwA/MS XQY4Nb+KCv6wE1gXZGW8jK4YcubkCDGHvVSobB2rDPIBV7sgAKP2RimWXchVne1U9bh5 a3oywzwiuuc7FP7ppxEKxT/oa2DKgUYOkqwsmWjkW+F/Xzz7WH0qJz0bbDfGs8icSBJ7 7LJA== X-Forwarded-Encrypted: i=1; AJvYcCVxI6ZL9ZtB/x2lLeDVTl/9K6yuDJBbBp4SRyBIBP5wvmKPjZnZ3zeaoc7DY/g5FSEUOo3vp6noCB+s@vger.kernel.org X-Gm-Message-State: AOJu0YxHVQprLA1+JhClQDHfMC9jsZQSvBHNacr1k2pqSh7n3dpNGVeY npBY/+XHGhPJXnHbNdSTPDMYRg1yU6ZawP0Xn1DymKMc34p5kig0PT2vUBDKgk8= X-Gm-Gg: ASbGncuSRwcg7KjPTFKUDvq/Kggekf+Byh7Yd8+ayCwzp+2D+F5uNjKswR6GNAu8TDs Ei2FcucRVUpURIvZ+JrOhDGhLzvvWxOB5zg6+nFlwnooFWRAHmNOGOrTvy8A2e+5FFpFpeKIS38 TtNuG7MyqHUsIqIYCQfeCiqqyODPh3hFOfcqB7LoNAG9Nj3P7pFNdb/2AvnrqNYbWMOpEROaVlm Wgc1LdVB2KXAyvJu1kZraknu5Ekl5flWarLaPZTXlxoLwGkXXYHAaYU8lp0skobBo3R1fceu5nK uShsNFsItYBOskzPBOOFpg6Q+XME9CO+nBLghH+zelsiUAHbaHKUxWHiDSIXM7E0C2gX 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: linux-rdma@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: 14005490 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 A5E1E27EC6C for ; Thu, 6 Mar 2025 23:04:10 +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=1741302253; cv=none; b=nyn7JsihXzZvnUK55pQBTkwCIOsfgZYeB9/t5MpERW48x0WIT4hXAT/EywxVFbPPmNEElo47QpEC1/O+QWJ8WNIN1SkJuIYrgoQUBrx+KunRUe/aJqqygmVmfuj2/z/v9Fy/vyw+GQhDnmWjdCWlC4J085M2ZP/0MCbbOZ35NL4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302253; c=relaxed/simple; bh=rhAdls14aXXr+B3banKqLmvbLqUuZInVd88ZhCUc3TA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bqI9rPnmfd3cYZbVJQgEgJxUbUKuK5yrZEWJOBm80uAsaIgRV5S2YxaQMFjGvXofcvWtwFs6YeHBwRHjgBqbtQm0zw5yt4aCpdfCNwyBl6E3LaE8wfGPqKBiAM4XlCBSbpA3ZGpT6lyK2r6IKYtM2cJtUhqEfrcLtJIJ1bm+O04= 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=bDL6EARs; 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="bDL6EARs" Received: by mail-qv1-f51.google.com with SMTP id 6a1803df08f44-6e8f06e13a4so19127846d6.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=1741302249; x=1741907049; 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=bDL6EARsr9MPoZFIMmPRdekv7u7/QORpBvSUlXOzBaCRYM4JsFeEOpDGs/l+xGrMJs 1MqEfKVjlNt+RY6Y4b2J2kK69ZkSVNlB9uNDaKH26PfC4CExyReMBqwdOhYdeQ21QkX6 7izS8luE5js7BUurTn3fMmvU9qjSZh6OgcVdQaxN1Jgx2xP99rjZ/SlB17dD89EemA7l xPNTkKtkJoU0WrwRPLgPApcixNXSVtOveZDdGATgDc+uOmkTvTEPlme/xs3N9XqsNpnE vmrCFlTMI7ejL5z8AMMZHTViHVjnuXuYNA85RUbkxgBhLtnGmkkt0xL7Rp8OCnPlAOI2 uEIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741302249; x=1741907049; 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=Q1CkCzPx1lCYEfAB0GRQRhi7UNsY61s8xikwA9BjCV3UguYxrvWFAt9uEjZ0UTxNKM 1vVNPfXfWm0DsdlK095yNcH2013uHAyI55EHcLtaHxPsdGVp8XNq7PKf5b31FhGxqURn URxTvOMtzCrDGnZMfUwdlFWAHa+brbvtyf/jJT1QdkMwEph9vNevD/PXWtwDfQ5HSI3L 88gPl06YFCXfXyi3v35yR0QJje0fAbrRXfWFmGjPJdyBJLnWRt1Bkq6LK3AufHp5oQTV ht2vP91lkT3xrBUe+xUxnIggNJg3s7UnInTmQKzL6G2Hn9b1CgMZ95kGf8JWRfLCytN1 rkRg== X-Forwarded-Encrypted: i=1; AJvYcCXX2Jvv6sM2R7rUDRIexKlOibuVAuRB6ulOn90yDtByR9XNDc0TqIO6zm9+co7KZwCs3PjQE/icAHJJ@vger.kernel.org X-Gm-Message-State: AOJu0YyalHXUrTcKtNDm9x9cH42VoloFP+QHY5pFtsmTXcHYxUwqUMNl XKsYWoaXAnl8b3a5DgJprzDS1obQsnxH8+J0YpxGk9baq2JyW4WIwwYCgklJUVc= X-Gm-Gg: ASbGncu4uJIeRJu2xlwA24IKfLJzkUm8NsWyIHKVPiaeZIicBkdmNdz8rFozqtc3C/W XkyaRzuRW0GBGedGa3gfC13YrbEWpgz2Vs08unKqzwBsMuGo3XNXyCXVjNsUAhuMB/VKK6FSXZA 5hUMHXtWoCDtxdsdjJ/B0FtkQwv5TQHcV7IrrrfjyDgfMT+1QA4gxihsS/thRdhqn5D+vv14+F4 K9BVZUrxcPRmz9Uus16u28Vw7Jq58+v8JMcBDdqipaOszrWfjEknIhYFRShl3JzrWPjjSPCBEvE ufblElmPs87NEDZBI/sYMVKBKjP6NFEEx3bYlm/I79WkTp8BATkfBipCYn27NEEYRy8b 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: linux-rdma@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: 14005491 Received: from mail-qk1-f177.google.com (mail-qk1-f177.google.com [209.85.222.177]) (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 6ADBA27E1D4 for ; Thu, 6 Mar 2025 23:04:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302254; cv=none; b=kuPG4FCp9RQQLuGXFK/PQ/slqVIP3M2nr+ZYPHrmwlU3bV1vrP4ZS+mvcqoUhOexK8s29moaBYq4Gvd2VaJpFwpDnuLWOzn9tchoOob1tvoobeMuoUVhC7lWiAf4KB4SlVMOkwnB/Nred6BA258IecsNsB7aDZde4DOBffybIwE= 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.177 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-f177.google.com with SMTP id af79cd13be357-7c3b4c4b409so198116685a.3 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=qOZneV+LhXy0avmRb4az+cU9Yyi4uY9NOsCK2HzSWeurxIoNekEsqL5kqAnLrCL5Pa Ckis92P+9ihHRdVA0kq7uhVv28iFt5oHw1lvqn2QenlVi24d/f9NN1vTJHy6Xerky8Fa LcQ04/4nRVgIZogwtSeT+cE9xh00N1l8ZmvqAQce1AFGnsu0UPFmyR5npb8LGkLp/b47 peqct/zDVt+hNjWmUkuBanNWbxf4LC26KYm3NX7OslQ1YZ0e4+weZlwNJQk3VaWgd3/J MWxrkKEF7CBE+zWesAsO75SEcJFzp1t7Kp83UEfQRbU2H2hdQHIwRhEc57PfSTS0As2u 8jiQ== X-Forwarded-Encrypted: i=1; AJvYcCVXaV8GpQpSNeReMF0UlB+qwD6x5n34LvONHvd8a+AyEwAvhlv2U3YZRSUteLRDat5TM61VP8zIfb4B@vger.kernel.org X-Gm-Message-State: AOJu0YwwMLGGux/Q/mENtr5HvHN1TnYa1fH45o4rd2b7Hrpe84XLxkda oA72LPL9lwrsZ5fNdikTGMTmYyNuzZ3rzdk9wMG83BZVssCD6rOMNejTadSv7Z8= X-Gm-Gg: ASbGncuojCMpBMmBeylEHGsLGsPOATr31nIeAofDWpzL4PvXuxbwfBqjwTYWe7YccGl NbnvzvIRoCZo1Tv7BNpBXDb5wlOi0Zb7K8Yhp0L7e2z+xWMqJlvSVuH+Um7uaPpfCZZCCpiKnJL XZP2fTOuL9CwW2eufY6bs9Sc29MGQENqt+/sdddNVRPNLlNDshZCLM+7BOHMNhUPWdXBB/S2yrB 1ISE03o4DfshjbVCryUkKCSlAGCogSDPeTkwLmar2uSnNc7OOEAQcAz4OrXUkG6634nlYucvsip gBl+HvLQsuhbG04OqTwwNhkkv3cujKC16EqwbdSqtRqPZ+KdzwvyzTgTXDHory9xpaph 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: linux-rdma@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: 14005492 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 2566C27F4C5 for ; Thu, 6 Mar 2025 23:04:14 +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=1741302256; cv=none; b=iC3QBGfvp74whSyJBkc4/BxuF7p7NcFx6llNoh1BwY3IutseJ/7zDCPdb0F1+1BaCn3LPmYpLCOmqYo/fc8me/D0LZAbEB5jniadiOwtYm0oa1UhEjE7CaUarVOQbjQaT1Ql5CBMHwgm9sT+m/M9p2DUEPLQq1fwhbojAZlcLsE= 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.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="CBXZCyeB" Received: by mail-qv1-f47.google.com with SMTP id 6a1803df08f44-6e8fb8ad525so8225546d6.3 for ; Thu, 06 Mar 2025 15:04:13 -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=wvfwCMg9a7I1W9i0+jRlu3USnZpcdq13fV2WBK8FlidWAHzppifH5HAT4bwjDBxa+j ocHB72DrRncQWjcT4D0JkoPZFW1JIGmQcI7UC5O2dgbOCsc6jCbSRuHEG21kAes9j0Ji 34UHn3KW5BjIrUnpNwaXdXA+TbkHZ3TXv+V+fviQwnBNrH+W1GEn6YsBjw1ckl2JR5pp lysza6SPSfnyjRnHAG+qCR3UpZaSlCqHXUL0nbiOba7IetZoJI8NpHuKl2iwGNSJuLKS KueIItf26+QxvKxIMxFIXklNW5I9SfBkVjJoO4SQxxSfofzjXAS43rtaKWSJDksqXrGP V9iA== X-Forwarded-Encrypted: i=1; AJvYcCWEjbGrgh2xPoD2d9UMA97kdweO9iLEjNrKRT5CXScuGI5W/AWnKCgjM9e5iIxXxUe/Z1tqRQdqAKtY@vger.kernel.org X-Gm-Message-State: AOJu0Yz1azXThDoXJCiiWKvneBDwCINzUT+30Ao21ZuaImBTAuGx6yKn pvPWZPioGR5Vy9wPUyoSuBSy9l7EH+BjxgRt1V68qDFvmNeGyLH6FJbvmP/OVQ0= X-Gm-Gg: ASbGnctzit5HpMx1SVLxf8yd0SlNsY4B9FGywGSc3Azw9xgCtj61LL0v6SwqLnJUxKF q+PbIR5QEa83FftEZRv4vjqDNCnG+F6Na/jJmfktxs59ymsAyOZUDq/x7f3LxKgaYzjwU8u52Xa ecqFw6XwetANQbYKss6uRGYlEzJmR8UyuKk6w2gQSMf+JeJqhPhcvM2zHmyEqBqiaX4GpouSMrM JUIn0AwzBv9h5UY+NM/+lJpgkVoMzlFLF6KShz0l/nLoRIogxFvyEt0AYfjr9WK9F8B7/DO8yr/ spBEv67XQMyW53/bKV8Ef92PbToFs2z0yyzkst+IH0W2jhZfZoi4zQOZGTjyelcrtLCe 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: linux-rdma@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: 14005493 Received: from mail-qt1-f177.google.com (mail-qt1-f177.google.com [209.85.160.177]) (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 26CA827FE7F for ; Thu, 6 Mar 2025 23:04:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302258; cv=none; b=CPpI4IukJ2ttjPmYMXC288lFQvn4a1lVn3StRZPooFvdTWOvyFKFn/ZspGVmFxKzw6r+oad+gQTr5H13+DVqrfDhbbtMz+v0aT4lnI84SHOnJqgq7lwo+KFcMxx37C4kGyTILsOaXuMtNznmo0xG8+630zJUE/51Mgy8YBmLJ4o= 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.160.177 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-qt1-f177.google.com with SMTP id d75a77b69052e-4750ca77d47so10057031cf.0 for ; Thu, 06 Mar 2025 15:04:15 -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=TIGjlYYgFwR1Y36fztSOIeWthK/3zQ6Nmq5wFkgQG0ipWRfkU1UuWIs7rBy8wVSBqc nDqZVASeOmFEFqnjH+c6gTkHdhoSmzQq4nm4l/c0OfdghjhkIlgxlDzzOnFsozKwGCXq GZS95DHQTJfMx7VM/3XBtBosXwF5OHmCsSmsXF458NDZbYcTc5xEfPHrdlpKZ1vynE3C iNoI71oHNJT54NX2kn+FPSqcltBUVLu8K/hrtk8lUsf5eIn04k3xYzkV4DGMQaotnA7j hfe7Mjm6DhQimCWqbk0GKzbDNFsesHCOCQdLtjL4RtWRE/w2+1ZieyPSI7PgAA/Gpypy B9fg== X-Forwarded-Encrypted: i=1; AJvYcCXNyWiN6SbgRfB1mj4TpeuD27jLJKukhuZ5idJaS2Lk5/ewgh1u6GkMWOegLBZ8D57copB3fFpdX33n@vger.kernel.org X-Gm-Message-State: AOJu0YyoD9VH9LtpUUwhMCfSgGLSlnFte5lUN8xf51emQY33Ar2FpJoJ 8KhOzHwCSxG9w3Wh1tM7wwBsVmWhLh3NsMUgj+Szrs4x3/53rFrIR2of2QpFLqk= X-Gm-Gg: ASbGnctiy1WN/5Co+toY+t+5B9i538yuaBoAXdkEi7Y0jLE/rwJXLzK2f/UeAteuLn5 4WzskVXFR6wTmBWSG9UW2sDtEMdEYvxglQb/SwVXr81XhQUuA328PcqBNi95Lw18sTkdyc2Lgyp Koo3vho/v/ua+eUCyp5Ts48nCTeS8VTDbJZkQ+y2K4uWpcxkQmHFBeH/48QjC2bcMFYVEi92YKJ RvF6wZObFMHzIm2kgENyJlwOtkRpogmGx+ywab7O5HaXmKBeHmB8S8MmymIczW76HumPiGZXKbZ ntQz7ZE5+mnTQOydnGIsRY5yJUfx9l+cPM6uXdEi8E9s/ZWU9ed0GHNHhAIEQLQqHn5d 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: linux-rdma@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: 14005494 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 BB61C2803F6 for ; Thu, 6 Mar 2025 23:04:17 +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=1741302259; cv=none; b=kypLc2B2XImWauF5nlPrD9QCeSD9uAbhmFXUTU7NTnBHY+bAP3k2YwlUdPk2fI2gtCzinJocSm7MZqmliOqFnkC97MBmXEe/UFIvtuRKG27anYZm5sji7biKJkVk5yrRda1dOtVpll6QX56mWeW9HhpzwTO4e5BjTead/c5OcGc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302259; c=relaxed/simple; bh=8zoJVMPNc2FcN+4s7xjapXpTwku8ERNAOulLVuTwkis=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=N7Lyk2WkSHY2v3aVJCG6ia0k5ngkXfeJFGEd6n7lTJuV6ND6NQASX4Jij7fsIOx3TjYHSmgCHhw2YNot2UkMf7lTRfu1iA232vvP8m9TYPKbSqTmYiH7p8RUdfflpZgLQRFvk9RfYPCEfzTYRvER/6oEGSMdx9eyJrl+hCPN+HI= 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.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="S7PASkt1" Received: by mail-qv1-f46.google.com with SMTP id 6a1803df08f44-6e41e17645dso11440196d6.2 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=UODweZGG1j08uONCtdmFoQCWWOk+FMy+Lbr8AuP5s6eOWwwuFv5ydf/aVxzxVa5heX hFwe3/S+GNtvf4zZbHkLXb/DQCQqDpAynvAhIyL7T2IeX+qq5Yp3zWhoITqi3RCrtLuL Ju6TvaMbNWTnct2NTEI4RfbfBGz2Fthqgwm+hgMP7tXzvkmog23V9rf1qvzklurQ9B9B 27D1gHBOXIzaepQyX2X3kSjMzvr7TCDbSjajZb+STWZ2jx7p1WvFedzKOUfBvuGpG5pQ 3t9C/MvG3LsIw25tDpuMyfhlMkOLuczuNB9UCBzpe5pKMC6vrUdHLCfaWIXTHpC3N63V KImw== X-Forwarded-Encrypted: i=1; AJvYcCWkq+9/wOyKvpHgLvSzfOa8pB6wjG2b2PuoyXHSUEUXTWMU4NyKNbCJNUOO6gxF0+jfkjLK/AB5LDxK@vger.kernel.org X-Gm-Message-State: AOJu0YxZwuk5lYtQ8wLUe8AIIul4lF6xOERYMzFkZOJiLo2iCdRlTiVG Kr+yPCe4RRUYWeQzJjMHDSOkMqWBe0hpsRiffK6GY415CbQpwbShn8C7+BXOPA8= X-Gm-Gg: ASbGncsTc8QDDd5DQLN9zdCH/1F+pffLhsaBWvbCTFsJNvP3a70eSRlPJf5CCKx8ttZ bSkGPsj1vKPQ+ijJwjR/Q4fgo7QXd7K3C5rjLnbpO5jc57/SpmYHEFcVsHTbJ5Yf2I53NktHYtq KBFbRzRc2nbNr9tiA2DOm8O0Cnc1JZdSZItxicGEeoMAmsceFdsLu1yaVG5OMhAPH7phqlzWpLl bncV6dlh9q60pDpIMyXMW9RivkbFf0lJ9iChfeVGvEyLZbytBxKlHrx/gPptGVdbZrnT6EKzXSG h79cvd8i5mT0kc/7SuIb70+LtdVWoBrHUCiERJOOWhuCpPVodcuSYC5qb/pHNyA2JjIz 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: linux-rdma@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: 14005495 Received: from mail-qk1-f169.google.com (mail-qk1-f169.google.com [209.85.222.169]) (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 9A273280A35 for ; Thu, 6 Mar 2025 23:04:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302262; cv=none; b=AHIJ+cy3uqsgMwo0rUzADBC3D3wmGZF1poSc5t29V0EJ/mtQfG+JLVAx3Kf6gZVxeWPGYb2aStqgFxgtCPoxFhlzLQxFmzNfT8igTOkC+x089KzsJc1M6mcsrNlxvAg/2KqToIjLOUxOxb+2BNemOJ6TH9NvlXciAbuNpE0RLy8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302262; c=relaxed/simple; bh=yndAeAn2xqhE/kdxFO1U65LUqw0DkYwAykXl65heU9E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZHAmLcVZ0HEJ0NhiAhttz+rp7F0D59v9Lij13pOHj4rSmN+u7L8GIFPhiQog5U4DBFo6axuTo9smL1lyxzTcvROnnPS+8lkizTSNGjqr0nCNxVXd4tq7OrUPAaCfvge7AoHGX9Yvhv7KfaN9p/nE1dH/HK4rJutVXk171SCk4W8= 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.222.169 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-qk1-f169.google.com with SMTP id af79cd13be357-7c3d591e50aso133957585a.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=HJ9xnnWFwqyalEIQGgS8KKpoj1qz+8BNtEiJpHDo25QFPF5xjU3/MKOdzauwtARW8B m8qJG7O68ioMPVPVwK1KdVBL6heps1hHIqLqISvwMkuDfGf9W6BKzagIRfShegVRrzgY T+KoEeJezoxJHRYiXhJAh5VXlR0CLz9WVHF4dtgnHPcZZjKZFAU/XSJXiYu5dwRFtbfd cf/ZHxhrivMp7uRW+GR68yDpjMBJW6EO6RBBZjyReemgaXDD+WWw8xJrXJ5L8pMbqZf+ 8KKA/TTNzKvU75jt5KJQnAvu01xKiiUGt4kUmKudUD6GZjQKNqNkKicjcQWKZeWaBHza SkGw== X-Forwarded-Encrypted: i=1; AJvYcCUAOqN3n3KIrmeYXaBrl7SxUpGQuKkwlcUGPv4PBTKqzx3lznwqwcIvZqMVjqRPUNTGKodDPDkfR1Dp@vger.kernel.org X-Gm-Message-State: AOJu0YwD3mX/n/OgZ0Di2O4XKEkr6t1nqDq3VC4YSqUkMiJQl/YghsI1 kycmJlnEFlw65SAACEsGDT94WO/dnbojVeCKk7FSwEB+28R1v5Ufa6bz3y5rSbg= X-Gm-Gg: ASbGncsSmt+XgZ8gKXeDSlfi4Z+sjBD6c5umgZjAG2huYU68ykhLizAIAHWXFKtUb3O r99ytl1zTB51M+iIif7dsJ2eUKOo7dkarxaaQl0sdkzA6JHenbDQn8NWofUQXmEc2Dt4drvAyn3 tpzyq7i1qmeiyF+whuTpFCeqTGjO+nv4a8xSCir5kddUuR1w8bpKRF3x8G2U2HWNnVg73FYg+Jd Wut5UzGKS6ULDQ4xHIbGfvp8K8t62USqNjwhKd6IBxa+WfsH2tso0F3XGurVYdJleIlTJ2xv3Ou ZBAiV/j1/kgBvLnFvbAkwl1pLhfwtds5GPI+Mi0nNgqW/qkzQ/SIy0b+fmMt5HkspFVw 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: linux-rdma@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: 14005496 Received: from mail-qk1-f171.google.com (mail-qk1-f171.google.com [209.85.222.171]) (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 6CC862803FD for ; Thu, 6 Mar 2025 23:04:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741302263; cv=none; b=nTNXUPjA8s19OAejXeEAKsvx7bA0NfkkDWRe0TTskoHJPVyfCM958oQgv8SUkq1ZgX7jQWNdlybrVx6ns6h+k+u8eEBJa9XLZnn0qVf8TTlQI7BzW0MTzL8bUfSkf2IMlV01s6tS/MXA0yck6OHTrKRS0q07l/j9ikcLfhv0ii8= 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.222.171 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-qk1-f171.google.com with SMTP id af79cd13be357-7c08fc20194so216440385a.2 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=wXO9uvP/uU4eODjM+m3bXrt62SJ2Wam+qr9VIyWuh3Dib03rAeAfkQNIX1/WXw3dSO E3BZMGxTB122jmpPMc3HZM+Sk1aPkQX3ma8d3wY6FlFZ1w1alb2hiVfTujKVqWinC9b+ oKF3eqfvaPPjJapyfLZpFOu62ulq2p4ZcSN2/l0yPMmJMiCEnrgO6nIRzOyMSR9naGx1 bqGcDyTRtJc1vdsL71GsN/uqXn5K6Rdg0QOteFylWiXI+dsoiP+108dbTfAFGeaA0rdo gPHJvwDiFbEIc2PQRDlPle1C0GVxsH3LPCD0lkqGAoyhMsPNN/SnaulLOtjObvv6SVic U9KA== X-Forwarded-Encrypted: i=1; AJvYcCVIChBhI7uVen68X2SIZB/PXRTcUQ4Xc4aO+BUucjs1zmAFBwDvW7VisCUUB85M9UypDCYTwOMW3mCs@vger.kernel.org X-Gm-Message-State: AOJu0YwsRaITE3gTsRM8HVvBxznYOO3rcBecZXWdgHn6Jf3J6CaPvWHT MxaUfKao8J78pGFI/LgqDINplJxyyz7qy3tniuM8poyQ6orckR90nzFErTBzJ74= X-Gm-Gg: ASbGnctQJF0hRZYqDyLwXp6Qrlad3fe1I6GjBVUy0SnjNHhJtXjJFK4yCnl1JT+/UAC 75hd//xA6jiZI8lGmQ5LyFIHFn7H4CFUTXz7XNpl0jbeoC4SXqyTH8r4ubuzepEZM9CzNc/otXU iv/qas8ZLD5Qgq1rgDyymYr/ypRQBQgtbVicdF8f4u8rPv7ZWq6V6nricdEEYsxqWNTyL/iigX2 hCjTnMZ5kZXadv0e3eqhCtRfIAojzpvE40S7MMeoLWU9w7QPJJtdvCU2k8TMGrD46sAVcEI2HjZ ZvMz7mbm1sqp59zuuHdJ5FVx/9c/xkFVry+OstE0Jx8zbJd8pQCKEKGq/ubMNY9cAMhN 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: linux-rdma@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: 14005497 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 3B2C8280A4D for ; Thu, 6 Mar 2025 23:04:22 +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=1741302265; cv=none; b=TwVmuBqAEMj6lzI5oKY05BtQ8Zx4nnQvXa+Q5+3tak5S7jJEyNeLIE+95C6UhL7y4Oq5OYFgjOqO5CLdzqD92zkX+EzXIboOE121MQK0jd0vURQZ1iKeRVSISfe8s8G03jfunkkLOwm2YCqNjy9PVqRfyE4+wYg5Db5rl31+yOY= 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.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="hUCnDA17" Received: by mail-qv1-f50.google.com with SMTP id 6a1803df08f44-6e8fd49b85eso9621396d6.0 for ; Thu, 06 Mar 2025 15:04:22 -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=WkuYlmrfT9/vOeIO5N6/Fdhu7TWEI/JIDTgGD4ChiActckgp0w+OaRKkDSQ90aVG2z jsKbkdhRIEJLKBHgY4rRdAuBM27x4nLmS6Gkjt2yUK+XGwIfujae/eUa1Z9WPyrU8jwf gxgNx/pL/kp0e2kzgMpUVwlRMkkERGI4oNjV1seFLADcsaf18BfQ0LzlPzsDmPH1LQyb tmBMxo7LSdRLL2I0VZP7jGw0j+4lsUZcHVRxaz067CpYe9Itq5v6NEyxhE3e2Zzh5csG U+UvsS+F/fcMzXzlxYiMNqEx0DDfk6OPfdG4vyzEvo/rcLLPAWQuzuJQ9P0Z4tsHsuvg /oQw== X-Forwarded-Encrypted: i=1; AJvYcCWuiR/G7HS9Y3KvnqAaBwxClriFdyqhBD5/4/QwCjmbreZ0eIheKNovnvrIyQNLHQCtid+WU8bxv/z7@vger.kernel.org X-Gm-Message-State: AOJu0YzJvLLTjQfquSVTz6oTzb3u1V6bw6PaJingEc6yT1cqrJARGIbg UZL7rwW3TLzh0dls08CI17j+MNj9nbzUJAAFiIWk2IKvbzuuBQUZNPAdklkt+pdAWUC3MhqQkdN n X-Gm-Gg: ASbGncsMzAHGKhp5pmS8nlCNqnvJBoDeBbtKAwDA2IkuDLolJ8qie13rL10PFPaQr0J kI/ohel40AIAxoEshztyUoV2hXTNkNKWD4kl8nFqG+dlDXL+aCi2bDZkbBWGu66rYX4YujksDK6 hEKWxN5RoJD9yEAyAIzQRQlXVsVLD6amHeNZZKh8G3U+PRzNFrkXct2REoSTLLtEjGsYgkssJNw I2BgeBES6/C45pC+8v45kDehg1LyN+AYqP+nFizKYTfFi8WKOvsiqsgmUfkI94U0QwLjWFwSzZa avZ5DjpK1mHH/R/RdQ2zY5r6/6+bcI2ZP1lCKWNQHPB5Te2fs4p8qeZ0d7eeW3IYG5CW 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: linux-rdma@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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)