All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sabrina Dubroca <sd@queasysnail.net>
To: kuba@kernel.org, Rishikesh Jethwani <rjethwani@purestorage.com>
Cc: netdev@vger.kernel.org, saeedm@nvidia.com, tariqt@nvidia.com,
	mbloch@nvidia.com, borisp@nvidia.com, john.fastabend@gmail.com,
	davem@davemloft.net, pabeni@redhat.com, edumazet@google.com,
	leon@kernel.org
Subject: Re: [PATCH v12 6/6] selftests: net: add TLS hardware offload test
Date: Wed, 8 Apr 2026 18:45:53 +0200	[thread overview]
Message-ID: <adaGQRUUNbXWXNgP@krikkit> (raw)
In-Reply-To: <20260402235511.664801-7-rjethwani@purestorage.com>

@Jakub [top-posting so you don't have to scroll through the rest of my
comments to find some global questions about this patch]

tools/testing/selftests/drivers/net/README.rst mentions "Local
host is the DUT", but this test does rekeys on both sides and sends a
bit of traffic back and forth. Is that acceptable?

Another thought: is there a "standard" for stdout vs stderr, as well as
verbosity of "test progress"/"debug" type messages ("sent
keyupdate"/"received keyupdate"/"server listening"/"setup complete"
etc) for those test programs? Any expectation for a --{debug,verbose}
option to only display all this stuff on request?

Output for 1 test:
-------- 8< --------
TLS Version: TLS 1.3
Cipher: AES-GCM-128
Buffer size: 16384
Connecting to 192.168.13.1:4433...
Connected!
Installing TLS_TX AES-GCM-128 gen 0...
TLS_TX AES-GCM-128 gen 0 installed
Installing TLS_RX AES-GCM-128 gen 0...
TLS_RX AES-GCM-128 gen 0 installed
TLS setup complete.
Sending 100 messages of 16384 bytes...
Sent 16384 bytes (iteration 1)
Received echo 16384 bytes (ok)
[...repeated]
Sent 16384 bytes (iteration 100)
Received echo 16384 bytes (ok)
-------- 8< --------

With some rekeys I get 300L of output on each side.


If not, I guess we can fall back to what makes the most sense for
NIPA?



2026-04-02, 17:55:11 -0600, Rishikesh Jethwani wrote:
> diff --git a/tools/testing/selftests/drivers/net/hw/tls_hw_offload.c b/tools/testing/selftests/drivers/net/hw/tls_hw_offload.c
> new file mode 100644
> index 000000000000..788891890ec8
> --- /dev/null
> +++ b/tools/testing/selftests/drivers/net/hw/tls_hw_offload.c

I think it would make sense to add the new files to the
"NETWORKING [TLS]" entry in MAINTAINERS. We already have the existing
selftest listed.

[...]
> +#define TEST_ITERATIONS	100
> +#define MAX_REKEYS	99

Making TEST_ITERATIONS a test argument would allow a test that lasts
more than half a second. Then MAX_REKEYS can be removed and the
argument validation switched to num_rekeys < num_iterations. (doing
rekeys without a send() in between [other than the send_keyupdate]
should be fine, but it makes the logic for "do we send a rekey and/or
application_data this round?" more complex, so let's keep the check on
num_rekeys)

In general, this test is a good start, but it doesn't cover enough
(see my reply to 5/6). How did you test the "unacked records" part of
the rekey patch? It's the most complex part of the series.


[...]
> +static void derive_key_fields(unsigned char *key, int key_size,
> +			      unsigned char *iv, int iv_size,
> +			      unsigned char *salt, int salt_size,
> +			      unsigned char *rec_seq, int rec_seq_size,
> +			      int generation)
> +{
> +	unsigned char pattern;
> +	int i;
> +
> +	if (generation == 0)
> +		return;
> +
> +	pattern = (unsigned char)((generation * 0x1B) ^ 0x63);
> +	for (i = 0; i < key_size; i++) {
> +		key[i] ^= pattern;
> +		pattern = (pattern << 1) | (pattern >> 7);
> +	}
> +
> +	pattern = (unsigned char)((generation * 0x2D) ^ 0x7C);
> +	for (i = 0; i < iv_size; i++) {
> +		iv[i] ^= pattern;
> +		pattern = (pattern << 1) | (pattern >> 7);
> +	}
> +
> +	for (i = 0; i < salt_size; i++)
> +		salt[i] ^= (unsigned char)(generation & 0xFF);
> +
> +	memset(rec_seq, 0, rec_seq_size);
> +}

This isn't wrong (so I'm not requesting to change it), but it seems
way overkill for "we want to fill tls12_crypto_info_aes_gcm_* with
some predictable data based only on key_generation".


> +/* Send TLS 1.3 KeyUpdate handshake message */
> +static int send_tls_key_update(int fd, int request_update)
> +{
> +	char cmsg_buf[CMSG_SPACE(sizeof(unsigned char))];
> +	unsigned char key_update_msg[5];
> +	struct msghdr msg = {0};
> +	struct cmsghdr *cmsg;
> +	struct iovec iov;
> +
> +	key_update_msg[0] = TLS_HANDSHAKE_KEY_UPDATE;
> +	key_update_msg[1] = 0;
> +	key_update_msg[2] = 0;
> +	key_update_msg[3] = 1;
> +	key_update_msg[4] = request_update ? KEY_UPDATE_REQUESTED
> +					   : KEY_UPDATE_NOT_REQUESTED;

I'm still really not convinced we need to bother with things that
would only affect a "proper" userspace.

[...]
> +static int validate_keyupdate(const char *buf, int len)
> +{
> +	if (len != 5) {
> +		printf("KeyUpdate: expected 5 bytes, got %d\n", len);
> +		return -1;
> +	}
> +
> +	if ((unsigned char)buf[0] != TLS_HANDSHAKE_KEY_UPDATE) {
> +		printf("Expected KeyUpdate (0x%02x), got 0x%02x\n",
> +		       TLS_HANDSHAKE_KEY_UPDATE, (unsigned char)buf[0]);
> +		return -1;
> +	}
> +
> +	if (buf[1] != 0 || buf[2] != 0 || buf[3] != 1) {
> +		printf("KeyUpdate: bad length field %02x%02x%02x\n",
> +		       (unsigned char)buf[1], (unsigned char)buf[2],
> +		       (unsigned char)buf[3]);
> +		return -1;
> +	}

And same here.

> +	if ((unsigned char)buf[4] != KEY_UPDATE_NOT_REQUESTED &&
> +	    (unsigned char)buf[4] != KEY_UPDATE_REQUESTED) {
> +		printf("KeyUpdate: invalid request_update value %u\n",
> +		       (unsigned char)buf[4]);
> +		return -1;
> +	}

And here.

What type of issue do you expect to identify by validating the
contents of the key update message that your test program is sending
to itself?


> +	printf("Received TLS KeyUpdate (request_update=%u)\n",
> +	       (unsigned char)buf[4]);
> +	return 0;
> +}
> +

...
> +static int do_client(void)
> +{
> +	char *buf = NULL, *echo_buf = NULL;
> +	int max_size, rekey_interval;
> +	ssize_t echo_total, echo_n;
> +	int csk = -1, ret, i, j;
> +	struct sockaddr_in sa;
> +	int test_result = -1;
> +	int current_gen = 0;
> +	int next_rekey_at;
> +	ssize_t n;
> +
> +	if (!server_ip) {
> +		printf("ERROR: Client requires -s <ip> option\n");
> +		return -1;
> +	}
> +
> +	max_size = random_size_max > 0 ? random_size_max : send_size;
> +	if (max_size < MIN_BUF_SIZE)
> +		max_size = MIN_BUF_SIZE;
> +	buf = malloc(max_size);
> +	echo_buf = malloc(max_size);
> +	if (!buf || !echo_buf) {
> +		printf("failed to allocate buffers\n");
> +		goto out;
> +	}
> +
> +	csk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
> +	if (csk < 0) {
> +		printf("failed to create socket: %s\n", strerror(errno));

Those failures (malloc, socket, connect, maybe also initial key setup)
could use a common prefix (maybe "SETUP ERROR") to differentate them
from "invalid arguments" and "actual test failure".


[...]
> +	rekey_interval = TEST_ITERATIONS / (num_rekeys + 1);
> +	if (rekey_interval < 1)
> +		rekey_interval = 1;

nit: should never happen since num_rekeys < TEST_ITERATIONS

> +	next_rekey_at = rekey_interval;
> +
> +	for (i = 0; i < TEST_ITERATIONS; i++) {

nit: i itself is never used, only i+1, so iterating from 1 up to
i <= TEST_ITERATIONS would be a tiny bit more readable.

> +		int this_size;
> +
> +		if (random_size_max > 0)
> +			this_size = (rand() % random_size_max) + 1;
> +		else
> +			this_size = send_size;
> +
> +		for (j = 0; j < this_size; j++)
> +			buf[j] = rand() & 0xFF;
> +
> +		n = send(csk, buf, this_size, 0);
> +		if (n != this_size) {
> +			printf("FAIL: send failed: %s\n", strerror(errno));

The test failures messages in the client consistently use "FAIL:" as a
prefix...

[...]
> +static int do_server(void)
> +{
[...]
> +	/* Main receive loop */
> +	while (1) {
[...]
> +			printf("recv failed: %s\n", strerror(errno));
[...]
> +				printf("Failed to send KeyUpdate\n");
[...]
> +				printf("Echo send failed: %s\n",
> +				       strerror(errno));

...but not in the server.


[...]
> +int main(int argc, char *argv[])
> +{
[...]
> +	if (tls_version == TLS_1_2_VERSION && num_rekeys) {
> +		printf("ERROR: TLS 1.2 does not support rekey\n");
> +		return -1;
> +	}

Maybe also a check to make setting random_size_max incompatible with
setting send_size. And probably at least a warning when client-only
options (server_ip, random_size, num_rekeys) are passed to the server
and will be ignored.

The "Client requires -s <ip> option" check would also fit better here,
with the rest of the options checking.



> diff --git a/tools/testing/selftests/drivers/net/hw/tls_hw_offload.py b/tools/testing/selftests/drivers/net/hw/tls_hw_offload.py
> new file mode 100755
> index 000000000000..66c5ddfd8125
> --- /dev/null
> +++ b/tools/testing/selftests/drivers/net/hw/tls_hw_offload.py
[...]
> +def verify_tls_counters(stats_before, stats_after, expected_rekeys, is_server):

This is much cleaner now, thanks.


> +def run_tls_test(cfg, cipher="128", tls_version="1.3", rekey=0, buffer_size=None, random_max=None):
> +    port = rand_port()
> +    send_size = random_max or buffer_size
> +
> +    server_args = f"{cfg.bin_remote} server -p {port} -c {cipher} -v {tls_version}"

These variables were called {server,client}_cmd in the previous
version, I wonder why you renamed them to something less accurate
(since it's actually the full command, not just the arguments).

> +    if send_size:
> +        server_args += f" -b {send_size}"
> +
> +    client_args = (f"{cfg.bin_local} client -s {cfg.remote_addr_v['4']} "
> +                   f"-p {port} -c {cipher} -v {tls_version}")
> +    if rekey:
> +        client_args += f" -k {rekey}"
> +    if random_max:
> +        client_args += f" -r {random_max}"
> +    elif send_size:
> +        client_args += f" -b {send_size}"

nit: I find the use of send_size here (instead of directly
buffer_size) slightly confusing, since we just took care of
"random_max was set".

-- 
Sabrina

  reply	other threads:[~2026-04-08 16:45 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-02 23:55 [PATCH net-next v12 0/6] tls: Add TLS 1.3 hardware offload support Rishikesh Jethwani
2026-04-02 23:55 ` [PATCH v12 1/6] net: tls: reject TLS 1.3 offload in chcr_ktls and nfp drivers Rishikesh Jethwani
2026-04-02 23:55 ` [PATCH v12 2/6] net/mlx5e: add TLS 1.3 hardware offload support Rishikesh Jethwani
2026-04-02 23:55 ` [PATCH v12 3/6] tls: " Rishikesh Jethwani
2026-04-02 23:55 ` [PATCH v12 4/6] tls: split tls_set_sw_offload into init and finalize stages Rishikesh Jethwani
2026-04-02 23:55 ` [PATCH v12 5/6] tls: add hardware offload key update support Rishikesh Jethwani
2026-04-06 20:59   ` Sabrina Dubroca
2026-04-09 17:46     ` Rishikesh Jethwani
2026-04-10 13:25       ` Sabrina Dubroca
2026-04-02 23:55 ` [PATCH v12 6/6] selftests: net: add TLS hardware offload test Rishikesh Jethwani
2026-04-08 16:45   ` Sabrina Dubroca [this message]
2026-04-08 17:44     ` Jakub Kicinski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=adaGQRUUNbXWXNgP@krikkit \
    --to=sd@queasysnail.net \
    --cc=borisp@nvidia.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=john.fastabend@gmail.com \
    --cc=kuba@kernel.org \
    --cc=leon@kernel.org \
    --cc=mbloch@nvidia.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=rjethwani@purestorage.com \
    --cc=saeedm@nvidia.com \
    --cc=tariqt@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.