netif_receive_skb()

本文深入探讨了Linux内核2.6.19版本中netif_receive_skb函数的实现细节,该函数负责处理接收的数据包,并通过各种过滤器进行传递。文章详细介绍了如何根据设备类型和数据包类型将数据包传递给相应的处理程序。
process_backlog()  --> netif_receive_skb()

/usr/src/linux-2.6.19/net/core/dev.c

int netif_receive_skb(struct sk_buff *skb)
{
    struct  packet_type  *ptype, *pt_prev;
    struct  net_device  *orig_dev;
    int ret = NET_RX_DROP;
    unsigned short type;

    if (skb->dev->poll && netpoll_rx(skb))
        return NET_RX_DROP;
    if (!skb->tstamp.off_sec)
        net_timestamp(skb);
    if (!skb->input_dev)
        skb->input_dev = skb->dev;

    orig_dev = skb_bond(skb);
    if (!orig_dev)
        return NET_RX_DROP;

    __get_cpu_var(netdev_rx_stat).total++;
    skb->h.raw = skb->nh.raw = skb->data;
    skb->mac_len = skb->nh.raw - skb->mac.raw;
    pt_prev = NULL;
    rcu_read_lock();

#ifdef CONFIG_NET_CLS_ACT
    if (skb->tc_verd & TC_NCLS) {
        skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
        goto ncls;
    }
#endif

    list_for_each_entry_rcu(ptype, &ptype_all, list) {
        if (!ptype->dev || ptype->dev == skb->dev) {
            if (pt_prev)
                ret = deliver_skb(skb, pt_prev, orig_dev);
            pt_prev = ptype;
        }
    }

#ifdef CONFIG_NET_CLS_ACT
    if (pt_prev) {
        ret = deliver_skb(skb, pt_prev, orig_dev);
        pt_prev = NULL; 
    } else {
        skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
    }
    ret = ing_filter(skb);    
    if (ret == TC_ACT_SHOT || (ret == TC_ACT_STOLEN)) {
        kfree_skb(skb);
        goto out;
    }
    skb->tc_verd = 0;
ncls:
#endif

    handle_diverter(skb);
    if (handle_bridge(&skb, &pt_prev, &ret, orig_dev))
        goto out;
    type = skb->protocol;

    list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {
        if (ptype->type == type &&
            (!ptype->dev || ptype->dev == skb->dev)) {
            if (pt_prev)
                ret = deliver_skb(skb, pt_prev, orig_dev);
            pt_prev = ptype;
        }
    }

    if (pt_prev) {
        ret =  pt_prev->func (skb, skb->dev, pt_prev, orig_dev);
    } else {
        kfree_skb(skb);
        ret = NET_RX_DROP;
    }

out:
    rcu_read_unlock();
    return ret;
}
<think>我们正在处理关于Linux内核网络子系统中`netif_receive_skb_internal`函数的使用和故障排除的问题。根据提供的引用,我们可以总结以下信息: 引用[2]提到:`netif_receive_skb_internal`函数是`netif_receive_skb`函数内部调用的实际处理数据包的函数。它处理网络数据包(由`struct sk_buff`表示)并负责将其传递给上层协议栈。 引用[3]提到:软中断处理程序`net_rx_action`会调用驱动程序的`poll()`函数,而`poll()`函数会调用`netif_receive_skb()`,然后逐一把接收到的数据包发送到上层。 引用[4]提到:`netif_rx`函数通过软中断将数据包提交给网络协议栈,以减少硬件中断处理时间。 因此,我们可以推断`netif_receive_skb_internal`是在软中断上下文中被调用的,用于将数据包传递到网络协议栈的上层。 关于使用和故障排除,我们可以从以下几个方面考虑: 1. **功能**:`netif_receive_skb_internal`负责处理接收到的数据包,包括检查数据包是否需要重定向(例如,用于数据包捕获或网络分流),以及将数据包传递给上层协议处理函数(如IP层)。 2. **常见问题**: - 数据包丢失:如果在该函数中处理数据包时出现问题,可能会导致数据包被丢弃。 - 性能问题:由于该函数在软中断上下文中运行,如果处理时间过长,可能会导致网络延迟增加或软中断负载过高。 3. **调试方法**: - 使用内核跟踪(tracepoint):`trace_netif_receive_skb`和`trace_netif_receive_skb_exit`可用于跟踪数据包在该函数中的处理情况。 - 使用`dropwatch`工具监视内核中数据包丢弃的情况。 - 使用`perf`工具分析软中断的CPU使用情况。 4. **使用场景**:该函数是内核网络栈接收路径的核心部分,任何通过网络接口进入系统的数据包都会经过此函数(除非使用了其他接收路径,如NAPI)。 下面我们根据以上信息组织回答。</think>### Linux内核netif_receive_skb_internal函数详解 #### 功能概述 `netif_receive_skb_internal()`是Linux内核网络子系统中的核心函数,主要负责将接收到的网络数据包(`struct sk_buff`)传递给上层协议栈。该函数在软中断(softirq)上下文中执行,其主要功能包括: 1. **数据包分发**:根据数据包类型(以太网类型)调用相应的协议处理函数(如IP、ARP等) 2. **分流处理**:支持RPS(Receive Packet Steering)实现多核负载均衡 3. **数据包捕获**:为`tcpdump`等工具提供抓包接口(`ptype_all`链表) 4. **拥塞控制**:实现GRO(Generic Receive Offload)数据包合并优化 5. **协议处理**:最终通过`__netif_receive_skb_core()`完成协议栈分发[^2] #### 典型调用路径 ```mermaid graph TD A[网卡硬件中断] --> B[NAPI poll] B --> C[netif_receive_skb] C --> D[netif_receive_skb_internal] D --> E[__netif_receive_skb_core] E --> F[IP/ARP协议处理] ``` #### 常见故障排查 1. **数据包丢失**: - 检查`/proc/net/softnet_stat`确认"dropped"计数 - 使用`dropwatch`工具监控丢包位置 ```bash $ dropwatch -l kas ``` 2. **CPU瓶颈**: - 通过`top`观察`si`(软中断)利用率 - 使用`perf`定位热点函数: ```bash $ perf record -e softirq:net_rx_action -ag ``` 3. **协议栈异常**: - 启用动态调试:`echo 'file net/core/dev.c +p' > /sys/kernel/debug/dynamic_debug/control` - 使用`ftrace`跟踪函数调用: ```bash $ echo netif_receive_skb_internal > set_ftrace_filter $ echo function > current_tracer ``` #### 性能优化建议 1. **调整GRO/GSO参数**: ```bash $ ethtool -K eth0 gro on $ sysctl -w net.core.netdev_max_backlog=30000 ``` 2. **启用RPS**(多核系统): ```bash # 将CPU掩码写入对应设备的rps_cpus $ echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus ``` 3. **调整NAPI权重**: ```bash $ sysctl -w net.core.dev_weight=600 ``` #### 使用场景 该函数主要应用于: 1. 网络设备驱动接收路径 2. 虚拟网络设备(veth, bridge)的数据转发 3. 内核网络协议栈开发 4. XDP(eXpress Data Path)后处理阶段[^3] > **关键设计原理**:通过软中断延迟处理机制(softirq),在保证吞吐量的同时减少硬件中断时间,这对高速网络设备尤为重要[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值