public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: Stefano Brivio <sbrivio@redhat.com>
To: passt-dev@passt.top
Cc: Laurent Vivier <lvivier@redhat.com>,
	David Gibson <david@gibson.dropbear.id.au>
Subject: Re: [PATCH 7/7] Introduce passt-repair
Date: Tue, 28 Jan 2025 00:31:33 +0100	[thread overview]
Message-ID: <20250128003133.19011f58@elisabeth> (raw)
In-Reply-To: <20250127231532.672363-8-sbrivio@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 540 bytes --]

On Tue, 28 Jan 2025 00:15:32 +0100
Stefano Brivio <sbrivio@redhat.com> wrote:

> A privileged helper to set/clear TCP_REPAIR on sockets on behalf of
> passt. Not used yet.

...but tested against source.c / target.c, attached.

---

$ nc -l 9996

---

$ ./source 127.0.0.1 9996 9898 /tmp/repair.sock
sending sequence: 3244673313
receiving sequence: 2250449386

---

# ./passt-repair /tmp/repair.sock

---

$ strace ./target 127.0.0.1 9996 9898 /tmp/repair.sock 3244673313 2250449386

---

# ./passt-repair /tmp/repair.sock

---

-- 
Stefano

[-- Attachment #2: source.c --]
[-- Type: text/x-c++src, Size: 2368 bytes --]

#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/tcp.h>

int main(int argc, char **argv)
{
	struct sockaddr_in a = { AF_INET, htons(atoi(argv[3])), { 0 }, { 0 } };
	struct addrinfo hints = { 0, AF_UNSPEC, SOCK_STREAM, 0, 0,
				  NULL, NULL, NULL };
	struct sockaddr_un a_helper = { AF_UNIX, { 0 } };
	int cmd, seq, s, s_helper;
	struct iovec iov = { &cmd, sizeof(cmd) };
	char buf[CMSG_SPACE(sizeof(int))];
	struct msghdr msg = { NULL, 0, &iov, 1, buf, sizeof(buf), 0 };
	struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
	socklen_t seqlen = sizeof(int);
	struct addrinfo *r;

	(void)argc;

	if (argc != 5) {
		fprintf(stderr, "%s DST_ADDR DST_PORT SRC_PORT HELPER_PATH\n",
			argv[0]);
		return -1;
	}

	strcpy(a_helper.sun_path, argv[4]);
	getaddrinfo(argv[1], argv[2], &hints, &r);

	/* Connect socket to server and send some data */
	s = socket(r->ai_family, SOCK_STREAM, IPPROTO_TCP);
	setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &((int){ 1 }), sizeof(int));
	bind(s, (struct sockaddr *)&a, sizeof(a));
	connect(s, r->ai_addr, r->ai_addrlen);
	send(s, "before migration\n", sizeof("before migration\n"), 0);

	/* Wait for helper */
	s_helper = socket(AF_UNIX, SOCK_STREAM, 0);
	unlink(a_helper.sun_path);
	bind(s_helper, (struct sockaddr *)&a_helper, sizeof(a_helper));
	listen(s_helper, 1);
	s_helper = accept(s_helper, NULL, NULL);

	/* Set up message for helper, with socket */
	cmsg->cmsg_level = SOL_SOCKET;
	cmsg->cmsg_type = SCM_RIGHTS;
	cmsg->cmsg_len = CMSG_LEN(sizeof(int));
	memcpy(CMSG_DATA(cmsg), &s, sizeof(s));

	/* Send command to helper: turn repair mode on, wait for reply */
	cmd = TCP_REPAIR_ON;
	sendmsg(s_helper, &msg, 0);
	recv(s_helper, &((int){ 0 }), 1, 0);

	/* Terminate helper */
	cmd = INT_MAX;
	sendmsg(s_helper, &msg, 0);

	/* Get sending sequence */
	seq = TCP_SEND_QUEUE;
	setsockopt(s, SOL_TCP, TCP_REPAIR_QUEUE, &seq, sizeof(seq));
	getsockopt(s, SOL_TCP, TCP_QUEUE_SEQ, &seq, &seqlen);
	fprintf(stdout, "sending sequence: %u\n", seq);

	/* Get receiving sequence */
	seq = TCP_RECV_QUEUE;
	setsockopt(s, SOL_TCP, TCP_REPAIR_QUEUE, &seq, sizeof(seq));
	getsockopt(s, SOL_TCP, TCP_QUEUE_SEQ, &seq, &seqlen);
	fprintf(stdout, "receiving sequence: %u\n", seq);
}

[-- Attachment #3: target.c --]
[-- Type: text/x-c++src, Size: 2550 bytes --]

#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/tcp.h>

int main(int argc, char **argv)
{
	struct sockaddr_in a = { AF_INET, htons(atoi(argv[3])), { 0 }, { 0 } };
	struct addrinfo hints = { 0, AF_UNSPEC, SOCK_STREAM, 0, 0,
				  NULL, NULL, NULL };
	struct sockaddr_un a_helper = { AF_UNIX, { 0 } };
	int cmd, s, s_helper, seq;
	struct iovec iov = { &cmd, sizeof(cmd) };
	char buf[CMSG_SPACE(sizeof(int))];
	struct msghdr msg = { NULL, 0, &iov, 1, buf, sizeof(buf), 0 };
	struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
	struct addrinfo *r;

	(void)argc;

	strcpy(a_helper.sun_path, argv[4]);
	getaddrinfo(argv[1], argv[2], &hints, &r);

	if (argc != 7) {
		fprintf(stderr,
			"%s DST_ADDR DST_PORT SRC_PORT HELPER_PATH SSEQ RSEQ\n",
			argv[0]);
		return -1;
	}

	/* Prepare socket, bind to source port */
	s = socket(r->ai_family, SOCK_STREAM, IPPROTO_TCP);
	setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &((int){ 1 }), sizeof(int));
	bind(s, (struct sockaddr *)&a, sizeof(a));

	/* Wait for helper */
	s_helper = socket(AF_UNIX, SOCK_STREAM, 0);
	unlink(a_helper.sun_path);
	bind(s_helper, (struct sockaddr *)&a_helper, sizeof(a_helper));
	listen(s_helper, 1);
	s_helper = accept(s_helper, NULL, NULL);

	/* Set up message for helper, with socket */
	cmsg->cmsg_level = SOL_SOCKET;
	cmsg->cmsg_type = SCM_RIGHTS;
	cmsg->cmsg_len = CMSG_LEN(sizeof(int));
	memcpy(CMSG_DATA(cmsg), &s, sizeof(s));

	/* Send command to helper: turn repair mode on, wait for reply */
	cmd = TCP_REPAIR_ON;
	sendmsg(s_helper, &msg, 0);
	recv(s_helper, &((int){ 0 }), 1, 0);

	/* Set sending sequence */
	seq = TCP_SEND_QUEUE;
	setsockopt(s, SOL_TCP, TCP_REPAIR_QUEUE, &seq, sizeof(seq));
	seq = atoi(argv[5]);
	setsockopt(s, SOL_TCP, TCP_QUEUE_SEQ, &seq, sizeof(seq));

	/* Set receiving sequence */
	seq = TCP_RECV_QUEUE;
	setsockopt(s, SOL_TCP, TCP_REPAIR_QUEUE, &seq, sizeof(seq));
	seq = atoi(argv[6]);
	setsockopt(s, SOL_TCP, TCP_QUEUE_SEQ, &seq, sizeof(seq));

	/* Connect setting kernel state only, without actual SYN / handshake */
	connect(s, r->ai_addr, r->ai_addrlen);

	/* Send command to helper: turn repair mode on, wait for reply */
	cmd = TCP_REPAIR_OFF;
	sendmsg(s_helper, &msg, 0);
	recv(s_helper, &((int){ 0 }), 1, 0);

	/* Terminate helper */
	cmd = INT_MAX;
	sendmsg(s_helper, &msg, 0);

	/* Send some more data */
	send(s, "after migration\n", sizeof("after migration\n"), 0);
}

  reply	other threads:[~2025-01-27 23:31 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-27 23:15 [PATCH 0/7] Draft, incomplete series introducing state migration Stefano Brivio
2025-01-27 23:15 ` [PATCH 1/7] icmp, udp: Pad time_t timestamp to 64-bit to ease " Stefano Brivio
2025-01-28  0:49   ` David Gibson
2025-01-28  6:48     ` Stefano Brivio
2025-01-27 23:15 ` [PATCH 2/7] flow, flow_table: Pad flow table entries to 128 bytes, hash entries to 32 bits Stefano Brivio
2025-01-28  0:50   ` David Gibson
2025-01-27 23:15 ` [PATCH 3/7] tcp_conn: Avoid 7-bit hole in struct tcp_splice_conn Stefano Brivio
2025-01-28  0:53   ` David Gibson
2025-01-28  6:48     ` Stefano Brivio
2025-01-29  1:02       ` David Gibson
2025-01-29  7:33         ` Stefano Brivio
2025-01-30  0:44           ` David Gibson
2025-01-30  4:55             ` Stefano Brivio
2025-01-30  7:27               ` David Gibson
2025-01-27 23:15 ` [PATCH 4/7] flow_table: Use size in extern declaration for flowtab Stefano Brivio
2025-01-27 23:15 ` [PATCH 5/7] util: Add read_remainder() and read_all_buf() Stefano Brivio
2025-01-28  0:59   ` David Gibson
2025-01-28  6:48     ` Stefano Brivio
2025-01-29  1:03       ` David Gibson
2025-01-29  7:33         ` Stefano Brivio
2025-01-30  0:44           ` David Gibson
2025-01-27 23:15 ` [PATCH 6/7] Introduce facilities for guest migration on top of vhost-user infrastructure Stefano Brivio
2025-01-28  1:40   ` David Gibson
2025-01-28  6:50     ` Stefano Brivio
2025-01-29  1:16       ` David Gibson
2025-01-29  7:33         ` Stefano Brivio
2025-01-30  0:48           ` David Gibson
2025-01-30  4:55             ` Stefano Brivio
2025-01-30  7:38               ` David Gibson
2025-01-30  8:32                 ` Stefano Brivio
2025-01-30  8:54                   ` David Gibson
2025-01-27 23:15 ` [PATCH 7/7] Introduce passt-repair Stefano Brivio
2025-01-27 23:31   ` Stefano Brivio [this message]
2025-01-28  1:51   ` David Gibson
2025-01-28  6:51     ` Stefano Brivio
2025-01-29  1:29       ` David Gibson
2025-01-29  7:04         ` Stefano Brivio
2025-01-30  0:53           ` David Gibson
2025-01-30  4:55             ` Stefano Brivio
2025-01-30  7:43               ` David Gibson
2025-01-30  7:56                 ` Stefano Brivio

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=20250128003133.19011f58@elisabeth \
    --to=sbrivio@redhat.com \
    --cc=david@gibson.dropbear.id.au \
    --cc=lvivier@redhat.com \
    --cc=passt-dev@passt.top \
    /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.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).