aboutgitcodebugslistschat
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2021-04-25 10:46:42 +0200
committerStefano Brivio <sbrivio@redhat.com>2021-04-29 17:12:59 +0200
commit48afbe321eddfb68966a4436884c022e64c3e166 (patch)
treee77e395c1cf3e27ce2bb65864fda5622fa275e20
parentb3b3451ae26ad53b80ee73182a333716573397f8 (diff)
downloadpasst-48afbe321eddfb68966a4436884c022e64c3e166.tar
passt-48afbe321eddfb68966a4436884c022e64c3e166.tar.gz
passt-48afbe321eddfb68966a4436884c022e64c3e166.tar.bz2
passt-48afbe321eddfb68966a4436884c022e64c3e166.tar.lz
passt-48afbe321eddfb68966a4436884c022e64c3e166.tar.xz
passt-48afbe321eddfb68966a4436884c022e64c3e166.tar.zst
passt-48afbe321eddfb68966a4436884c022e64c3e166.zip
tcp: Preserve data sent during SOCK_SYN_SENT state
Seen with iperf3 server on tap side: connection state is SOCK_SYN_SENT, we haven't got an ACK from the tap yet (that's why we're not in ESTABLISHED), but a data packet comes. Don't read this data until we reach the ESTABLISHED state, by keeping EPOLLIN disabled until that point. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
-rw-r--r--tcp.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/tcp.c b/tcp.c
index 3d47f35..1713dbc 100644
--- a/tcp.c
+++ b/tcp.c
@@ -954,7 +954,7 @@ static void tcp_conn_from_tap(struct ctx *c, int af, void *addr,
tcp_act_set(s);
- ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP | EPOLLERR | EPOLLHUP;
+ ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP | EPOLLHUP;
ev.data.fd = s;
tc[s].seq_init_from_tap = ntohl(th->seq);
@@ -1059,7 +1059,7 @@ static void tcp_conn_from_sock(struct ctx *c, int fd)
tcp_act_set(s);
- ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP | EPOLLERR | EPOLLHUP;
+ ev.events = EPOLLRDHUP | EPOLLHUP;
ev.data.fd = s;
epoll_ctl(c->epollfd, EPOLL_CTL_ADD, s, &ev);
@@ -1209,6 +1209,7 @@ int tcp_tap_handler(struct ctx *c, int af, void *addr,
{
/* TODO: Implement message batching for TCP */
struct tcphdr *th = (struct tcphdr *)msg[0].l4h;
+ struct epoll_event ev = { 0 };
size_t len = msg[0].l4_len;
size_t off, skip = 0;
@@ -1272,6 +1273,16 @@ int tcp_tap_handler(struct ctx *c, int af, void *addr,
tcp_set_state(s, ESTABLISHED);
tcp_send_to_tap(c, s, ACK, NULL, 0);
+
+ /* The client might have sent data already, which we didn't
+ * dequeue waiting for SYN,ACK from tap -- check now.
+ */
+ tcp_data_from_sock(c, s);
+
+ ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP | EPOLLHUP;
+ ev.data.fd = s;
+ epoll_ctl(c->epollfd, EPOLL_CTL_MOD, s, &ev);
+
break;
case TAP_SYN_RCVD:
if (th->fin) {
@@ -1379,7 +1390,7 @@ static void tcp_connect_finish(struct ctx *c, int s)
return;
/* Drop EPOLLOUT, only used to wait for connect() to complete */
- ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP | EPOLLERR | EPOLLHUP;
+ ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP | EPOLLHUP;
ev.data.fd = s;
epoll_ctl(c->epollfd, EPOLL_CTL_MOD, s, &ev);
@@ -1403,6 +1414,12 @@ void tcp_sock_handler(struct ctx *c, int s, uint32_t events)
return;
}
+ if (tc[s].s == SOCK_SYN_SENT) {
+ /* This can only be a socket error or a shutdown from remote */
+ tcp_rst(c, s);
+ return;
+ }
+
sl = sizeof(so);
if ((events & EPOLLERR) ||
getsockopt(s, SOL_SOCKET, SO_ACCEPTCONN, &so, &sl)) {