fix(native): repost RX queue before waiting for relay ACK

This commit is contained in:
冰朔 2026-08-06 20:25:27 +08:00
commit f7a6dd2f19
4 changed files with 49 additions and 4 deletions

View file

@ -962,12 +962,17 @@ ghal_net_icmp_exchange_once:
add r12, 4095
and r12, -4096
movzx r8d, word [rel ghal_net_rx_next_index]
mov byte [rel ghal_net_resident_retry_count], 0
.post_receive:
mov rdi, VIRTIO_NET_RX_BUFFER
xor eax, eax
mov ecx, VIRTIO_NET_BUFFER_SIZE / 8
rep stosq
mov eax, r10d
shl eax, 4
mov ebx, VIRTIO_NET_RX_QUEUE
add rbx, rax
mov eax, r8d
dec eax
mov ecx, r10d
@ -1085,6 +1090,7 @@ ghal_net_icmp_exchange_once:
.request_complete:
inc word [rel ghal_net_tx_next_index]
.reset_receive_wait:
mov ecx, 0x80000000
.wait_receive:
cmp word [r12 + 2], r8w
@ -1092,12 +1098,15 @@ ghal_net_icmp_exchange_once:
pause
loop .wait_receive
%ifdef GHOS_NATIVE_RESIDENT
inc byte [rel ghal_net_resident_retry_count]
cmp byte [rel ghal_net_resident_retry_count], 3
jae .receive_timeout
jmp .send_request
%else
%endif
.receive_timeout:
mov byte [rel physical_proof_error_code], 0x54
stc
ret
%endif
.packet_received:
mov eax, r8d
@ -1180,7 +1189,29 @@ ghal_net_icmp_exchange_once:
.ignore_packet:
inc r8w
jnz .post_receive
jz .receive_index_exhausted
mov rdi, VIRTIO_NET_RX_BUFFER
xor eax, eax
mov ecx, VIRTIO_NET_BUFFER_SIZE / 8
rep stosq
mov eax, r10d
shl eax, 4
mov ebx, VIRTIO_NET_RX_QUEUE
add rbx, rax
mov eax, r8d
dec eax
mov ecx, r10d
dec ecx
and eax, ecx
mov word [rbx + rax * 2 + 4], 0
mov word [rbx + 2], r8w
sfence
mov dx, [rel ghal_net_io_base]
add dx, VIRTIO_QUEUE_NOTIFY
xor ax, ax
out dx, ax
jmp .reset_receive_wait
.receive_index_exhausted:
mov byte [rel physical_proof_error_code], 0x57
stc
ret
@ -1248,6 +1279,7 @@ ghal_net_expected_magic: dq ghal_login_magic
ghal_net_command_kind: db 0
ghal_net_matched_kind: db 0
ghal_net_expected_sequence: db 1
ghal_net_resident_retry_count: db 0
msg_ghal_net_discovered: db "GHOS_GHAL_VIRTIO_NET=DISCOVERED", 13, 10, 0
msg_ghal_block_discovered: db "GHOS_GHAL_VIRTIO_BLOCK=DISCOVERED", 13, 10, 0

View file

@ -64,7 +64,7 @@ def verified_request(frame: bytes, sequence: int, magic: bytes) -> None:
assert checksum(frame[34:82]) == 0
def authenticated_reply(frame: bytes, magic: bytes) -> bytes:
def ordinary_reply(frame: bytes) -> bytes:
reply = bytearray(frame)
reply[0:6] = GUEST_MAC
reply[6:12] = PEER_MAC
@ -74,6 +74,13 @@ def authenticated_reply(frame: bytes, magic: bytes) -> bytes:
reply[24:26] = struct.pack("!H", checksum(bytes(reply[14:34])))
reply[34] = 0
reply[36:38] = b"\0\0"
reply[36:38] = struct.pack("!H", checksum(bytes(reply[34:82])))
return bytes(reply)
def authenticated_reply(frame: bytes, magic: bytes) -> bytes:
reply = bytearray(ordinary_reply(frame))
reply[36:38] = b"\0\0"
reply[66:82] = NATIVE_ACK_MAGIC
reply[36:38] = struct.pack("!H", checksum(bytes(reply[34:82])))
return bytes(reply)
@ -137,6 +144,8 @@ def main() -> None:
else:
raise AssertionError(f"unexpected native sequence {sequence}")
verified_request(frame, sequence, magic)
peer.sendto(ordinary_reply(frame), qemu)
time.sleep(0.05)
peer.sendto(authenticated_reply(frame, magic), qemu)
terminal_sequence = 3 if args.login_only else (16 if args.resident else 5)
@ -147,6 +156,7 @@ def main() -> None:
"arp_gateway_reply: VERIFIED\n"
"handshake_direction: NATIVE_INITIATED_OUTBOUND_ICMP\n"
"authenticated_relay_reply: VERIFIED\n"
"ordinary_echo_reply_ignored: true\n"
"icmp_login_request_sent: true\n"
"icmp_login_reply_verified: true\n"
f"icmp_login_reply_count: {login_count}\n"

View file

@ -62,6 +62,7 @@ peer_pid=
grep -q '^handshake_direction: NATIVE_INITIATED_OUTBOUND_ICMP$' \
"${test_root}/peer.hldp"
grep -q '^authenticated_relay_reply: VERIFIED$' "${test_root}/peer.hldp"
grep -q '^ordinary_echo_reply_ignored: true$' "${test_root}/peer.hldp"
grep -q '^icmp_login_reply_count: 3$' "${test_root}/peer.hldp"
grep -q '^code_commit_reply_verified: true$' "${test_root}/peer.hldp"
grep -q '^branch_move_reply_verified: true$' "${test_root}/peer.hldp"

View file

@ -18,6 +18,8 @@ handshake:
response_delay_reason: ALLOW_KERNEL_NAT_REPLY_THEN_NATIVE_RX_REPOST
expected_sequences: 1-16
ordinary_echo_action: IGNORE
ordinary_echo_follow_up: REPOST_RX_AND_WAIT_WITHOUT_RETRANSMIT
receive_timeout_action: RETRY_THREE_TIMES_THEN_WRITE_FAIL_PROOF_AND_RESET
stale_sequence_action: IGNORE_WITHOUT_STATE_ADVANCE
future_sequence_action: IGNORE_WITHOUT_STATE_ADVANCE
accepted_sequence_action: ADVANCE_EXACTLY_ONCE