看了网上的一些对此函数的解析,有些比较旧了。我在这分析一下linux-3.0.8的代码。
netif_receive_skb()中有RPS,我们不看了,直接看__netif_receive_skb()。
static int __netif_receive_skb(struct sk_buff *skb)
{
struct packet_type *ptype, *pt_prev;
rx_handler_func_t *rx_handler;
struct net_device *orig_dev;
struct net_device *null_or_dev;
bool deliver_exact = false;
int ret = NET_RX_DROP;
__be16 type;
// netdev_tstamp_prequeue设置为0,表示可能有些帧的延时;默认为1。
//net_timestamp_check()是设置skb的tstamp值,此值是记录接收包的时间
if (!netdev_tstamp_prequeue)
net_timestamp_check(skb);
trace_netif_receive_skb(skb);
/* netpoll 需要处理这个帧的话,会调用netpoll_rx 处理*/
if (netpoll_receive_skb(skb))
return NET_RX_DROP;
//给设备的接口序号赋值
if (!skb->skb_iif)
skb->skb_iif = skb->dev->ifindex;
orig_dev = skb->dev;
//下面说的复位主要是校准对应的指针
skb_reset_network_header(skb);//skb->network_header = skb->data - skb->head;网络层头
skb_reset_transport_header(skb);// skb->transport_header = skb->data;传输层
skb_reset_mac_len(skb);//skb->mac_len = skb->network_header - skb->mac_header;链路层头长,mac地址长度
pt_prev = NULL;
rcu_read_lock();
another_round:
__this_cpu_inc(softnet_data.processed);
if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) {//如果是vlan要用的
skb = vlan_untag(skb);//vlan头数据的处理
if (unlikely(!skb))
goto out;
}
//…
//之前有说协议类型时有个ALL,这是给每个sniffer发一个
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);
/*
deliver_skb()就认为是pt_prev->func(skb,