You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux内核使用Raw socket发包高速率下死机,是否为正确实现方案?

内核态套接字发送代码问题排查

在内核中使用socket发送数据包是合法的实现方案,kernel_sendmsg是内核提供的标准原生接口,你遇到的高负载死机问题是代码逻辑缺陷导致,和方案本身无关。

现有代码的致命缺陷

  • 内存泄漏问题:当前仅当kernel_sendmsg返回值大于等于0时才会释放frame缓冲区,一旦发送失败进入错误返回分支,frame不会被释放,高发送速率下会快速耗尽系统内存,触发内核OOM panic。
  • 空指针风险:代码中直接使用外部sock变量,未做空指针合法性校验,若套接字处于未初始化、已释放或异常关闭状态,高并发场景下传入野指针调用kernel_sendmsg会直接触发空指针引用崩溃。
  • 上下文适配问题:kernel_sendmsg属于可能阻塞的接口,如果你的send_packet函数是在中断、软中断等原子上下文,或是持有自旋锁的场景下调用,高负载下触发进程调度会直接抛出内核BUG死机。
  • 入参校验缺失:没有判断传入的size是否小于ETH_HLEN,若传入的报文长度不足,len = size - ETH_HLEN会得到负值,赋值给无符号类型的iov_len后会变成超大值,导致内存越界访问崩溃。

优化建议

  1. 首先修复内存泄漏、入参校验类基础问题,修复后代码参考:
bool send_packet(uint8_t *frame, const uint32_t size)
{
    int len, ret;
    struct iphdr *ip;
    struct msghdr msg;
    struct kvec vec;

    // 增加入参合法性校验
    if (unlikely(!frame || size <= ETH_HLEN || !sock)) {
        kfree(frame);
        return false;
    }

    ip = (struct iphdr*)(frame + ETH_HLEN); 

    tgb_pr_debug("packet ip version : %d\n",ip->version);
    tgb_pr_debug("packet from %pI4 to %pI4\n",&ip->saddr, &ip->daddr);
    tgb_pr_debug("packet ip protocol : %d\n",ip->protocol);

    memset(&msg,0,sizeof(msg));

    len = size - ETH_HLEN;
    vec.iov_base = ip;
    vec.iov_len = len;

    ret = kernel_sendmsg(sock,&msg,&vec,1,len);
    if (ret < 0) {
        pr_err("sendmsg return code %d\n",ret);
        kfree(frame); // 错误分支补充缓冲区释放逻辑
        return false;
    }

    kfree(frame);
    return true;
}
  1. 如果你当前的调用上下文是原子上下文无法接受阻塞,建议替换发送方案,改用dev_queue_xmit直接向网卡提交skb发送,性能更高且不存在阻塞风险。

内容的提问来源于stack exchange,提问作者Jordan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 06:15:05