On Wed, Nov 20, 2024 at 01:40:50PM +0100, Laurent Vivier wrote:On 20/11/2024 04:33, David Gibson wrote:Ah, yes, I see your point. -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibsonI tried but tcp_fill_headersX() needs the length computed in tcp_prepare_flags() but tcp_prepare_flags() needs to be after tcp_vu_prepare() because tcp_vu_prepare() resets the TCP header and tcp_prepare_flags() updates it with the flags. tcp_prepare_flags() should be called in the middle of tcp_vu_prepare(). It's really simpler to duplicate the code of tcp_vu_prepare() in tcp_vu_send_flag() rather than to call tcp_vu_prepare() from tcp_vu_send_flag().+ vu_set_vnethdr(vdev, flags_elem[0].in_sg[0].iov_base, 1); + + eh = vu_eth(flags_elem[0].in_sg[0].iov_base); + + memcpy(eh->h_dest, c->guest_mac, sizeof(eh->h_dest)); + memcpy(eh->h_source, c->our_tap_mac, sizeof(eh->h_source)); + + if (CONN_V4(conn)) { + struct tcp_payload_t *payload; + struct iphdr *iph; + uint32_t seq; + + eh->h_proto = htons(ETH_P_IP); + + iph = vu_ip(flags_elem[0].in_sg[0].iov_base); + *iph = (struct iphdr)L2_BUF_IP4_INIT(IPPROTO_TCP); + + payload = vu_payloadv4(flags_elem[0].in_sg[0].iov_base); + memset(&payload->th, 0, sizeof(payload->th)); + payload->th.doff = offsetof(struct tcp_payload_t, data) / 4; + payload->th.ack = 1; + + seq = conn->seq_to_tap; + ret = tcp_prepare_flags(c, conn, flags, &payload->th, + (struct tcp_syn_opts *)payload->data, + &optlen); + if (ret <= 0) { + vu_queue_rewind(vq, 1); + return ret; + } + + l4len = tcp_fill_headers4(conn, NULL, iph, payload, optlen, + NULL, seq, true); + l2len = sizeof(*iph);Much of the above duplicates tcp_vu_prepare(). Any chance you could call into it instead?