macOS开启PMTU发现时,路径MTU缓存能否自动更新?
问题解答:开启
net.inet.tcp.path_mtu_discovery后MTU缓存是否自动更新? 核心结论
开启net.inet.tcp.path_mtu_discovery后,你通过sysctl NET_RT_DUMP获取的路由表中的rt_msghdr.rt_metrics.rmx_mtu(路径MTU缓存)会自动更新。
详细说明
macOS的TCP栈在开启该标志后,会自动执行路径MTU发现(PMTUD)流程:
- 当TCP发送的数据包设置了DF(不分片)位,且在传输路径中遇到MTU更小的节点时,对方会返回ICMP“需要分片但DF位已置位”的错误。
- 系统收到该错误后,会自动更新对应目的地址路由条目中的
rmx_mtu值,这个更新会同步到全局路由缓存中,你通过sysctl轮询可以获取到最新的MTU数据。
注意事项(结合你的场景)
- 触发条件:只有当有实际的TCP流量经过对应目的路径时,才会触发PMTUD并更新MTU缓存;如果没有流量,系统不会主动探测路径MTU。
- 轮询策略:你当前通过
sysctl轮询路由表的方式可以拿到更新后的MTU,但需要合理设置轮询间隔,避免过于频繁的轮询带来性能开销。 - UDP场景:PMTUD默认只针对TCP协议,如果你需要处理UDP流量,需要自行在UDP数据包上设置DF位,并手动处理ICMP错误来更新MTU缓存,系统不会自动维护UDP路径的MTU。
你的场景与代码
你创建了一个虚拟接口,接收所有出站数据包,封装额外头部后通过物理适配器转发至最终目的地。为避免分片,计划通过物理接口与目的地间的PMTU减去封装开销来设置虚拟适配器的MTU,为此你通过sysctl轮询macOS的全局MTU缓存,相关代码如下:
size_t sz_needed = 0; std::vector<char> route_table; std::array<int, kSysctlMibLength> mib; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = 0; mib[4] = NET_RT_DUMP; mib[5] = 0; // first check the size if (sysctl(mib.data(), kSysctlMibLength, nullptr, &sz_needed, nullptr, 0) < 0) { return {}; } // allocate needed size for pba route_table.reserve(sz_needed); // than I get the route table contents if (sysctl(mib.data(), kSysctlMibLength, route_table.data(), &sz_needed, nullptr, 0) < 0) { return {}; } // now we need to get the rt_msghdr.rt_metrics.rmx_mtu /* MTU for this path */
内容的提问来源于stack exchange,提问作者Zohar81
相关产品推荐
相关产品推荐

