diff --git a/src/libknot/xdp/tcp.c b/src/libknot/xdp/tcp.c
index 80760bc3b7530917baa67d8c30d8e6fe75776aa5..afe192ab158916dbdb1e7a4d751bd8a934093682 100644
--- a/src/libknot/xdp/tcp.c
+++ b/src/libknot/xdp/tcp.c
@@ -170,7 +170,15 @@ dynarray_define(tcp_relay, knot_tcp_relay_t, DYNARRAY_VISIBILITY_PUBLIC)
 
 static bool check_seq_ack(const knot_xdp_msg_t *msg, const knot_tcp_conn_t *conn)
 {
-	return (conn != NULL && conn->seqno == msg->seqno && conn->ackno == msg->ackno);
+	if (conn == NULL || conn->seqno != msg->seqno) {
+		return false;
+	}
+
+	if (conn->acked <= conn->ackno) { // ackno does not wrap around uint32
+		return (msg->ackno >= conn->acked && msg->ackno <= conn->ackno);
+	} else { // this is more tricky
+		return (msg->ackno >= conn->acked || msg->ackno <= conn->ackno);
+	}
 }
 
 _public_
@@ -217,6 +225,9 @@ int knot_xdp_tcp_relay(knot_xdp_socket_t *socket, knot_xdp_msg_t msgs[], uint32_
 			memcpy((*conn)->last_eth_rem, msg->eth_from, sizeof((*conn)->last_eth_rem));
 			memcpy((*conn)->last_eth_loc, msg->eth_to, sizeof((*conn)->last_eth_loc));
 			(*conn)->last_active = get_timestamp();
+			if (msg->flags & KNOT_XDP_MSG_ACK) {
+				(*conn)->acked = msg->ackno;
+			}
 		}
 
 		knot_tcp_relay_t relay = { .msg = msg, .conn = *conn };
@@ -234,7 +245,8 @@ int knot_xdp_tcp_relay(knot_xdp_socket_t *socket, knot_xdp_msg_t msgs[], uint32_
 				relay.conn->state = XDP_TCP_ESTABLISHING;
 				relay.conn->seqno++;
 				if (!synack) {
-					relay.conn->ackno = acks[n_acks - 1].seqno + 1;
+					relay.conn->acked = acks[n_acks - 1].seqno;
+					relay.conn->ackno = relay.conn->acked + 1;
 				}
 			} else {
 				resp_ack(msg, KNOT_XDP_MSG_RST); // TODO consider resetting the OLD conn and accepting new one
diff --git a/src/libknot/xdp/tcp.h b/src/libknot/xdp/tcp.h
index d5acc2debe064fd1c5e796cb960953cb6c54a8be..7f327ddb694f2f3a928514146e27ba53fa4b923e 100644
--- a/src/libknot/xdp/tcp.h
+++ b/src/libknot/xdp/tcp.h
@@ -55,6 +55,7 @@ typedef struct knot_xdp_tcp_conn {
 	uint8_t last_eth_loc[ETH_ALEN];
 	uint32_t seqno;
 	uint32_t ackno;
+	uint32_t acked;
 	uint32_t last_active;
 	knot_tcp_state_t state;
 	struct knot_xdp_tcp_conn *next;