diff options
author | Stefano Brivio <sbrivio@redhat.com> | 2021-04-25 10:46:42 +0200 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2021-04-29 17:12:59 +0200 |
commit | 48afbe321eddfb68966a4436884c022e64c3e166 (patch) | |
tree | e77e395c1cf3e27ce2bb65864fda5622fa275e20 /tcp.c | |
parent | b3b3451ae26ad53b80ee73182a333716573397f8 (diff) | |
download | passt-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>
Diffstat (limited to 'tcp.c')
-rw-r--r-- | tcp.c | 23 |
1 files changed, 20 insertions, 3 deletions
@@ -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)) { |