From: Stefano Brivio <sbrivio@redhat.com>
To: passt-dev@passt.top
Cc: David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH] tcp: Get socket port and address using getsockname() when connecting from guest
Date: Tue, 4 Feb 2025 01:05:20 +0100 [thread overview]
Message-ID: <20250204000520.3811285-1-sbrivio@redhat.com> (raw)
For migration only: we need to store 'oport', our socket-side port,
as we establish a connection from the guest, so that we can bind the
same oport as source port in the migration target.
Similar for 'oaddr': this is needed in case the migration target has
additional network interfaces, and we need to make sure our socket is
bound to the equivalent interface as it was on the source.
Use getsockname() to fetch them.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
---
Note: I'm merging this right now, but posting anyway to ease review.
flow.c | 4 ++--
flow_table.h | 4 ++--
tcp.c | 26 +++++++++++++++++++++++++-
3 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/flow.c b/flow.c
index ee1221b..a6fe6d1 100644
--- a/flow.c
+++ b/flow.c
@@ -414,8 +414,8 @@ const struct flowside *flow_initiate_sa(union flow *flow, uint8_t pif,
*
* Return: pointer to the target flowside information
*/
-const struct flowside *flow_target(const struct ctx *c, union flow *flow,
- uint8_t proto)
+struct flowside *flow_target(const struct ctx *c, union flow *flow,
+ uint8_t proto)
{
char estr[INANY_ADDRSTRLEN], fstr[INANY_ADDRSTRLEN];
struct flow_common *f = &flow->f;
diff --git a/flow_table.h b/flow_table.h
index f15db53..eeb6f41 100644
--- a/flow_table.h
+++ b/flow_table.h
@@ -168,8 +168,8 @@ const struct flowside *flow_target_af(union flow *flow, uint8_t pif,
sa_family_t af,
const void *saddr, in_port_t sport,
const void *daddr, in_port_t dport);
-const struct flowside *flow_target(const struct ctx *c, union flow *flow,
- uint8_t proto);
+struct flowside *flow_target(const struct ctx *c, union flow *flow,
+ uint8_t proto);
union flow *flow_set_type(union flow *flow, enum flow_type type);
#define FLOW_SET_TYPE(flow_, t_, var_) (&flow_set_type((flow_), (t_))->var_)
diff --git a/tcp.c b/tcp.c
index 51ad692..cf2943d 100644
--- a/tcp.c
+++ b/tcp.c
@@ -1415,6 +1415,8 @@ static void tcp_bind_outbound(const struct ctx *c,
* @opts: Pointer to start of options
* @optlen: Bytes in options: caller MUST ensure available length
* @now: Current timestamp
+ *
+ * #syscalls:vu getsockname
*/
static void tcp_conn_from_tap(const struct ctx *c, sa_family_t af,
const void *saddr, const void *daddr,
@@ -1423,9 +1425,10 @@ static void tcp_conn_from_tap(const struct ctx *c, sa_family_t af,
{
in_port_t srcport = ntohs(th->source);
in_port_t dstport = ntohs(th->dest);
- const struct flowside *ini, *tgt;
+ const struct flowside *ini;
struct tcp_tap_conn *conn;
union sockaddr_inany sa;
+ struct flowside *tgt;
union flow *flow;
int s = -1, mss;
uint64_t hash;
@@ -1530,6 +1533,27 @@ static void tcp_conn_from_tap(const struct ctx *c, sa_family_t af,
}
tcp_epoll_ctl(c, conn);
+
+ if (c->mode == MODE_VU) { /* To rebind to same oport after migration */
+ if (af == AF_INET) {
+ struct sockaddr_in s_in;
+ socklen_t sl;
+
+ sl = sizeof(s_in);
+ getsockname(s, (struct sockaddr *)&s_in, &sl);
+ tgt->oport = ntohs(s_in.sin_port);
+ tgt->oaddr = inany_from_v4(s_in.sin_addr);
+ } else {
+ struct sockaddr_in6 s_in6;
+ socklen_t sl;
+
+ sl = sizeof(s_in6);
+ getsockname(s, (struct sockaddr *)&s_in6, &sl);
+ tgt->oport = ntohs(s_in6.sin6_port);
+ tgt->oaddr.a6 = s_in6.sin6_addr;
+ }
+ }
+
FLOW_ACTIVATE(conn);
return;
--
@@ -1415,6 +1415,8 @@ static void tcp_bind_outbound(const struct ctx *c,
* @opts: Pointer to start of options
* @optlen: Bytes in options: caller MUST ensure available length
* @now: Current timestamp
+ *
+ * #syscalls:vu getsockname
*/
static void tcp_conn_from_tap(const struct ctx *c, sa_family_t af,
const void *saddr, const void *daddr,
@@ -1423,9 +1425,10 @@ static void tcp_conn_from_tap(const struct ctx *c, sa_family_t af,
{
in_port_t srcport = ntohs(th->source);
in_port_t dstport = ntohs(th->dest);
- const struct flowside *ini, *tgt;
+ const struct flowside *ini;
struct tcp_tap_conn *conn;
union sockaddr_inany sa;
+ struct flowside *tgt;
union flow *flow;
int s = -1, mss;
uint64_t hash;
@@ -1530,6 +1533,27 @@ static void tcp_conn_from_tap(const struct ctx *c, sa_family_t af,
}
tcp_epoll_ctl(c, conn);
+
+ if (c->mode == MODE_VU) { /* To rebind to same oport after migration */
+ if (af == AF_INET) {
+ struct sockaddr_in s_in;
+ socklen_t sl;
+
+ sl = sizeof(s_in);
+ getsockname(s, (struct sockaddr *)&s_in, &sl);
+ tgt->oport = ntohs(s_in.sin_port);
+ tgt->oaddr = inany_from_v4(s_in.sin_addr);
+ } else {
+ struct sockaddr_in6 s_in6;
+ socklen_t sl;
+
+ sl = sizeof(s_in6);
+ getsockname(s, (struct sockaddr *)&s_in6, &sl);
+ tgt->oport = ntohs(s_in6.sin6_port);
+ tgt->oaddr.a6 = s_in6.sin6_addr;
+ }
+ }
+
FLOW_ACTIVATE(conn);
return;
--
2.43.0
reply other threads:[~2025-02-04 0:05 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20250204000520.3811285-1-sbrivio@redhat.com \
--to=sbrivio@redhat.com \
--cc=david@gibson.dropbear.id.au \
--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).