aboutgitcodebugslistschat
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2025-01-31 18:27:07 +0100
committerStefano Brivio <sbrivio@redhat.com>2025-02-04 01:28:04 +0100
commit52e57f9c9a6d8ae4153ac592d01d868b31c10171 (patch)
tree9e2368d9e29a58be0b53f17b2a962f1fd3ad30d7
parent8c24301462c39027e6eb6f1ad56c1f6c83fb0c23 (diff)
downloadpasst-52e57f9c9a6d8ae4153ac592d01d868b31c10171.tar
passt-52e57f9c9a6d8ae4153ac592d01d868b31c10171.tar.gz
passt-52e57f9c9a6d8ae4153ac592d01d868b31c10171.tar.bz2
passt-52e57f9c9a6d8ae4153ac592d01d868b31c10171.tar.lz
passt-52e57f9c9a6d8ae4153ac592d01d868b31c10171.tar.xz
passt-52e57f9c9a6d8ae4153ac592d01d868b31c10171.tar.zst
passt-52e57f9c9a6d8ae4153ac592d01d868b31c10171.zip
tcp: Get socket port and address using getsockname() when connecting from guest
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>
-rw-r--r--flow.c4
-rw-r--r--flow_table.h4
-rw-r--r--tcp.c28
3 files changed, 31 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..fac322c 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,29 @@ 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;
+
+ sl = sizeof(s_in);
+ if (!getsockname(s, (struct sockaddr *)&s_in, &sl)) {
+ /* NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) */
+ tgt->oport = ntohs(s_in.sin_port);
+ tgt->oaddr = inany_from_v4(s_in.sin_addr);
+ }
+ } else {
+ struct sockaddr_in6 s_in6;
+
+ sl = sizeof(s_in6);
+ if (!getsockname(s, (struct sockaddr *)&s_in6, &sl)) {
+ /* NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) */
+ tgt->oport = ntohs(s_in6.sin6_port);
+ tgt->oaddr.a6 = s_in6.sin6_addr;
+ }
+ }
+ }
+
FLOW_ACTIVATE(conn);
return;