diff options
Diffstat (limited to 'tcp.c')
-rw-r--r-- | tcp.c | 59 |
1 files changed, 59 insertions, 0 deletions
@@ -2857,6 +2857,57 @@ static int tcp_flow_dump_mss(int s, struct tcp_tap_transfer_ext *t) return 0; } + +/** + * tcp_flow_dump_timestamp() - Dump RFC 7323 timestamp via TCP_TIMESTAMP + * @conn: Pointer to the TCP connection structure + * @t: Extended migration data (tcpi_options must be populated) + * + * Return: 0 on success, negative error code on failure + */ +static int tcp_flow_dump_timestamp(const struct tcp_tap_conn *conn, + struct tcp_tap_transfer_ext *t) +{ + int val = 0; + + if (t->tcpi_options & TCPI_OPT_TIMESTAMPS) { + socklen_t sl = sizeof(val); + + if (getsockopt(conn->sock, SOL_TCP, TCP_TIMESTAMP, &val, &sl)) { + int rc = -errno; + flow_perror(conn, "Getting RFC 7323 timestamp"); + return rc; + } + } + + t->timestamp = (uint32_t)val; + return 0; +} + +/** + * tcp_flow_repair_timestamp() - Restore RFC 7323 timestamp via TCP_TIMESTAMP + * @conn: Pointer to the TCP connection structure + * @t: Extended migration data + * + * Return: 0 on success, negative error code on failure + */ +static int tcp_flow_repair_timestamp(const struct tcp_tap_conn *conn, + const struct tcp_tap_transfer_ext *t) +{ + int val = (int)t->timestamp; + + if (t->tcpi_options & TCPI_OPT_TIMESTAMPS) { + if (setsockopt(conn->sock, SOL_TCP, TCP_TIMESTAMP, + &val, sizeof(val))) { + int rc = -errno; + flow_perror(conn, "Setting RFC 7323 timestamp"); + return rc; + } + } + + return 0; +} + /** * tcp_flow_dump_wnd() - Dump current tcp_repair_window parameters * @c: Execution context @@ -3244,6 +3295,9 @@ int tcp_flow_migrate_source_ext(int fd, int fidx, if ((rc = tcp_flow_dump_mss(s, t))) goto fail; + if ((rc = tcp_flow_dump_timestamp(conn, t))) + goto fail; + if ((rc = tcp_flow_dump_wnd(s, t))) goto fail; @@ -3289,6 +3343,7 @@ int tcp_flow_migrate_source_ext(int fd, int fidx, t->notsent = htonl(t->notsent); t->rcvq = htonl(t->rcvq); t->mss = htonl(t->mss); + t->timestamp = htonl(t->timestamp); t->snd_wl1 = htonl(t->snd_wl1); t->snd_wnd = htonl(t->snd_wnd); @@ -3503,6 +3558,7 @@ int tcp_flow_migrate_target_ext(struct ctx *c, union flow *flow, int fd) t.notsent = ntohl(t.notsent); t.rcvq = ntohl(t.rcvq); t.mss = ntohl(t.mss); + t.timestamp = ntohl(t.timestamp); t.snd_wl1 = ntohl(t.snd_wl1); t.snd_wnd = ntohl(t.snd_wnd); @@ -3542,6 +3598,9 @@ int tcp_flow_migrate_target_ext(struct ctx *c, union flow *flow, int fd) /* We weren't able to create the socket, discard flow */ goto fail; + if (tcp_flow_repair_timestamp(conn, &t)) + goto fail; + if (tcp_flow_select_queue(s, TCP_SEND_QUEUE)) goto fail; |