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(a)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;
--
2.43.0