链路层接收到数据包后会通过netif_receive_skb将数据包丢给网络层,而网络层处理接口就是ip_rcv。网络层接口都是通过网络层协议号从ptype_base散列表中找到相应的接收函数。ipv4的数据包类型为ip_packet_type,通过dev_add_pack注册到系统的ptype_base中。
ip_rcv功能:
1、首先会丢弃不是发往本地的数据报;
2、如果数据报是一个共享的数据包,就会复制一个副本,判断如下:其实就是判断skb的使用用户的数量
static inline struct sk_buff *skb_share_check(struct sk_buff *skb,
gfp_t pri)
{
might_sleep_if(pri & __GFP_WAIT);
if (skb_shared(skb)) {
struct sk_buff *nskb = skb_clone(skb, pri);
kfree_skb(skb);
skb = nskb;
}
return skb;
}
static inline int skb_shared(const struct sk_buff *skb)
{
return atomic_read(&skb->users) != 1;
}
3、判断数据包的长度,ip首部长度是否有效,如果有效就会调用ip_rcv_finish;
ip_rcv_finish的功能:
1、查找skb的路由,如果路由为空,需要去路由表中查找;路由表的查找以后学习
2、如果ip的首部长度大于5,说明有ip选项,需用通过ip_rcv_options处理ip选项
3、调用dst_input