这段代码是Linux内核中网络层接收数据包的核心函数,其作用是接收一个sk_buff类型的数据包,并根据协议类型和目标地址等信息将其分发给对应的处理程序。该函数具体实现如下:
int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc, struct packet_type **ppt_prev)
{
struct sk_buff *skb = *pskb;
const struct net_device *dev = skb->dev;
u16 protocol = skb->protocol;
int ret;
/* 数据包过滤 */
if (unlikely(!dev->flags & IFF_UP)) {
goto drop;
}
/* 处理vlan标签 */
#ifdef CONFIG_VLAN_8021Q
if (skb_vlan_tag_present(skb) && !pfmemalloc) {
ret = skb_vlan_untag(skb);
if (ret < 0)
goto drop;
protocol = ntohs(skb->protocol);
}
#endif
#ifdef CONFIG_NETFILTER_INGRESS
/* 进行入站过滤 */
ret = nf_hook(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, skb,
dev, NULL, __nf_in_hook);
switch (ret) {
case NF_ACCEPT:
break;
case NF_DROP:
goto drop_nfdrop;
default:
goto out_unlock;
}
#endif
#ifdef CONFIG_NET_SCHED
/* 入队统计相关操作 */
out:
#ifndef CONFIG_CPUSETS
首先,该函数会获取传递进来的数据包指针和一些其他参数,然后进行设备状态检查(判断设备是否启动),如果设备未启动则直接将数据包丢弃(goto drop)。之后,该函数会处理VLAN标签(如果有的话),并根据协议类型和目标地址等信息将其分发给对应的处理程序。在这个过程中,还会进行入站过滤和入队统计相关操作。
需要注意的是,在进行vlan标签处理时,函数会检查是否为内存分配失败而调用本函数(pfmemalloc参数),如果是,则不进行vlan标签处理。在进行入站过滤时,函数会调用nf_hook()函数进行网络层的hook处理。最后,在完成所有操作之后,该函数返回0表示成功。