Linux内核:从底层向上分析传输层之UDP协议
作者:网络转载 发布时间:[ 2012/12/27 10:30:20 ] 推荐标签:
/*
* All we need to do is get the socket, and then do a checksum.
*/
int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
unsigned long daddr, unsigned short len,
unsigned long saddr, int redo, struct inet_protocol *protocol)
{
struct sock *sk;
struct udphdr *uh;
unsigned short ulen;
int addr_type = IS_MYADDR;
if(!dev || dev->pa_addr!=daddr)//检查这个数据包是不是发送给本地的数据包
addr_type=ip_chk_addr(daddr);//该函数定义在devinet.c中,用于检查ip地址是否是本地或多播、广播地址
/*
* Get the header.
*/
uh = (struct udphdr *) skb->h.uh;//获得UDP数据报的报头
ip_statistics.IpInDelivers++;
/*
* Validate the packet and the UDP length.
*/
ulen = ntohs(uh->len);
//参数len表示ip负载长度(IP数据报的数据部分长度)= UDP数据包头+UDP数据包的数据部分+填充部分长度
//ulen表示的是UDP数据报首部和负载部分的长度,所以正常情况下len>=ulen
if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh))
{
printk("UDP: short packet: %d/%d
", ulen, len);
udp_statistics.UdpInErrors++;
kfree_skb(skb, FREE_WRITE);
return(0);
}
if (uh->check && udp_check(uh, len, saddr, daddr)) //进行UDP数据包校验
{
/* <mea@utu.fi> wants to know, who sent it, to
go and stomp on the garbage sender... */
printk("UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d
",
ntohl(saddr),ntohs(uh->source),
ntohl(daddr),ntohs(uh->dest),
ulen);
udp_statistics.UdpInErrors++;
kfree_skb(skb, FREE_WRITE);
return(0);
}
len=ulen;//对len赋值为实际的UDP数据报长度
#ifdef CONFIG_IP_MULTICAST//对多播情况进行处理
if (addr_type!=IS_MYADDR)
{
/*
* Multicasts and broadcasts go to each listener.
*/
struct sock *sknext=NULL;//next指针
/*get_sock_mcast 获取在对应端口的多播套接字队列
*下面函数的参数依次表示:sock结构指针,本地端口,远端地址,远端端口,本地地址
*/
sk=get_sock_mcast(udp_prot.sock_array[ntohs(uh->dest)&(SOCK_ARRAY_SIZE-1)], uh->dest,
saddr, uh->source, daddr);
if(sk)
{
do
{
struct sk_buff *skb1;
sknext=get_sock_mcast(sk->next, uh->dest, saddr, uh->source, daddr);//下一个满足条件的套接字
if(sknext)
skb1=skb_clone(skb,GFP_ATOMIC);
else
skb1=skb;
if(skb1)
udp_deliver(sk, uh, skb1, dev,saddr,daddr,len);//对满足条件的套接字调用发送函数发送
sk=sknext;
}
while(sknext!=NULL);
}
else
kfree_skb(skb, FREE_READ);
return 0;
}
#endif
sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
if (sk == NULL) //没有找到本地对应的套接字,则进行出错处理
{
udp_statistics.UdpNoPorts++;
if (addr_type == IS_MYADDR)
{
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);//回复ICMP出错报文,目的主机不可达
}
/*
* Hmm. We got an UDP broadcast to a port to which we
* don't wanna listen. Ignore it.
*/
skb->sk = NULL;
kfree_skb(skb, FREE_WRITE);
return(0);
}
return udp_deliver(sk,uh,skb,dev, saddr, daddr, len);//调用函数发送套接字
}
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11