mirror of
https://github.com/kvcache-ai/AgentENV.git
synced 2026-11-05 01:17:36 +00:00
[PR #409] [MERGED] fix(sandbox): announce guest MAC changes via arp_notify #412
Labels
No labels
bug
documentation
enhancement
enhancement
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
kvcache-ai/AgentENV#412
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/kvcache-ai/AgentENV/pull/409
Author: @dushulin
Created: 10/21/2026
Status: ✅ Merged
Merged: 10/22/2026
Merged by: @yingdi-shan
Base:
main← Head:fix/fixed-guest-mac📝 Commits (2)
e9cc9a9fix(sandbox): set a fixed guest MAC so udev does not rewrite eth01898468fix(sandbox): announce guest MAC changes via arp_notify📊 Changes
2 files changed (+6 additions, -0 deletions)
View changed files
📝
docs/src/internals/networking.md(+2 -0)📝
src/sandbox/firecracker/sandbox.rs(+4 -0)📄 Description
What
冷启动(
start_fresh)时在 kernel cmdline 的ip=参数之后追加sysctl.net.ipv4.conf.all.arp_notify=1,让 guest 内核在eth0的 MAC 变化时主动发 gratuitous ARP。同时在docs/src/internals/networking.md的 Address Plan 一节补充说明。本 PR 最初的版本是给
eth0配置固定的guest_mac。按 #407 里维护者的建议改为arp_notify,固定 MAC 的改动已撤回,网卡仍是guest_mac = None。对main的净改动只有一个常量、一行append_boot_arg和一段文档。Why
详见 #407,简述如下:
start_fresh添加eth0时没有guest_mac,guest 的 virtio_net 随机分配 MAC。pivot-init交给 systemd(>= 242)后,systemd-udevd按自带的99-default.link(MACAddressPolicy=persistent)把随机 MAC 改写掉,且不发 gratuitous ARP。tap0上169.254.0.21的 neighbour 表项仍指向启动时的 MAC,host 发往 guest 的帧被丢弃。proxy 的连接一直等到 5s connect timeout 后返回502,直到表项老化、重新解析为止(复现中约 43s)。arp_notify的取值是MAXCONF(all, dev),所以all=1对eth0生效。MAC 变化(NETDEV_CHANGEADDR)时 guest 内核发一个 gratuitous ARP,tap0上的表项立即被覆盖成新 MAC,不必等老化。相比固定 MAC:
MACAddressPolicy=random也会改写内核报告为NET_ADDR_PERM的 MAC;.link里显式写MACAddress=同样会改。Related issue
Closes #407
Scope and non-goals
start_fresh追加一个 boot arg。DEFAULT_BOOT_ARGS:配置文件不会叠加config/default.toml,自定义了firecracker.boot_args的部署也需要这个参数。tap0的 neighbour 参数,不往用户 rootfs 注入.link文件,也不加静态 neighbour 表项(理由见 #407 的 Alternatives considered)。Design and behavior changes
ip=之后、custom extensionextraBootArgs之前,extension 仍可以追加或覆盖。arp_notify打开后,guest 在 link up 和 MAC 变化时各多发一个 gratuitous ARP。这些帧只出现在 slot 私有的 TAP 链路上。Compatibility and operations
firecracker.boot_args的部署同样生效。arp_notify为 1;已有快照不变。sysctl.*形式的 cmdline 需要 guest kernel >= 5.8(默认的vmlinux-6.1.175满足);更老的 guest 内核会忽略这个参数,行为与现在相同。Validation
make fmtmake clippymake test-unit(只跑了其中的cargo test -p agentenv --lib,见下)make -C services test(required whenservices/changes)maketargetCommands and results:
线上验证:在一个下游部署里,把一台节点换成包含此改动的构建做 canary,环境与 #407 相同(KVM,Firecracker
1.15.1-patch-v1,guest kernelvmlinux-6.1.175)。使用 #407 中的 Image A(Ubuntu 24.04,systemd 255),方法与 #407 一致:在 slot netns 里运行ip -timestamp monitor neigh,每 250 ms 请求一次/proxy/health。204之后 154×502(每次 5.00 s,约 43 s)204,最大 9 mstap0neighbourSTALE→FAILED→ 新 MACPROBE/FAILEDarp_notify(all / default / eth0)eth0addr_assign_typeNET_ADDR_SET,已被 udev 改写)修改后,guest 的
/proc/cmdline末尾为... ip=169.254.0.21::169.254.0.22:255.255.255.252:instance:eth0:off:<dns> sysctl.net.ipv4.conf.all.arp_notify=1。16 个并发沙箱的tap0表项都是同一模式:随机 MAC → udev 改写后的 MAC,切换间隔约 1 s。另外在同一台节点上做了一组只改
arp_notify的对照:在 guest 内用ip link set eth0 address ...(与 udev 同样走 rtnetlink)改 MAC。arp_notify=0时 39 s 内 156 次502(每次 5 s),表项经历STALE→PROBE→FAILED后才切到新 MAC;只把all设为 1、eth0保持 0 时,240 次全部204,最大 5 ms,表项立即被覆盖。Skipped checks and reasons:
make test-unit中需要 capability runner 的--ignored测试,以及 Rust 集成测试:本地没有运行(需要 root / KVM 环境)。改动只是一个 boot arg,已用上面的 canary 做了端到端验证。services/,也没有生成代码;不涉及性能。Risks and reviewer notes
sysctl.d把net.ipv4.conf.all.arp_notify显式设回 0,并且在 udev 改写 MAC 之前生效,这个修复就不起作用。默认的 systemd 发行版不会这样配置。src/sandbox/firecracker/sandbox.rs中start_fresh的append_boot_arg调用位置。Checklist
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.