Linux TCP/IP协议栈之Socket的实现分析(数据包的接收)
前面了解过sk有一个接收队列,用于存储接收到的skb,对于socket层面上来讲,数据接收,就是要把数据从这个队列中取出来,交给上层用户态。这里涉及到出队操作,但是,要了解如何出队,就得了解传输层协议如何入队。前面一直用tcp协议来分析,现在还没有把整个tcp栈分析出来,要再继续用tcp协议来分析,就有点问题了,所以,数据的接收和发送,都将以udp协议来分析。虽然它很简单,但同样也反应了socket层数据与接收的全部核心内容与思路。我以希望,下一步拿下tcp协议后,再把这部份的tcp实现补上来。
一、udp层的数据接收
udp层的数据接收,对于socket而言,就是接收队列的入队操作。在ip层中,如果是本地数据,则会交由ip_local_deliver_finish()函数处理,它会根据传输层协议的类型,交由相应的处理函数,对于udp协议而言,就是udp_rcv():
int udp_rcv(struct sk_buff *skb)
{
struct sock *sk;
struct udphdr *uh;
unsigned short ulen;
struct rtable *rt = (struct rtable*)skb->dst;
u32 saddr = skb->nh.iph->saddr;
u32 daddr = skb->nh.iph->daddr;
int len = skb->len;
if (!pskb_may_pull(skb, sizeof(struct udphdr)))
goto no_header;
uh = skb->h.uh;
ulen = ntohs(uh->len);
if (ulen > len || ulen < sizeof(*uh))
goto short_packet;
if (pskb_trim(skb, ulen))
goto short_packet;
if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0)
goto csum_error;
if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
return udp_v4_mcast_deliver(skb, uh, saddr, daddr);