当前位置: 首页 > news >正文

跟踪napi_gro_receive_entry时IP头信息缺失的分析

问题描述

在使用eBPF程序跟踪napi_gro_receive_entry内核跟踪点时,发现获取到的IP头部字段(如saddrdaddrprotocol)为空值。

代码如下:

/* 自定义结构体来映射 napi_gro_receive_entry tracepoint 的 format */
struct napi_gro_receive_entry_data {
    unsigned short common_type;
    unsigned char common_flags;
    unsigned char common_preempt_count;
    int common_pid;

    /* 以下字段根据 format 来定义 */
    char name[4];      // __data_loc char[]
    unsigned int napi_id;
    unsigned short queue_mapping;
    const void *skbaddr; // skbaddr 字段,用来访问 skb 数据
    bool vlan_tagged;
    unsigned short vlan_proto;
    unsigned short vlan_tci;
    unsigned short protocol;
    unsigned char ip_summed;
    unsigned int hash;
    bool l4_hash;
    unsigned int len;
    unsigned int data_len;
    unsigned int truesize;
    bool mac_header_valid;
    int mac_header;
    unsigned char nr_frags;
    unsigned short gso_size;
    unsigned short gso_type;
};
//ip头里面的信息为空
SEC("tp/net/napi_gro_receive_entry")
int trace_napi(struct napi_gro_receive_entry_data *ctx)
{
    // 获取当前进程 PID
    int pid = bpf_get_current_pid_tgid();

    bpf_printk("Hello!!! \n");

    // 读取 IP 头中的 protocol 字段
    u8 protocol; 
    
    struct sk_buff *skb = (struct sk_buff *)ctx->skbaddr;
    if(skb == NULL){
        bpf_printk("skb is NULL \n");
        return 0;
    }

    struct iphdr *ip = (struct iphdr *)(BPF_CORE_READ(skb, head) +
                            BPF_CORE_READ(skb, network_header));
    if(ip == NULL){
        bpf_printk("ip is NULL \n");
        return 0;
    }

    protocol = BPF_CORE_READ(ip, protocol);
    // 如果协议字段无效,返回
    if (protocol < 0) {
        bpf_printk("protocol is NULL \n");
        return 0;
    }
    //输出协议源IP字段
    __u32 saddr = BPF_CORE_READ(ip, saddr);
    bpf_printk("Source IP: %d.%d.%d.%d\n",
               (saddr >> 24) & 0xFF,
               (saddr >> 16) & 0xFF,
               (saddr >> 8) & 0xFF,
               saddr & 0xFF);
    //输出协议协议字段
    bpf_printk("protocol: %d \n", protocol);
    return 0;

}

 输出结果如下:

 发现读取到的IP头部信息(iphdr结构中的内容)是空的,但是可以确定获取到了skb以及iphdr结构体。

问题分析:(deepseek解答)

  1. GRO合并未完成
    GRO机制会对多个分片报文进行重组,此时network_header可能仅指向首个分片的头部位置。当处理后续分片时,skb->network_header可能尚未更新为有效偏移量‌。

  2. 协议头初始化时序
    在GRO处理路径中,skb->transport_headerskb->network_header的初始化可能延迟到分片重组完成后进行。过早访问会导致读取到内核未初始化的内存区域‌。

  3. SKB共享状态干扰
    skb被克隆(skb_clone())时,多个副本共享数据缓冲区。此时直接访问skb->head + skb->network_header可能触发内存越界,因为克隆操作的元数据更新存在延迟‌。

 以上给出了deepseek的解释,但是本人并没有验证,后期会去深入源码实现来探讨这个问题。

相关文章:

  • leetcode153 寻找旋转排序数组中的最小值 思考过程
  • BambuStudio学习笔记:MultiMaterialSegmentation
  • Docker 入门与实战指南
  • 视频推拉流:EasyDSS平台直播通道重连转推失败原因排查与解决
  • Python 逆向工程:2025 年能破解什么?
  • 云上特权凭证攻防启示录:从根账号AK泄露到安全体系升级的深度实践
  • 扫雷小游戏
  • 汇川EASY系列之以太网通讯(套接字socket做主站)
  • 蓝桥杯javaB组备战第二天 题目 区间次方和 编号3382
  • Linux中grep指令
  • yum修改阿里云
  • 致远互联FE协作办公平台 存在SQL注入漏洞(DVB-2025-8942)
  • WHAT - 前端性能监控和错误追踪(Sentry 篇)
  • 爬取动态数据,爬取持久化数据
  • docker-compose Install m3e(fastgpt扩展) GPU模式
  • 官宣 | Fluss 0.6 发布公告
  • Vue 实现AI对话和AI绘图(AIGC)人工智能
  • redux_旧版本
  • Matlab 多项式拟合点法线(二维)
  • 【每日学点HarmonyOS Next知识】防止重复点击、对话框收拾拦截、自定义键盘焦点、页面层级、自定义对话框创建
  • 林州风景网站建设的目的/seo接单平台
  • 福州网站建设公司哪家好/免费广告推广
  • 新手如何做网站的教程/营销方案怎么写
  • 周口哪里有做网站的/windows优化大师
  • 赌博类网站开发犯罪吗/宁波seo快速优化公司
  • 品牌网站怎么建设/宁波seo推广