苹果设备在家里「无法验证」:从 iPad 日志一路追到联发科的连接跟踪补丁
排查日期:2026-11-03 ~ 2026-11-04
状态:已解决。根因是联发科补丁的内存重叠 Bug;修复已在路由器上持久生效,并复测通过。
先看结论
路由器固件(基于香蕉派官方仓库自编译的 BPI-R4 Pro OpenWrt)中,联发科的「DSCP 学习」补丁给连接跟踪(conntrack)加了一个 QoS 扩展(开关 net.netfilter.nf_conntrack_qos,默认为 1),却忘了在内核里登记这个扩展的结构体大小。
由于它实际只被分配了 0 字节,导致和随后加入的 NAT 扩展共用了同一块内存。路由器每转发一个包,都会把包的 TOS 字节写进这块内存,正好覆盖掉 NAT 记录的出口网卡编号 masq_index:
TOS =
0x00:网卡编号被覆盖成0,主线内核 NAT 的「出口网卡是否变更」检查刚好跳过0值,数据包正常通过;TOS =
0x02(ECN 的ECT(0))或0x20(DSCP):网卡编号变成2或32,与隧道口ipip6-wan的真实编号20对不上。NAT 误以为出口网卡发生了变化,于是直接删掉这条连接跟踪记录并静默丢弃当前数据包,不留任何计数,也不报任何错。
苹果设备默认对 TCP 开启 ECN,发出的上行数据包 TOS 几乎都是 0x02,导致每隔几个包就会触发一次「删连接 + 丢包」。苹果登录服务器因迟迟收不全请求而重置连接,iPad 上便弹出「无法验证」。
修复方案:将 net.netfilter.nf_conntrack_qos 设为 0 并写入 /etc/sysctl.conf。关闭后 ECN 和 DSCP 均恢复正常,硬件加速与下载速度不受影响。
环境信息
固件来源
因为需要 v6plus / MAP-E 等隧道支持,固件基于香蕉派官方 BPI-R4 Pro OpenWrt 开发仓库 构建。刷写与编译背景见前文:《Banana Pi BPI-R4 Pro OpenWrt固件刷写指南》。
与本次问题有关的配置
IPv4-over-IPv6 隧道使用
ip6tnl连接运营商 BR,fw4在隧道口执行 masquerade(SNAT)。卸载配置为
flow_offloading=1、flow_offloading_hw=1;SDK 另带/etc/flowtable.conf自定义表。已加载
br_netfilter,bridge-nf-call-iptables=1;开机脚本pppq-ebl默认设置qos_toggle=2。异常线索:
/proc/net/nf_conntrack的每个方向都多出了主线内核没有的tos=字段。
症状表现
iPad 连接家里 Wi-Fi 时,退出、登录、验证 Apple 账户均告失败,提示「无法验证」。系统日志报错
NSURLErrorDomain -1005(网络连接已中断)和AKAuthenticationError -7005。同一台 iPad 切换到手机热点后,验证一切正常。
家里的 Windows 台式机访问同样的苹果服务一直正常。
早期排查 Discord 语音断流问题时曾发现:iPad 发出的带 ECN 标记的 IPv4 包得不到及时确认,当时如果在路由器上强行清掉 ECN 标记就能恢复正常(后来为了排查根因撤掉了该临时规则)。
排查过程
1. 抓取 iPad 日志:协商了 ECN,带标记的包大量丢失
使用 pymobiledevice3 抓取 iPad 的 syslog,观察 akd(Apple 账户守护进程)访问苹果认证服务器(gsa.apple.com,仅支持 IPv4)的一条连接记录:
01.153 tcp_output flags=[SEC] (SYN,带 ECE+CWR,请求开启 ECN)
01.307 tcp_input flags=[S.E] (SYN-ACK,服务器同意 ECN)
01.308 写出 ClientHello(1534 字节)
02.558 才收到 ServerHello ← 间隔长达 1.25 秒,说明首个 ClientHello 丢了,靠超时重传才成功
02.577 TLS 握手完成,开始发 HTTP 请求(约 16 KB)
04.157 tcp_input flags=[R] ack=0 ← 收到 RST,连接被重置
连接结束时 iPad 内核打印的 TCP 统计摘要非常关键:
ECN: 0/1/1 ← ECN 已成功协商
bytes in/out: 5789/22814, retransmitted bytes: 9936
ecn packets sent/acked/marked/lost: 11/142947/0/8 ← 发出的 11 个带 ECN 标记的包里,丢了 8 个!
另一条并发连接则是发出 8 个丢了 5 个。随后 CFNetwork 报错 HTTP load failed, 16249/0 bytes (error code: -1005)——客户端发出了 16 KB 的请求体,但连一个字节的响应都没收到。
此外还有一个细节:收到的 RST 包只带 R 标志、不带 ACK,且序号正好等于客户端的 rcv_nxt。这是对端 TCP 栈在「本地根本没有这条连接状态」时的标准回应。
2. 为什么 Windows 电脑没事:默认不开 ECN
在 Windows 台式机上检查 TCP 全局参数:
netsh int tcp show global → ECN 功能 : disabled
Windows 默认关闭 TCP ECN,发出的包永远不带 ECN 标记;而 Linux 默认 tcp_ecn=2(仅在作为服务端且对方请求时才被动启用),作为客户端主动发起连接时也不会开启。唯独苹果设备默认主动开启 ECN,因此成了家里的「唯一受害者」。
3. 排除运营商问题:带 ECN 标记的 ICMP 全部正常
在 WSL 里用 ping -Q 发送 TOS 分别为 0、1、2、3 的 ICMP 包,测试目标包括路由器、8.8.8.8、1.1.1.1 以及苹果服务器 17.179.252.2:全部 0% 丢包。宿主机网卡抓包确认这些 ECN 标记确实发到了线上,回包也全部正常。
这说明运营商和 ipip6 隧道并不会无脑丢弃带 ECN 标记的包,问题只出在经过状态跟踪的 TCP(以及 UDP)流量上。
4. 在电脑上稳定复现:WSL 开启 ECN
在 WSL 里临时修改 net.ipv4.tcp_ecn,用 curl 向 https://gsa.apple.com/grandslam/GsService2 发送 20 KB 的随机 POST 数据:
默认设置 2 不主动开启 ECN;HTTP 401 表示随机 POST 数据被拒绝,属于预期结果。主动开启 ECN 后,curl 的完整报错为:
curl: (56) Recv failure: Connection reset by peer
现象与 iPad 分毫不差:开启 ECN 后,TLS 握手多出来的约 0.36 秒正是 ClientHello 丢失后触发超时重传的时间。这同时证明了有线网络同样会复现,彻底排除了 Wi-Fi 驱动或无线干扰的嫌疑。
注:
gsa.apple.com的证书链根证书为苹果自家的「Apple Root CA」,不在 Ubuntu 默认信任库中,因此测试时加了-k参数(已提前通过openssl校验过证书指纹,排除中间人干扰)。
5. 路由器三点同步抓包:数据包在路由器内部蒸发
SSH 登录路由器,在三个关键接口同时用 tcpdump 抓包(抓包统计显示内核缓冲区 dropped by kernel 均为 0):
br-lan:LAN 侧网桥,数据包刚进入路由器;ipip6-wan:隧道虚拟接口,NAT 转换之后、IPv6 封装之前;br-wan:WAN 侧接口,IPv6 封装之后。
观察一条开启 ECN 的连接中,上行数据包的流向(✗ 表示在 br-lan 抓到了,但没能走到 ipip6-wan 隧道口):
时间(s) 数据包 ECN标记 是否到达隧道口
0.117 ClientHello (517B) ECT(0) ✗ (在路由器内部蒸发)
0.477 ClientHello 重传 无 ✓
0.607 Finished (80B) ECT(0) ✗ (在路由器内部蒸发)
0.607 后续 5 个数据段 ECT(0) ✓
0.723 数据段 (2456B, GRO合并) ECT(0) ✗ (在路由器内部蒸发)
0.723 Finished 重传 无 ✓
0.723 数据段 ECT(0) ✓
0.724 数据段 (2456B) ECT(0) ✗ (在路由器内部蒸发)
...
规律非常明显:带 ECN 标记(ECT(0))的数据包有一部分在 br-lan 到 ipip6-wan 之间被路由器自己丢掉了(往往是一连串突发数据里的第一个包);而超时重传时因为内核自动退避去掉了 ECN 标记,重传包 100% 能够通过。另外,成功穿过的 ECT(0) 包在 WAN 口的外层 IPv6 头里也正常保留了 ECN 标记,实锤问题出在路由器内核内部。
同时,既然所有被丢的包都能在 br-lan 上被 tcpdump 看到,说明它们当时还没进入 flowtable 硬件/软件快速路径,走的是标准的 Linux 内核网络栈转发路径。
6. 常规计数器全部为零:诡异的静默丢包
在测试前后对比路由器的所有常规丢包计数器(网卡 rx/tx_dropped、/proc/net/snmp、/proc/net/netstat、conntrack 统计、nftables 规则计数):
网卡与 IP 协议栈丢包计数:变化为 0;
nftables中所有带counter的drop规则(包括fw4的 NAT 泄漏防护规则):变化为 0;conntrack invalid计数:仅在连接末尾增加 3 个(属于连接异常关闭阶段的附带现象)。
明明丢了十几个数据包,常规监控指标却一片祥和。这意味着大概率是某个内核 Netfilter 钩子函数直接返回了 NF_DROP。顺带一提,排查时也确认了路由器上没有残留的 legacy iptables 规则、没有启用任何透明代理插件,也没有配置复杂的策略路由。
7. 内核 Tracepoint 追踪:锁定 POSTROUTING 阶段的 Netfilter 钩子
启用内核自带的 skb:kfree_skb 跟踪点(可记录丢包原因 reason),先空跑 6 秒采集基线,再在 ECN 复现测试期间采集 6 秒:
统计 nf_hook_slow 触发 NETFILTER_DROP 的次数:
接着为该跟踪点挂载调用栈触发器(stacktrace if reason == NETFILTER_DROP),抓到了多出来的那部分丢包的完整调用栈:
kfree_skb_reason < nf_hook_slow < ip_output < ip_forward_finish
真相渐近:转发的 IPv4 数据包是在 POSTROUTING(ip_output)阶段被某个 Netfilter 钩子函数直接丢弃的。而在 POSTROUTING 阶段挂载的只有 NAT(masquerade)、MSS 钳制(仅处理 SYN 包)以及连接跟踪确认(nf_conntrack_confirm)。
8. Kprobe 挂载 NAT 函数:NAT 亲手删了连接并丢了包
利用 kprobe / kretprobe 动态探针挂载到 NAT 核心函数上进行验证:
nf_nat_inet_fn 返回丢包的次数与实际丢包数完全吻合。nf_ct_delete 的上述 23 次调用均来自:
nf_nat_inet_fn < nf_nat_ipv4_out < nf_hook_slow < ip_output
结论让人惊讶:正是 NAT 模块自己在出口阶段调用了 nf_ct_delete 删掉了这条连接的跟踪记录,并返回 NF_DROP 丢弃了当前包。
在主线 Linux 内核里,nf_nat_inet_fn 只有在检测到「masquerade 绑定的出口网卡发生变化(nf_nat_oif_changed)」时才会走这条删连接并丢包的分支。但我的隧道接口 ipip6-wan 全程根本没有变动过,为什么会触发这个分支?
9. 观察连接跟踪表:开 ECN 的连接在半路被反复「杀死重建」
在测试期间以 0.1 秒的间隔高频轮询 /proc/net/nf_conntrack:
【不开 ECN 的正常连接】
SYN_SENT → ESTABLISHED [ASSURED] pkts=3 → FIN_WAIT pkts=18 → TIME_WAIT pkts=19
【开启 ECN 的异常连接】
SYN_SENT → ESTABLISHED tos=20/0 [UNREPLIED] orig_pkts=1 → ESTABLISHED [ASSURED] pkts=3 ...
↑ 注意这里:明明已经握手完成,却突然变成 UNREPLIED 且包计数归 1!
当旧的连接跟踪记录被 NAT 误杀后,紧接着到达的下一个 TCP 数据包会因为内核默认开启了 nf_conntrack_tcp_loose=1(允许半路拾起已建立的 TCP 连接)而重新创建一条新的 conntrack 记录。这就是为什么连接没有当场暴毙,而是表现为「每发一阵数据就得献祭一个包用来删表重建」。
这里我还注意到一个极其反常的细节:线上抓包确认 SYN 包的 TOS 明明是 0x00,但连接跟踪表里刚建立连接时却显示 tos=20!当时百思不得其解,直到最后看懂了内存布局才恍然大悟(详见第 13 节):20 根本不是什么 TOS 值,而是隧道网卡 ipip6-wan 的 ifindex(网卡接口编号)!
10. 不只是 ECN:中途修改 DSCP 同样会触发
为了验证这个 Bug 针对的是整个 8 位 TOS 字节(而不仅仅是低 2 位的 ECN),我写了一个完全不用 ECN 的测试脚本:在 TLS 握手完成后,通过 setsockopt(IP_TOS) 动态修改 socket 的 DSCP 值再发送 HTTP 请求,测量收到响应的耗时:
结果非常清晰:只要发送请求时的 TOS 不是 0x00(无论是 0x00 → 0x20 还是全程 0x20),耗时都会精准增加约 360 ms(恰好是一次超时重传的时间),同时连接跟踪表里也能看到连接被删掉重建。也就是说,任何上行 IPv4 流量只要 TOS 非零,经过 masquerade 时都会中招,ECN 只是日常最容易触发它的场景。
11. 顺藤摸瓜找到内核开关:net.netfilter.nf_conntrack_qos
在路由器上检索与 tos / qos 相关的 sysctl 参数和内核符号表(/proc/kallsyms):
sysctl 参数:
net.netfilter.nf_conntrack_qos = 1 ← 主线内核根本没有这个参数!
内核符号:
nf_conntrack_qos_pernet_init ← conntrack 的 QoS 扩展(正是 tos= 字段的来源)
mtk_foe_entry_set_dscp ← 向联发科硬件 PPE 表项写入 DSCP
mtk_ppe_internal_debugfs_{open,read,write}_qos ← 对应 debugfs 下的 qos_toggle
起初我怀疑是联发科这个扩展故意设计成「检测到 TOS 变化就删掉连接重学」,但随后的源码比对推翻了这个猜测——不是设计逻辑蠢,而是写出了一个教科书级别的 C 语言内存重叠 Bug。
12. 开关对照实验:立竿见影
将 net.netfilter.nf_conntrack_qos 临时设为 0 进行对比测试:
开关为 net.netfilter.nf_conntrack_qos;DSCP 测试在连接中途将 TOS 改为 0x20。
关闭扩展后,ECN 连接的 TLS 握手耗时与不开 ECN 时完全一致;重新开启,问题立即复现。
13. 补丁溯源:内存重叠是如何发生的?
顺着源码树排查我在《Banana Pi BPI-R4 Pro OpenWrt固件刷写指南》中编译固件所用的官方仓库 BPI-SINOVOIP/BPI-R4PRO-8X-OPENWRT-V24.10.0-Master-Devel,在 target/linux/mediatek/patches-6.6/ 目录下找到了罪魁祸首:
999-3004-netfilter-add-DSCP-learning-flow-to-xt_FLOWOFFLOAD.patch999-3016-netfilter-add-DSCP-learning-flow-to-nft_flow_offload.patch
这两个联发科 SDK 补丁新增了 nf_conn_qos 连接跟踪扩展(也就是 /proc/net/nf_conntrack 里 tos= 的来源)和 nf_conntrack_qos sysctl 开关,本意是在 nft_flow_offload 的 flow add 阶段记录双向流量的 TOS 值,等攒够 30 个包后将学习到的 DSCP 写入硬件 PPE 表项(mtk_foe_entry_set_dscp)。
补丁本身既不比较 TOS,也绝不会主动删连接。 真正致命的缺陷在于:
漏登记扩展大小:补丁定义了
NF_CT_EXT_QOS扩展,却忘了在内核的nf_ct_ext_type_len[]数组里登记struct nf_conn_qos的长度!分配 0 字节导致内存重叠:由于登记长度为 0,内核在给连接分配
NF_CT_EXT_QOS扩展时,指针偏移量没有推进(只分了 0 字节)。紧接着,当数据包走到 masquerade 阶段分配NF_CT_EXT_NAT(struct nf_conn_nat)扩展时,NAT 扩展被严丝合缝地分配到了与 QoS 扩展完全相同的内存起始地址上!字段精准踩踏:这台路由器的内核默认未开启 PPTP(
# CONFIG_NF_CONNTRACK_PPTP is not set),因此struct nf_conn_nat结构体里的第一个成员就是int masq_index(用于记录 masquerade 出口网卡的ifindex)。而它的内存位置,恰好与struct nf_conn_qos的「原方向 TOS」字段完全重叠!
我在路由器上核对了网卡编号,ip link 显示隧道口 ipip6-wan 的 ifindex 恰好就是 20:
当
SYN包建立连接并经过 masquerade 时,NAT 把出口网卡编号20写进了nat->masq_index;所以打印/proc/net/nf_conntrack时,共用同一块内存的 QoS 扩展就莫名其妙地打印出了tos=20!当连接建立完成(
ESTABLISHED且ASSURED),后续转发包开始进入flow add逻辑,QoS 扩展把数据包的 TOS 字节写进这块内存,当场把nat->masq_index覆盖掉了!紧接着数据包在
POSTROUTING阶段走到主线内核的nf_nat_oif_changed(),其检查逻辑为:if (nat->masq_index && nat->masq_index != out->ifindex) { nf_ct_kill_acct(ct, ctinfo, skb); return NF_DROP; }如果数据包 TOS 为
0:masq_index被覆盖成0,if (nat->masq_index ...)条件为假,检查被直接跳过,数据包侥幸存活!如果数据包 TOS 为
0x02(ECN)或0x20(DSCP):masq_index被覆盖成2或32,既不为0、又不等于ipip6-wan的真实编号20。NAT 立即判定「出口网卡变了」,调用nf_ct_kill_acct()杀掉连接并返回NF_DROP!
这完美解释了第 5 节和第 8 节里观测到的所有现象:
为什么握手和重传包不丢?因为连接刚重建、还没拿到对端回包变成
ASSURED之前,flow add会提前返回,不去写 TOS;一旦连接变成ASSURED,下一个带 ECN 的包立刻写坏masq_index并自爆;为什么结尾会有几个
conntrack invalid?因为连接在最后阶段被误杀后,尾随其后的FIN包无法通过tcp_loose新建连接,被当成无主包丢弃。
巧合的是,社区里已经有开发者独立踩中并定位了完全相同的 Bug,开源在 yearsyan/mediatek-conntrack-qos-fix 仓库中(其排查的基线 Commit 56e0e77a 正好也是我当时编译固件所用的版本),并提供了修复补丁 999-3035-netfilter-fix-conntrack-qos-extension-size.patch。
补充:为什么最后会收到苹果服务器的 RST?
已排除原因:并非 NAT 删表重建后改变了源端口。对比 LAN 侧和隧道口的抓包,重建前后的 TCP 源端口完全一致。
合理推断:抓包确认
RST确实由远端服务器发出(TTL 与正常回包一致)。由于客户端在发送 16 KB 的认证请求体期间反复遭遇丢包与超时重传,耗时被大幅拉长,苹果前端负载均衡或服务端因超时提前关闭了连接状态;当客户端重传的后续分段姗姗来迟时,对端已无该连接记录,便直接回了不带ACK的RST。
修复方案与复测结果
1. 运行时持久化修复(无需重刷固件)
直接在路由器上关闭 nf_conntrack_qos,并将其写入 /etc/sysctl.conf(OpenWrt 在升级固件时默认也会保留该配置文件):
sysctl -w net.netfilter.nf_conntrack_qos=0
echo 'net.netfilter.nf_conntrack_qos=0' >> /etc/sysctl.conf
关闭该开关后,新建的连接不再分配 NF_CT_EXT_QOS 扩展,内存重叠问题自然消失。唯一的影响是硬件 PPE 表项不再学习 DSCP(保持为 0),且流量在连接建立后会立即下发给硬件加速,无需再苦等 30 个数据包,反而加快了硬件卸载的生效速度。
2. 修复前后复测
以下对比中,修复前为 nf_conntrack_qos=1,修复后为 nf_conntrack_qos=0。
关闭扩展后,ECN、DSCP 均恢复正常,下载性能无损。
应用修复后,家里 iPad 的 Apple 账户登录验证、Discord 语音等服务全部恢复丝滑。
3. 源码级根治方案(重编固件)
如果后续重新编译固件,并且确实需要硬件 PPE 的 DSCP 学习功能,可以在源码树的 target/linux/mediatek/patches-6.6/ 中合入 yearsyan/mediatek-conntrack-qos-fix 提供的 999-3035-netfilter-fix-conntrack-qos-extension-size.patch,补齐 nf_ct_ext_type_len 的大小注册即可。
附:排查走过的弯路(被排除的假设)
隧道 MTU / MSS 钳制:路由器已有 MSS clamping;将 WSL 网卡 MTU 手动降至 1280 后依然复现。
运营商或 BR 丢弃 ECN 包:
ping -Q测试全部 0% 丢包;三点抓包证实包丢在路由器内部,成功转发的包在外层 IPv6 头中也正常保留 ECN。Wi-Fi 驱动或无线干扰:纯有线连接的 WSL 开启
tcp_ecn=1后,仍可 100% 复现。Flowtable 软硬件加速出错:被丢的包都能在
br-lan抓到,尚未进入快速路径;当时 PPE 硬件表项也处于未绑定状态。防火墙或连接状态误判:丢包发生时,
nft规则计数器和conntrack invalid计数均无增长。隧道接口闪断:
kprobe确认出口始终是ipip6-wan,ifindex=20未变。NAT 重建时更换源端口:对比 LAN 侧和隧道侧抓包,源端口全程一致。
参考资料
Banana Pi BPI-R4 Pro OpenWrt固件刷写指南 - 彼方(前文:本机固件的编译背景与刷写流程)
yearsyan/mediatek-conntrack-qos-fix(该内存重叠 Bug 的根因分析与内核修复补丁
999-3035)BPI-SINOVOIP/BPI-R4PRO-8X-OPENWRT-V24.10.0-Master-Devel(引入问题的补丁
999-3004与999-3016所在目录)Banana Pi 论坛:Flowtable corrupts large TCP packets on BPI-R4-PRO-8X
BPI-R4PRO-4E 仓库 Issue #1(社区反馈开启
/etc/flowtable.conf后 SSH 连接偶发被重置,高度疑似同一内存重叠 Bug 所致)
附录:排查用到的关键命令备忘
1. 在 Linux / WSL 下复现 ECN 丢包
测试完成后,将 tcp_ecn 恢复为 2。
sysctl -w net.ipv4.tcp_ecn=1 # 主动发起 ECN 协商(默认 2)
head -c 15000 /dev/urandom | base64 -w0 > /tmp/body.txt
curl -4 -sSk -o /dev/null --data-binary @/tmp/body.txt \
-w 'code=%{http_code} tls=%{time_appconnect} total=%{time_total}\n' \
https://gsa.apple.com/grandslam/GsService2
sysctl -w net.ipv4.tcp_ecn=2
2. 发送带 ECN 标记的 Ping
ping -c 5 -Q 2 8.8.8.8 # 0=Not-ECT, 1=ECT(1), 2=ECT(0), 3=CE
3. 在 WAN 口抓取隧道封装后的数据包
抓取 ipip6 数据包,按内层目的 IP 17.157.64.66(0x119d4042)过滤:
tcpdump -ni br-wan -w /tmp/wan.pcap 'ip6 proto 4 and (ip6[56:4] = 0x119d4042 or ip6[52:4] = 0x119d4042)'
4. 开启内核丢包原因与调用栈追踪
使用 kfree_skb 跟踪点,用完务必关闭。
T=/sys/kernel/debug/tracing
echo 'protocol == 2048' > $T/events/skb/kfree_skb/filter
echo 'stacktrace if reason == 8' > $T/events/skb/kfree_skb/trigger # 8 对应 NETFILTER_DROP(具体数值以同目录 format 文件为准)
echo 1 > $T/events/skb/kfree_skb/enable
# ……执行复现测试……
echo 0 > $T/events/skb/kfree_skb/enable
echo '!stacktrace if reason == 8' > $T/events/skb/kfree_skb/trigger
5. 挂载 NAT kprobe 探针
以下命令适用于 ARM64,用完清理探针。
T=/sys/kernel/debug/tracing
echo 'r:ecnnatret nf_nat_inet_fn ret=$retval:u32' >> $T/kprobe_events
echo 'ret == 0' > $T/events/kprobes/ecnnatret/filter
echo 'p:ecndel nf_ct_delete' >> $T/kprobe_events
echo stacktrace > $T/events/kprobes/ecndel/trigger
# ……执行复现测试,查看 $T/trace……
# 清理探针:先 disable 并移除 trigger,再执行:
echo '-:ecnnatret' >> $T/kprobe_events
echo '-:ecndel' >> $T/kprobe_events