New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
hnat导致wg/gre over ipv6转发速度极慢 #9
Comments
大雕那边也是,稀奇古怪的加速能关就关,最好的还是官方的加上插件 |
内网各种速度都很正常,就是ipv6隧道不太行 |
觉得官方好那你去用官方呗,跑这里ky很好玩? |
wg和硬nat是冲突的,只能二选一,无解 |
我在主楼也提到了,开启hnat时,走ipv4的wg速度是完全正常的,只有ipv6上的wg(以及gre、l2tp等)速度有问题 |
后续将参考小米原厂固件做一个ipv6 hook的开关,可以单独控制v6 hnat加速功能 |
有具体接口吗?hook_toggle 这个好像是全局的,目前 turboacc 已支持配置。 |
划分多个vlan转发到wan也会出现这个bug, 我实测下载2mbps 上传10mbps 关掉硬件加速之后就正常 , 不知道啥原因了 |
研究了一下,hnat + wireguard + ipv6会导致client端iperf udp dl每秒只有30pps,从抓包来看,client的网卡每秒是能收到几百pps的,但其中有大部分的包wireguard协议头前12字节会被替换成src mac和dst mac,因此这些包都会解包错误而被丢弃,丢包率90+% 从wireguard代码来看 // ./drivers/net/wireguard/send.c
void wg_packet_encrypt_worker(struct work_struct *work)
{
// ....
if (likely(encrypt_packet(skb,
PACKET_CB(first)->keypair))) {
// 这里会把skb->mac_header指向wireguard协议头
// 然后调用udp_tunnel6_xmit_skb往wan接口发送这个skb
wg_reset_packet(skb, true);
} else {
state = PACKET_STATE_DEAD;
break;
}
} 再看hnat的代码 // ./drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
static unsigned int mtk_hnat_nf_post_routing(
struct sk_buff *skb, const struct net_device *out,
unsigned int (*fn)(struct sk_buff *, const struct net_device *,
struct flow_offload_hw_path *),
const char *func)
{
// ....
// 这里会判断skb->mac_header是否有效
// 此时mac_header是指向wireguard协议头的位置,所以是有效的
if (unlikely(!skb_mac_header_was_set(skb)))
return 0;
// ....
switch (skb_hnat_reason(skb)) {
case HIT_UNBIND_RATE_REACH:
if (entry_hnat_is_bound(entry))
break;
if (fn && !mtk_hnat_accel_type(skb))
break;
// 每秒大于30pps后,后续的包会走到这里,ipv6 skb的fn指向hnat_ipv6_get_nexthop函数
if (fn && fn(skb, arp_dev, &hw_path))
break;
skb_to_hnat_info(skb, out, entry, &hw_path);
break;
// .....
}
static unsigned int hnat_ipv6_get_nexthop(struct sk_buff *skb,
const struct net_device *out,
struct flow_offload_hw_path *hw_path)
{
// 这里会往skb->mac_header指向的地址里填充src mac和dst mac
// 导致client端收到的wireguard包是错的
if (hw_path->flags & FLOW_OFFLOAD_PATH_PPPOE) {
memcpy(eth_hdr(skb)->h_source, hw_path->eth_src, ETH_ALEN);
memcpy(eth_hdr(skb)->h_dest, hw_path->eth_dest, ETH_ALEN);
return 0;
}
// ....
} 看起来是一个bug,对hnat并不太了解,不知道是wireguard内核代码的问题,还是hnat代码的问题 按照第一个思路,对wireguard代码做如下改动,测试了下,速率就正常了,但不知道有没有什么风险 if (likely(encrypt_packet(skb,
PACKET_CB(first)->keypair))) {
wg_reset_packet(skb, true);
// yc.lu add for coexistence with mtkhat
skb_unset_mac_header(skb);
skb_reset_inner_headers(skb);
} |
还是给hnat加上wg包识别比较好,各家都是自己处理硬nat和wg的兼容问题,不应该去修改wg代码 |
@ftdlyc 可以尝试下面这样修改hnat驱动。我这边没有wgv6的测试环境,烦请测试下能否正常使用 --- hnat_nf_hook-orig.c 2023-10-05 14:58:07.361987421 +0000
+++ hnat_nf_hook.c 2023-10-05 15:05:07.023465414 +0000
@@ -2159,9 +2159,15 @@ mtk_hnat_ipv6_nf_local_out(void *priv, s
if (unlikely(!skb_hnat_is_hashed(skb)))
return NF_ACCEPT;
+ ip6h = ipv6_hdr(skb);
+
+ if (ip6h->nexthdr != NEXTHDR_IPIP) {
+ hnat_set_head_frags(state, skb, 1, hnat_set_alg);
+ return NF_ACCEPT;
+ }
+
entry = &hnat_priv->foe_table_cpu[skb_hnat_ppe(skb)][skb_hnat_entry(skb)];
if (skb_hnat_reason(skb) == HIT_UNBIND_RATE_REACH) {
- ip6h = ipv6_hdr(skb);
if (ip6h->nexthdr == NEXTHDR_IPIP) {
/* Map-E LAN->WAN: need to record orig info before fn. */
if (mape_toggle) { |
@hanwckf 测试了下你的修改,速率正常,能解决问题 |
好的,晚点改上去 |
大致网络拓扑:
PC A====Router A==wg/gre over ipv6==Route B====PC B
192.168.0.0/24 172.16.0.0/24 192.168.1.0/24
由PC A访问PC B的速度只有2~10Mbps,但是使用wireguard over ipv4时网速正常。此前使用mt7621时无此问题。
通过‘echo 0 > /sys/kernel/debug/hnat/hook_toggle’关闭hnat后速度恢复正常。
The text was updated successfully, but these errors were encountered: