feat(native): add JD read-only anchor HTTP service
This commit is contained in:
parent
22b834eb79
commit
f31c33e77a
7 changed files with 476 additions and 4 deletions
|
|
@ -0,0 +1,59 @@
|
||||||
|
# ADR-0171 · 京东原生服务等价分阶段门禁
|
||||||
|
|
||||||
|
## 状态
|
||||||
|
|
||||||
|
Accepted for staged verification. Production native cutover remains `0`.
|
||||||
|
|
||||||
|
## 为什么不能把“原生内核已常驻”当成“服务器部署完成”
|
||||||
|
|
||||||
|
JD-FD-PRIMARY 在原生光湖 OS 常驻时已经证明:
|
||||||
|
|
||||||
|
- GOSK/GHAL 在物理机启动;
|
||||||
|
- Linux 内核与 Linux 用户态不在场;
|
||||||
|
- 五域、代码对象、分支回执和人格索引可从原生盘面读写;
|
||||||
|
- 受保护的人类授权恢复能力有效。
|
||||||
|
|
||||||
|
但现有公共代码频道和导航服务由 Linux 上的 Forgejo、Node 服务及反向 SSH 前门共同提供。
|
||||||
|
原生常驻时这条 Linux 数据面消失,`/code/` 与公共导航锚点都返回 `502`。因此内核常驻和
|
||||||
|
生产服务等价是两个独立的二值门。
|
||||||
|
|
||||||
|
## 分阶段目标
|
||||||
|
|
||||||
|
1. `NATIVE_ANCHOR_HTTP_QEMU`
|
||||||
|
- GHAL 直接处理 TCP/IPv4;
|
||||||
|
- 原生端口 `3922` 回应 `GET /v1/anchor`;
|
||||||
|
- 返回唯一锚点 `GLW-PUBLIC-NAV-ANCHOR-001`;
|
||||||
|
- 不引入 Linux 用户态或通用套接字库。
|
||||||
|
2. `NATIVE_ANCHOR_HTTP_PHYSICAL`
|
||||||
|
- 京东物理机原生启动;
|
||||||
|
- 由服务器外部节点完成 TCP、校验和与正文回读;
|
||||||
|
- 同一窗口验证受保护恢复。
|
||||||
|
3. `PUBLIC_FRONT_DOOR_NATIVE_ANCHOR`
|
||||||
|
- `https://guanghulab.com/api/ai/v1/anchor` 在京东原生常驻时仍返回 `200`;
|
||||||
|
- 返回值必须与唯一公共锚点一致;
|
||||||
|
- 不允许把用户的个人腾讯云服务器静默改成生产承载节点。
|
||||||
|
4. `NATIVE_CODE_CHANNEL_READ_ONLY`
|
||||||
|
- 原生数据面可读取仓库对象、引用和提交;
|
||||||
|
- 先提供只读发现能力,再设计带授权的写入。
|
||||||
|
5. `NATIVE_CODE_CHANNEL_MUTATION`
|
||||||
|
- HLDP 意图、授权、对象写入、分支移动和回执形成闭环。
|
||||||
|
6. `PRODUCTION_NATIVE_CUTOVER`
|
||||||
|
- 公共导航与代码频道全部通过物理公网门禁;
|
||||||
|
- 回滚路径与服务器自有回执可读;
|
||||||
|
- 才允许恢复原生默认启动。
|
||||||
|
|
||||||
|
## 当前实现边界
|
||||||
|
|
||||||
|
本阶段实现的是一个有界的只读 TCP 投影,不是通用 TCP/IP 栈,也不是 Forgejo 替代品。
|
||||||
|
它从收到的帧派生对端 MAC、IP、端口和确认号,直接构造 SYN-ACK 与带 FIN 的 HTTP 200
|
||||||
|
响应。它与现有 ICMP 控制/恢复通道并存。
|
||||||
|
|
||||||
|
当前正文包含稳定的唯一入口映射。它尚未在原生常驻期间自动拉取 REPO-012 的新版本,
|
||||||
|
因此“公共导航自动更新”仍需后续的原生锚点快照同步或带认证的增量更新协议。
|
||||||
|
|
||||||
|
## 安全决定
|
||||||
|
|
||||||
|
- 京东的无人值守默认启动继续保持 Linux 维护位;
|
||||||
|
- 原生候选保留为非默认的一次性门禁入口;
|
||||||
|
- 物理原生门禁失败时立即走已经证明的受保护恢复路径;
|
||||||
|
- 不用协议文件、QEMU 结果或端口发包冒充公网服务等价。
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
schema: guanghu.jd-native-anchor-service-qemu-receipt/v1
|
||||||
|
receipt_id: GH-OS-JD-FD-PRIMARY-NATIVE-ANCHOR-QEMU-20260807-001
|
||||||
|
status: PASS_100
|
||||||
|
observed_at: 2026-08-07T01:08:24+08:00
|
||||||
|
node_id: JD-FD-PRIMARY
|
||||||
|
source_branch: codex/jd-native-anchor-service-20260807
|
||||||
|
candidate:
|
||||||
|
lba_start: 105
|
||||||
|
sector_count: 29
|
||||||
|
sha256: 2911b5f6a067efb7b5b7ec330833cb9f8a6b965b5a05802770dd27032678f32f
|
||||||
|
native_anchor_service:
|
||||||
|
transport: TCP_IPV4_OVER_GHAL_VIRTIO_NET
|
||||||
|
port: 3922
|
||||||
|
request: GET /v1/anchor
|
||||||
|
response_schema: guanghu.native-public-anchor/v1
|
||||||
|
anchor_id: GLW-PUBLIC-NAV-ANCHOR-001
|
||||||
|
entry_path: LL-CMPN-0001
|
||||||
|
world_node_id: SYS-GLW-0001
|
||||||
|
repository_id: REPO-012
|
||||||
|
branch: main
|
||||||
|
code_entry: https://guanghulab.com/code/bingshuo/guanghu-ice-heart
|
||||||
|
runtime: GUANGHU_OS_NATIVE
|
||||||
|
verification:
|
||||||
|
tcp_syn_ack_checksum: PASS_100
|
||||||
|
http_response_checksum: PASS_100
|
||||||
|
response_body_exact_match: PASS_100
|
||||||
|
wrong_recovery_capability_kept_native_resident: PASS_100
|
||||||
|
protected_recovery_capability_returned_hosted_linux: PASS_100
|
||||||
|
boundary:
|
||||||
|
native_anchor_http_qemu_capability: 100
|
||||||
|
native_anchor_http_physical_capability: 0
|
||||||
|
public_front_door_native_anchor_equivalence: 0
|
||||||
|
code_channel_service_equivalence: 0
|
||||||
|
production_native_cutover: 0
|
||||||
|
next_action: PHYSICAL_ONE_TIME_NATIVE_ANCHOR_HTTP_GATE_WITH_PROTECTED_RECOVERY
|
||||||
|
|
@ -500,6 +500,8 @@ physical_proof_gestational_index_initialized: db 0
|
||||||
physical_proof_gestational_index_present: db 0
|
physical_proof_gestational_index_present: db 0
|
||||||
physical_proof_gestational_index_read_verified: db 0
|
physical_proof_gestational_index_read_verified: db 0
|
||||||
physical_proof_last_completed_sequence: db 0
|
physical_proof_last_completed_sequence: db 0
|
||||||
|
physical_proof_anchor_tcp_syn_ack_tx: db 0
|
||||||
|
physical_proof_anchor_http_response_tx: db 0
|
||||||
times 512 - ($ - physical_proof_sector) db 0
|
times 512 - ($ - physical_proof_sector) db 0
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ bits 64
|
||||||
%define ETHERNET_HEADER_SIZE 14
|
%define ETHERNET_HEADER_SIZE 14
|
||||||
%define IPV4_HEADER_SIZE 20
|
%define IPV4_HEADER_SIZE 20
|
||||||
%define ICMP_HEADER_SIZE 8
|
%define ICMP_HEADER_SIZE 8
|
||||||
|
%define TCP_HEADER_SIZE 20
|
||||||
|
%define GHOS_NATIVE_ANCHOR_PORT_NETWORK 0x520f
|
||||||
%define GHOS_LOGIN_MAGIC_OFFSET 60
|
%define GHOS_LOGIN_MAGIC_OFFSET 60
|
||||||
%define GHOS_LOGIN_MAGIC_SIZE 16
|
%define GHOS_LOGIN_MAGIC_SIZE 16
|
||||||
; JD Cloud exposes 4096-entry legacy queues. A queue of that size occupies
|
; JD Cloud exposes 4096-entry legacy queues. A queue of that size occupies
|
||||||
|
|
@ -1116,6 +1118,10 @@ ghal_net_icmp_exchange_once:
|
||||||
and eax, ecx
|
and eax, ecx
|
||||||
shl eax, 3
|
shl eax, 3
|
||||||
mov r14d, [r12 + rax + 8]
|
mov r14d, [r12 + rax + 8]
|
||||||
|
%ifdef GHOS_NATIVE_ANCHOR_SERVICE
|
||||||
|
call ghal_net_try_anchor_http
|
||||||
|
jnc .ignore_packet
|
||||||
|
%endif
|
||||||
cmp r14d, GHOS_LOGIN_MAGIC_OFFSET + GHOS_LOGIN_MAGIC_SIZE * 2
|
cmp r14d, GHOS_LOGIN_MAGIC_OFFSET + GHOS_LOGIN_MAGIC_SIZE * 2
|
||||||
jb .ignore_packet
|
jb .ignore_packet
|
||||||
cmp word [VIRTIO_NET_RX_BUFFER + 22], 0x0008
|
cmp word [VIRTIO_NET_RX_BUFFER + 22], 0x0008
|
||||||
|
|
@ -1279,6 +1285,225 @@ ghal_net_checksum:
|
||||||
xchg bl, bh
|
xchg bl, bh
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
%ifdef GHOS_NATIVE_ANCHOR_SERVICE
|
||||||
|
; A deliberately small read-only TCP projection for the unique public anchor.
|
||||||
|
; It is not a general socket stack and it does not claim Forgejo equivalence.
|
||||||
|
; CF=0 means an anchor packet was handled; CF=1 means the caller should keep
|
||||||
|
; applying the existing native-control packet parser.
|
||||||
|
ghal_net_try_anchor_http:
|
||||||
|
cmp r14d, VIRTIO_NET_HEADER_SIZE + ETHERNET_HEADER_SIZE + IPV4_HEADER_SIZE + TCP_HEADER_SIZE
|
||||||
|
jb .not_anchor
|
||||||
|
cmp word [VIRTIO_NET_RX_BUFFER + 22], 0x0008
|
||||||
|
jne .not_anchor
|
||||||
|
cmp byte [VIRTIO_NET_RX_BUFFER + 24], 0x45
|
||||||
|
jne .not_anchor
|
||||||
|
cmp byte [VIRTIO_NET_RX_BUFFER + 33], 6
|
||||||
|
jne .not_anchor
|
||||||
|
cmp dword [VIRTIO_NET_RX_BUFFER + 40], GHOS_NATIVE_IPV4_DWORD
|
||||||
|
jne .not_anchor
|
||||||
|
cmp word [VIRTIO_NET_RX_BUFFER + 46], GHOS_NATIVE_ANCHOR_PORT_NETWORK
|
||||||
|
jne .not_anchor
|
||||||
|
cmp byte [VIRTIO_NET_RX_BUFFER + 56], 0x50
|
||||||
|
jne .not_anchor
|
||||||
|
test byte [VIRTIO_NET_RX_BUFFER + 57], 0x02
|
||||||
|
jnz .handle_syn
|
||||||
|
cmp dword [VIRTIO_NET_RX_BUFFER + 64], 0x20544547
|
||||||
|
jne .handled_without_reply
|
||||||
|
mov byte [rel ghal_anchor_tcp_flags], 0x19
|
||||||
|
mov rsi, ghal_anchor_http_response
|
||||||
|
mov word [rel ghal_anchor_tcp_payload_size], ghal_anchor_http_response_end - ghal_anchor_http_response
|
||||||
|
call ghal_net_send_anchor_tcp
|
||||||
|
jc .not_anchor
|
||||||
|
mov byte [rel physical_proof_anchor_http_response_tx], 1
|
||||||
|
mov rsi, msg_ghal_anchor_http_ready
|
||||||
|
call serial_write64
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
|
||||||
|
.handle_syn:
|
||||||
|
mov byte [rel ghal_anchor_tcp_flags], 0x12
|
||||||
|
mov word [rel ghal_anchor_tcp_payload_size], 0
|
||||||
|
call ghal_net_send_anchor_tcp
|
||||||
|
jc .not_anchor
|
||||||
|
mov byte [rel physical_proof_anchor_tcp_syn_ack_tx], 1
|
||||||
|
.handled_without_reply:
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
.not_anchor:
|
||||||
|
stc
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Build a single TCP response from the current RX frame. The peer address,
|
||||||
|
; ports and acknowledgement are derived from that frame, keeping this native
|
||||||
|
; projection independent from a Linux network stack.
|
||||||
|
ghal_net_send_anchor_tcp:
|
||||||
|
mov rdi, VIRTIO_NET_TX_BUFFER
|
||||||
|
xor eax, eax
|
||||||
|
mov ecx, VIRTIO_NET_BUFFER_SIZE / 8
|
||||||
|
rep stosq
|
||||||
|
xor ecx, ecx
|
||||||
|
.copy_peer_mac:
|
||||||
|
cmp ecx, 6
|
||||||
|
jae .copy_native_mac
|
||||||
|
mov al, [VIRTIO_NET_RX_BUFFER + 16 + rcx]
|
||||||
|
mov [VIRTIO_NET_TX_BUFFER + 10 + rcx], al
|
||||||
|
inc ecx
|
||||||
|
jmp .copy_peer_mac
|
||||||
|
.copy_native_mac:
|
||||||
|
xor ecx, ecx
|
||||||
|
.copy_native_mac_loop:
|
||||||
|
cmp ecx, 6
|
||||||
|
jae .headers
|
||||||
|
mov al, [rel physical_proof_mac + rcx]
|
||||||
|
mov [VIRTIO_NET_TX_BUFFER + 16 + rcx], al
|
||||||
|
inc ecx
|
||||||
|
jmp .copy_native_mac_loop
|
||||||
|
.headers:
|
||||||
|
mov word [VIRTIO_NET_TX_BUFFER + 22], 0x0008
|
||||||
|
mov byte [VIRTIO_NET_TX_BUFFER + 24], 0x45
|
||||||
|
mov byte [VIRTIO_NET_TX_BUFFER + 25], 0
|
||||||
|
movzx eax, word [rel ghal_anchor_tcp_payload_size]
|
||||||
|
add eax, IPV4_HEADER_SIZE + TCP_HEADER_SIZE
|
||||||
|
xchg al, ah
|
||||||
|
mov [VIRTIO_NET_TX_BUFFER + 26], ax
|
||||||
|
mov word [VIRTIO_NET_TX_BUFFER + 28], 0x4147
|
||||||
|
mov word [VIRTIO_NET_TX_BUFFER + 30], 0
|
||||||
|
mov byte [VIRTIO_NET_TX_BUFFER + 32], 39
|
||||||
|
mov byte [VIRTIO_NET_TX_BUFFER + 33], 6
|
||||||
|
mov word [VIRTIO_NET_TX_BUFFER + 34], 0
|
||||||
|
mov dword [VIRTIO_NET_TX_BUFFER + 36], GHOS_NATIVE_IPV4_DWORD
|
||||||
|
mov eax, [VIRTIO_NET_RX_BUFFER + 36]
|
||||||
|
mov [VIRTIO_NET_TX_BUFFER + 40], eax
|
||||||
|
mov word [VIRTIO_NET_TX_BUFFER + 44], GHOS_NATIVE_ANCHOR_PORT_NETWORK
|
||||||
|
mov ax, [VIRTIO_NET_RX_BUFFER + 44]
|
||||||
|
mov [VIRTIO_NET_TX_BUFFER + 46], ax
|
||||||
|
mov eax, 0x534f4847
|
||||||
|
mov [VIRTIO_NET_TX_BUFFER + 48], eax
|
||||||
|
mov eax, [VIRTIO_NET_RX_BUFFER + 48]
|
||||||
|
bswap eax
|
||||||
|
movzx ecx, word [VIRTIO_NET_RX_BUFFER + 26]
|
||||||
|
xchg cl, ch
|
||||||
|
sub ecx, IPV4_HEADER_SIZE + TCP_HEADER_SIZE
|
||||||
|
test byte [VIRTIO_NET_RX_BUFFER + 57], 0x02
|
||||||
|
jz .ack_payload
|
||||||
|
inc ecx
|
||||||
|
.ack_payload:
|
||||||
|
add eax, ecx
|
||||||
|
bswap eax
|
||||||
|
mov [VIRTIO_NET_TX_BUFFER + 52], eax
|
||||||
|
mov byte [VIRTIO_NET_TX_BUFFER + 56], 0x50
|
||||||
|
mov al, [rel ghal_anchor_tcp_flags]
|
||||||
|
mov [VIRTIO_NET_TX_BUFFER + 57], al
|
||||||
|
mov word [VIRTIO_NET_TX_BUFFER + 58], 0x0040
|
||||||
|
mov word [VIRTIO_NET_TX_BUFFER + 60], 0
|
||||||
|
mov word [VIRTIO_NET_TX_BUFFER + 62], 0
|
||||||
|
movzx ecx, word [rel ghal_anchor_tcp_payload_size]
|
||||||
|
test ecx, ecx
|
||||||
|
jz .checksums
|
||||||
|
mov rsi, ghal_anchor_http_response
|
||||||
|
mov rdi, VIRTIO_NET_TX_BUFFER + 64
|
||||||
|
rep movsb
|
||||||
|
.checksums:
|
||||||
|
mov rsi, VIRTIO_NET_TX_BUFFER + 24
|
||||||
|
mov ecx, IPV4_HEADER_SIZE
|
||||||
|
xor ebx, ebx
|
||||||
|
call ghal_net_checksum
|
||||||
|
mov [VIRTIO_NET_TX_BUFFER + 34], bx
|
||||||
|
movzx r15d, word [rel ghal_anchor_tcp_payload_size]
|
||||||
|
add r15d, TCP_HEADER_SIZE
|
||||||
|
call ghal_net_tcp_checksum
|
||||||
|
mov [VIRTIO_NET_TX_BUFFER + 60], bx
|
||||||
|
|
||||||
|
mov qword [VIRTIO_NET_TX_QUEUE], VIRTIO_NET_TX_BUFFER
|
||||||
|
mov eax, r15d
|
||||||
|
add eax, VIRTIO_NET_HEADER_SIZE + ETHERNET_HEADER_SIZE + IPV4_HEADER_SIZE
|
||||||
|
mov dword [VIRTIO_NET_TX_QUEUE + 8], eax
|
||||||
|
mov word [VIRTIO_NET_TX_QUEUE + 12], 0
|
||||||
|
mov word [VIRTIO_NET_TX_QUEUE + 14], 0
|
||||||
|
movzx ecx, word [rel physical_proof_net_tx_queue_size]
|
||||||
|
test ecx, ecx
|
||||||
|
jz .tx_fail
|
||||||
|
mov eax, ecx
|
||||||
|
shl eax, 4
|
||||||
|
mov ebx, VIRTIO_NET_TX_QUEUE
|
||||||
|
add rbx, rax
|
||||||
|
movzx r11d, word [rel ghal_net_tx_next_index]
|
||||||
|
mov eax, r11d
|
||||||
|
dec eax
|
||||||
|
mov edx, ecx
|
||||||
|
dec edx
|
||||||
|
and eax, edx
|
||||||
|
mov word [rbx + rax * 2 + 4], 0
|
||||||
|
mov word [rbx + 2], r11w
|
||||||
|
mov eax, ecx
|
||||||
|
shl eax, 1
|
||||||
|
lea r13, [rbx + rax + 4]
|
||||||
|
add r13, 4095
|
||||||
|
and r13, -4096
|
||||||
|
sfence
|
||||||
|
mov dx, [rel ghal_net_io_base]
|
||||||
|
add dx, VIRTIO_QUEUE_NOTIFY
|
||||||
|
mov ax, 1
|
||||||
|
out dx, ax
|
||||||
|
mov ecx, 0x20000000
|
||||||
|
.wait_tx:
|
||||||
|
cmp word [r13 + 2], r11w
|
||||||
|
je .tx_complete
|
||||||
|
pause
|
||||||
|
loop .wait_tx
|
||||||
|
.tx_fail:
|
||||||
|
stc
|
||||||
|
ret
|
||||||
|
.tx_complete:
|
||||||
|
inc word [rel ghal_net_tx_next_index]
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
|
||||||
|
ghal_net_tcp_checksum:
|
||||||
|
xor ebx, ebx
|
||||||
|
mov rsi, VIRTIO_NET_TX_BUFFER + 36
|
||||||
|
mov ecx, 8
|
||||||
|
call ghal_net_checksum_add
|
||||||
|
add ebx, 6
|
||||||
|
add ebx, r15d
|
||||||
|
mov rsi, VIRTIO_NET_TX_BUFFER + 44
|
||||||
|
mov ecx, r15d
|
||||||
|
call ghal_net_checksum_add
|
||||||
|
jmp ghal_net_checksum_fold
|
||||||
|
|
||||||
|
ghal_net_checksum_add:
|
||||||
|
.words:
|
||||||
|
cmp ecx, 2
|
||||||
|
jb .tail
|
||||||
|
movzx eax, word [rsi]
|
||||||
|
xchg al, ah
|
||||||
|
add ebx, eax
|
||||||
|
add rsi, 2
|
||||||
|
sub ecx, 2
|
||||||
|
jmp .words
|
||||||
|
.tail:
|
||||||
|
test ecx, ecx
|
||||||
|
jz .done
|
||||||
|
movzx eax, byte [rsi]
|
||||||
|
shl eax, 8
|
||||||
|
add ebx, eax
|
||||||
|
.done:
|
||||||
|
ret
|
||||||
|
|
||||||
|
ghal_net_checksum_fold:
|
||||||
|
mov eax, ebx
|
||||||
|
shr eax, 16
|
||||||
|
and ebx, 0xffff
|
||||||
|
add ebx, eax
|
||||||
|
mov eax, ebx
|
||||||
|
shr eax, 16
|
||||||
|
and ebx, 0xffff
|
||||||
|
add ebx, eax
|
||||||
|
not bx
|
||||||
|
xchg bl, bh
|
||||||
|
ret
|
||||||
|
%endif
|
||||||
|
|
||||||
ghal_net_io_base: dw 0
|
ghal_net_io_base: dw 0
|
||||||
ghal_block_io_base: dw 0
|
ghal_block_io_base: dw 0
|
||||||
ghal_net_pci_device: dd 0
|
ghal_net_pci_device: dd 0
|
||||||
|
|
@ -1294,6 +1519,10 @@ ghal_net_command_kind: db 0
|
||||||
ghal_net_matched_kind: db 0
|
ghal_net_matched_kind: db 0
|
||||||
ghal_net_expected_sequence: db 1
|
ghal_net_expected_sequence: db 1
|
||||||
ghal_net_resident_retry_count: db 0
|
ghal_net_resident_retry_count: db 0
|
||||||
|
%ifdef GHOS_NATIVE_ANCHOR_SERVICE
|
||||||
|
ghal_anchor_tcp_flags: db 0
|
||||||
|
ghal_anchor_tcp_payload_size: dw 0
|
||||||
|
%endif
|
||||||
|
|
||||||
msg_ghal_net_discovered: db "GHOS_GHAL_VIRTIO_NET=DISCOVERED", 13, 10, 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
|
msg_ghal_block_discovered: db "GHOS_GHAL_VIRTIO_BLOCK=DISCOVERED", 13, 10, 0
|
||||||
|
|
@ -1301,6 +1530,17 @@ msg_ghal_net_ready: db "GHOS_GHAL_VIRTIO_NET_QUEUE=DRIVER_OK", 13, 10, 0
|
||||||
msg_ghal_block_ready: db "GHOS_GHAL_VIRTIO_BLOCK_QUEUE=DRIVER_OK", 13, 10, 0
|
msg_ghal_block_ready: db "GHOS_GHAL_VIRTIO_BLOCK_QUEUE=DRIVER_OK", 13, 10, 0
|
||||||
msg_ghal_arp_ready: db "GHOS_GHAL_ARP_GATEWAY=VERIFIED", 13, 10, 0
|
msg_ghal_arp_ready: db "GHOS_GHAL_ARP_GATEWAY=VERIFIED", 13, 10, 0
|
||||||
msg_ghal_icmp_login_ready: db "GHOS_GHAL_ICMP_LOGIN=VERIFIED", 13, 10, 0
|
msg_ghal_icmp_login_ready: db "GHOS_GHAL_ICMP_LOGIN=VERIFIED", 13, 10, 0
|
||||||
|
%ifdef GHOS_NATIVE_ANCHOR_SERVICE
|
||||||
|
msg_ghal_anchor_http_ready: db "GHOS_NATIVE_ANCHOR_HTTP=RESPONSE_TX", 13, 10, 0
|
||||||
|
ghal_anchor_http_response:
|
||||||
|
db "HTTP/1.1 200 OK", 13, 10
|
||||||
|
db "Content-Type: application/json", 13, 10
|
||||||
|
db "Cache-Control: no-store", 13, 10
|
||||||
|
db "Connection: close", 13, 10
|
||||||
|
db "Content-Length: 286", 13, 10, 13, 10
|
||||||
|
db '{"schema":"guanghu.native-public-anchor/v1","anchor_id":"GLW-PUBLIC-NAV-ANCHOR-001","entry_path":"LL-CMPN-0001","world_node_id":"SYS-GLW-0001","repository_id":"REPO-012","branch":"main","code_entry":"https://guanghulab.com/code/bingshuo/guanghu-ice-heart","runtime":"GUANGHU_OS_NATIVE"}'
|
||||||
|
ghal_anchor_http_response_end:
|
||||||
|
%endif
|
||||||
msg_ghal_world_store_ready: db "GHOS_HLDP_WORLD_STORE=WRITE_READ_VERIFIED", 13, 10, 0
|
msg_ghal_world_store_ready: db "GHOS_HLDP_WORLD_STORE=WRITE_READ_VERIFIED", 13, 10, 0
|
||||||
msg_ghal_code_channel_store_ready: db "GHOS_CODE_CHANNEL_STORE=WRITE_READ_VERIFIED", 13, 10, 0
|
msg_ghal_code_channel_store_ready: db "GHOS_CODE_CHANNEL_STORE=WRITE_READ_VERIFIED", 13, 10, 0
|
||||||
msg_ghal_recovery_ready: db "GHOS_NATIVE_RECOVERY_BEACON=WRITE_READ_VERIFIED", 13, 10, 0
|
msg_ghal_recovery_ready: db "GHOS_NATIVE_RECOVERY_BEACON=WRITE_READ_VERIFIED", 13, 10, 0
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ while IFS= read -r argument; do layout_args+=("${argument}"); done \
|
||||||
-dGHOS_PHYSICAL_CANDIDATE=1 \
|
-dGHOS_PHYSICAL_CANDIDATE=1 \
|
||||||
-dGHOS_NATIVE_RESIDENT=1 \
|
-dGHOS_NATIVE_RESIDENT=1 \
|
||||||
-dGHOS_NATIVE_FINAL_RESIDENT=1 \
|
-dGHOS_NATIVE_FINAL_RESIDENT=1 \
|
||||||
|
-dGHOS_NATIVE_ANCHOR_SERVICE=1 \
|
||||||
"${native_root}/boot.asm" \
|
"${native_root}/boot.asm" \
|
||||||
-o guanghu-os-x86_64-bios-final-resident.img
|
-o guanghu-os-x86_64-bios-final-resident.img
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,17 @@ COMMIT_MAGIC = b"HLDP-CODE-COMMIT"
|
||||||
BRANCH_MAGIC = b"HLDP-BRANCH-MOVE"
|
BRANCH_MAGIC = b"HLDP-BRANCH-MOVE"
|
||||||
RECOVERY_MAGIC = b"HLDP-RECOVER-OS!"
|
RECOVERY_MAGIC = b"HLDP-RECOVER-OS!"
|
||||||
NATIVE_ACK_MAGIC = b"HLDP-NATIVE-ACK!"
|
NATIVE_ACK_MAGIC = b"HLDP-NATIVE-ACK!"
|
||||||
|
ANCHOR_PORT = 3922
|
||||||
|
ANCHOR_CLIENT_PORT = 40392
|
||||||
|
ANCHOR_CLIENT_SEQUENCE = 0x10203040
|
||||||
|
ANCHOR_BODY = (
|
||||||
|
b'{"schema":"guanghu.native-public-anchor/v1",'
|
||||||
|
b'"anchor_id":"GLW-PUBLIC-NAV-ANCHOR-001",'
|
||||||
|
b'"entry_path":"LL-CMPN-0001","world_node_id":"SYS-GLW-0001",'
|
||||||
|
b'"repository_id":"REPO-012","branch":"main",'
|
||||||
|
b'"code_entry":"https://guanghulab.com/code/bingshuo/guanghu-ice-heart",'
|
||||||
|
b'"runtime":"GUANGHU_OS_NATIVE"}'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def checksum(payload: bytes) -> int:
|
def checksum(payload: bytes) -> int:
|
||||||
|
|
@ -88,6 +99,62 @@ def authenticated_reply(frame: bytes, response_capability: bytes = NATIVE_ACK_MA
|
||||||
return bytes(reply)
|
return bytes(reply)
|
||||||
|
|
||||||
|
|
||||||
|
def tcp_frame(
|
||||||
|
flags: int,
|
||||||
|
sequence: int,
|
||||||
|
acknowledgement: int,
|
||||||
|
payload: bytes = b"",
|
||||||
|
) -> bytes:
|
||||||
|
tcp = bytearray(
|
||||||
|
struct.pack(
|
||||||
|
"!HHIIBBHHH",
|
||||||
|
ANCHOR_CLIENT_PORT,
|
||||||
|
ANCHOR_PORT,
|
||||||
|
sequence,
|
||||||
|
acknowledgement,
|
||||||
|
5 << 4,
|
||||||
|
flags,
|
||||||
|
16384,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
+ payload
|
||||||
|
)
|
||||||
|
pseudo = GATEWAY_IP + GUEST_IP + b"\0\x06" + struct.pack("!H", len(tcp))
|
||||||
|
tcp[16:18] = struct.pack("!H", checksum(pseudo + tcp))
|
||||||
|
ip = bytearray(
|
||||||
|
b"\x45\x00"
|
||||||
|
+ struct.pack("!H", 20 + len(tcp))
|
||||||
|
+ b"\x47\x41\x00\x00\x40\x06\x00\x00"
|
||||||
|
+ GATEWAY_IP
|
||||||
|
+ GUEST_IP
|
||||||
|
)
|
||||||
|
ip[10:12] = struct.pack("!H", checksum(ip))
|
||||||
|
return GUEST_MAC + PEER_MAC + b"\x08\x00" + bytes(ip) + bytes(tcp)
|
||||||
|
|
||||||
|
|
||||||
|
def verify_anchor_tcp(frame: bytes, expected_flags: int) -> tuple[int, int, bytes]:
|
||||||
|
assert frame[0:6] == PEER_MAC
|
||||||
|
assert frame[6:12] == GUEST_MAC
|
||||||
|
assert frame[12:14] == b"\x08\x00"
|
||||||
|
assert frame[23] == 6
|
||||||
|
assert frame[26:30] == GUEST_IP
|
||||||
|
assert frame[30:34] == GATEWAY_IP
|
||||||
|
assert checksum(frame[14:34]) == 0
|
||||||
|
total_length = int.from_bytes(frame[16:18], "big")
|
||||||
|
tcp = frame[34 : 14 + total_length]
|
||||||
|
assert int.from_bytes(tcp[0:2], "big") == ANCHOR_PORT
|
||||||
|
assert int.from_bytes(tcp[2:4], "big") == ANCHOR_CLIENT_PORT
|
||||||
|
assert tcp[13] == expected_flags
|
||||||
|
pseudo = GUEST_IP + GATEWAY_IP + b"\0\x06" + struct.pack("!H", len(tcp))
|
||||||
|
assert checksum(pseudo + tcp) == 0
|
||||||
|
return (
|
||||||
|
int.from_bytes(tcp[4:8], "big"),
|
||||||
|
int.from_bytes(tcp[8:12], "big"),
|
||||||
|
tcp[20:],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
global GUEST_IP, GATEWAY_IP, RELAY_IP
|
global GUEST_IP, GATEWAY_IP, RELAY_IP
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
|
@ -98,6 +165,7 @@ def main() -> None:
|
||||||
parser.add_argument("--final-resident", action="store_true")
|
parser.add_argument("--final-resident", action="store_true")
|
||||||
parser.add_argument("--recovery-token-file")
|
parser.add_argument("--recovery-token-file")
|
||||||
parser.add_argument("--login-only", action="store_true")
|
parser.add_argument("--login-only", action="store_true")
|
||||||
|
parser.add_argument("--anchor-http", action="store_true")
|
||||||
parser.add_argument("--guest-ip", default="172.16.0.6")
|
parser.add_argument("--guest-ip", default="172.16.0.6")
|
||||||
parser.add_argument("--peer-ip", default="172.16.0.1")
|
parser.add_argument("--peer-ip", default="172.16.0.1")
|
||||||
parser.add_argument("--relay-ip", default="43.153.193.169")
|
parser.add_argument("--relay-ip", default="43.153.193.169")
|
||||||
|
|
@ -127,6 +195,10 @@ def main() -> None:
|
||||||
commit_verified = False
|
commit_verified = False
|
||||||
branch_verified = False
|
branch_verified = False
|
||||||
recovery_verified = False
|
recovery_verified = False
|
||||||
|
anchor_syn_sent = False
|
||||||
|
anchor_syn_ack_verified = False
|
||||||
|
anchor_get_sent = False
|
||||||
|
anchor_http_verified = False
|
||||||
|
|
||||||
while time.monotonic() < deadline:
|
while time.monotonic() < deadline:
|
||||||
try:
|
try:
|
||||||
|
|
@ -139,6 +211,36 @@ def main() -> None:
|
||||||
continue
|
continue
|
||||||
if frame[12:14] != b"\x08\x00":
|
if frame[12:14] != b"\x08\x00":
|
||||||
continue
|
continue
|
||||||
|
if frame[23] == 6:
|
||||||
|
if not anchor_syn_ack_verified:
|
||||||
|
server_sequence, acknowledgement, payload = verify_anchor_tcp(frame, 0x12)
|
||||||
|
assert acknowledgement == ANCHOR_CLIENT_SEQUENCE + 1
|
||||||
|
assert payload == b""
|
||||||
|
anchor_syn_ack_verified = True
|
||||||
|
request = (
|
||||||
|
b"GET /v1/anchor HTTP/1.1\r\n"
|
||||||
|
b"Host: native.guanghulab.com\r\n"
|
||||||
|
b"Connection: close\r\n\r\n"
|
||||||
|
)
|
||||||
|
peer.sendto(
|
||||||
|
tcp_frame(
|
||||||
|
0x18,
|
||||||
|
ANCHOR_CLIENT_SEQUENCE + 1,
|
||||||
|
server_sequence + 1,
|
||||||
|
request,
|
||||||
|
),
|
||||||
|
qemu,
|
||||||
|
)
|
||||||
|
anchor_get_sent = True
|
||||||
|
continue
|
||||||
|
_, acknowledgement, payload = verify_anchor_tcp(frame, 0x19)
|
||||||
|
assert acknowledgement > ANCHOR_CLIENT_SEQUENCE + 1
|
||||||
|
header, body = payload.split(b"\r\n\r\n", 1)
|
||||||
|
assert b"HTTP/1.1 200 OK" in header
|
||||||
|
assert b"Content-Length: 286" in header
|
||||||
|
assert body == ANCHOR_BODY
|
||||||
|
anchor_http_verified = True
|
||||||
|
continue
|
||||||
sequence = int.from_bytes(frame[40:42], "big")
|
sequence = int.from_bytes(frame[40:42], "big")
|
||||||
if sequence <= 3:
|
if sequence <= 3:
|
||||||
magic = LOGIN_MAGIC
|
magic = LOGIN_MAGIC
|
||||||
|
|
@ -164,7 +266,11 @@ def main() -> None:
|
||||||
peer.sendto(ordinary_reply(frame), qemu)
|
peer.sendto(ordinary_reply(frame), qemu)
|
||||||
time.sleep(0.05)
|
time.sleep(0.05)
|
||||||
response_capability = NATIVE_ACK_MAGIC
|
response_capability = NATIVE_ACK_MAGIC
|
||||||
if args.final_resident and resident_login_count >= 3:
|
if (
|
||||||
|
args.final_resident
|
||||||
|
and resident_login_count >= 3
|
||||||
|
and (not args.anchor_http or anchor_http_verified)
|
||||||
|
):
|
||||||
response_capability = recovery_capability
|
response_capability = recovery_capability
|
||||||
recovery_verified = True
|
recovery_verified = True
|
||||||
reply = authenticated_reply(frame, response_capability)
|
reply = authenticated_reply(frame, response_capability)
|
||||||
|
|
@ -172,11 +278,19 @@ def main() -> None:
|
||||||
peer.sendto(reply, qemu)
|
peer.sendto(reply, qemu)
|
||||||
if repetition < 3:
|
if repetition < 3:
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
if (
|
||||||
|
args.anchor_http
|
||||||
|
and args.final_resident
|
||||||
|
and sequence == 6
|
||||||
|
and not anchor_syn_sent
|
||||||
|
):
|
||||||
|
peer.sendto(tcp_frame(0x02, ANCHOR_CLIENT_SEQUENCE, 0), qemu)
|
||||||
|
anchor_syn_sent = True
|
||||||
|
|
||||||
terminal = (
|
terminal = (
|
||||||
sequence == 3
|
sequence == 3
|
||||||
if args.login_only
|
if args.login_only
|
||||||
else recovery_verified
|
else recovery_verified and (not args.anchor_http or anchor_http_verified)
|
||||||
if args.final_resident
|
if args.final_resident
|
||||||
else sequence == 16
|
else sequence == 16
|
||||||
if args.resident
|
if args.resident
|
||||||
|
|
@ -199,6 +313,10 @@ def main() -> None:
|
||||||
f"resident_login_reply_count: {resident_login_count}\n"
|
f"resident_login_reply_count: {resident_login_count}\n"
|
||||||
f"recovery_reply_verified: {str(recovery_verified).lower()}\n"
|
f"recovery_reply_verified: {str(recovery_verified).lower()}\n"
|
||||||
f"final_resident_control: {str(args.final_resident).lower()}\n"
|
f"final_resident_control: {str(args.final_resident).lower()}\n"
|
||||||
|
f"anchor_syn_sent: {str(anchor_syn_sent).lower()}\n"
|
||||||
|
f"anchor_syn_ack_verified: {str(anchor_syn_ack_verified).lower()}\n"
|
||||||
|
f"anchor_get_sent: {str(anchor_get_sent).lower()}\n"
|
||||||
|
f"anchor_http_verified: {str(anchor_http_verified).lower()}\n"
|
||||||
"recovery_selected_by_native: false\n"
|
"recovery_selected_by_native: false\n"
|
||||||
"login_magic: HLDP-GHOS-LOGIN!\n"
|
"login_magic: HLDP-GHOS-LOGIN!\n"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ python3 "${source_root}/scripts/qemu-native-net-peer.py" \
|
||||||
--qemu-port "${qemu_port}" \
|
--qemu-port "${qemu_port}" \
|
||||||
--receipt "${test_root}/peer.hldp" \
|
--receipt "${test_root}/peer.hldp" \
|
||||||
--final-resident \
|
--final-resident \
|
||||||
|
--anchor-http \
|
||||||
--recovery-token-file "${token_file}" >"${test_root}/peer.log" 2>&1 &
|
--recovery-token-file "${token_file}" >"${test_root}/peer.log" 2>&1 &
|
||||||
peer_pid=$!
|
peer_pid=$!
|
||||||
set +e
|
set +e
|
||||||
|
|
@ -71,9 +72,13 @@ wait "${peer_pid}"
|
||||||
peer_pid=
|
peer_pid=
|
||||||
|
|
||||||
grep -q '^final_resident_control: true$' "${test_root}/peer.hldp"
|
grep -q '^final_resident_control: true$' "${test_root}/peer.hldp"
|
||||||
grep -q '^resident_login_reply_count: 3$' "${test_root}/peer.hldp"
|
awk -F': ' '$1 == "resident_login_reply_count" { found = 1; if ($2 < 3) exit 1 } END { if (!found) exit 1 }' \
|
||||||
|
"${test_root}/peer.hldp"
|
||||||
grep -q '^recovery_reply_verified: true$' "${test_root}/peer.hldp"
|
grep -q '^recovery_reply_verified: true$' "${test_root}/peer.hldp"
|
||||||
grep -q '^recovery_selected_by_native: false$' "${test_root}/peer.hldp"
|
grep -q '^recovery_selected_by_native: false$' "${test_root}/peer.hldp"
|
||||||
|
grep -q '^anchor_syn_ack_verified: true$' "${test_root}/peer.hldp"
|
||||||
|
grep -q '^anchor_http_verified: true$' "${test_root}/peer.hldp"
|
||||||
|
grep -q '^GHOS_NATIVE_ANCHOR_HTTP=RESPONSE_TX' "${test_root}/serial.log"
|
||||||
grep -q '^GHOS_NATIVE_RECOVERY_BEACON=WRITE_READ_VERIFIED' "${test_root}/serial.log"
|
grep -q '^GHOS_NATIVE_RECOVERY_BEACON=WRITE_READ_VERIFIED' "${test_root}/serial.log"
|
||||||
grep -q '^GHOS_DISK_PROOF_OBSERVED_AFTER_RESET=LBA134' "${test_root}/serial.log"
|
grep -q '^GHOS_DISK_PROOF_OBSERVED_AFTER_RESET=LBA134' "${test_root}/serial.log"
|
||||||
|
|
||||||
|
|
@ -158,6 +163,15 @@ resident_runtime:
|
||||||
code_commit_reply_verified: true
|
code_commit_reply_verified: true
|
||||||
branch_move_reply_verified: true
|
branch_move_reply_verified: true
|
||||||
sustained_login_replies_before_recovery: 2
|
sustained_login_replies_before_recovery: 2
|
||||||
|
native_anchor_service:
|
||||||
|
tcp_syn_ack: PASS_100
|
||||||
|
http_get_v1_anchor: PASS_100
|
||||||
|
response_schema: guanghu.native-public-anchor/v1
|
||||||
|
anchor_id: GLW-PUBLIC-NAV-ANCHOR-001
|
||||||
|
entry_path: LL-CMPN-0001
|
||||||
|
world_node_id: SYS-GLW-0001
|
||||||
|
repository_id: REPO-012
|
||||||
|
runtime: GUANGHU_OS_NATIVE
|
||||||
recovery_control:
|
recovery_control:
|
||||||
selected_by_native_runtime: false
|
selected_by_native_runtime: false
|
||||||
per_deployment_capability_required: true
|
per_deployment_capability_required: true
|
||||||
|
|
@ -167,6 +181,9 @@ recovery_control:
|
||||||
boundary:
|
boundary:
|
||||||
qemu_capability: 100
|
qemu_capability: 100
|
||||||
physical_server_capability: 0
|
physical_server_capability: 0
|
||||||
|
native_anchor_http_qemu_capability: 100
|
||||||
|
native_anchor_http_physical_capability: 0
|
||||||
|
code_channel_service_equivalence: 0
|
||||||
final_native_residency_proven: false
|
final_native_residency_proven: false
|
||||||
next_action: PHYSICAL_ONE_TIME_FINAL_RESIDENCY_AND_PROTECTED_RECOVERY_GATE
|
next_action: PHYSICAL_ONE_TIME_NATIVE_ANCHOR_HTTP_GATE_WITH_PROTECTED_RECOVERY
|
||||||
EOF
|
EOF
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue