免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5947 | 回复: 4
打印 上一主题 下一主题

udp 校验和 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-11-03 15:41 |只看该作者 |倒序浏览
在收到udp报文后
我的理解是会先进行校验和计算(伪头,头部,数据),校验和正确再进行后续操作,入队列
但在协议栈代码中[2.6.34 kernel]
udp_rcv() -> __udp4_lib_rcv()中,只有udp4_csum_init()初始化了校验和,但并没有判断校验和是否正确,所以一定会调用
__udp_lib_lookup_skb()和udp_queue_rcv_skb()开始udp的接收。这样的话,即使udp的校验和是错误的,协议栈也会接收,我哪里理解错了吗?
  1. int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
  2.                    int proto)
  3. {
  4.         struct sock *sk;
  5.         struct udphdr *uh;
  6.         unsigned short ulen;
  7.         struct rtable *rt = skb_rtable(skb);
  8.         __be32 saddr, daddr;
  9.         struct net *net = dev_net(skb->dev);

  10.         /*
  11.          *  Validate the packet.
  12.          */
  13.         if (!pskb_may_pull(skb, sizeof(struct udphdr)))
  14.                 goto drop;                /* No space for header. */

  15.         uh   = udp_hdr(skb);
  16.         ulen = ntohs(uh->len);
  17.         saddr = ip_hdr(skb)->saddr;
  18.         daddr = ip_hdr(skb)->daddr;

  19.         if (ulen > skb->len)
  20.                 goto short_packet;

  21.         if (proto == IPPROTO_UDP) {
  22.                 /* UDP validates ulen. */
  23.                 if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen))
  24.                         goto short_packet;
  25.                 uh = udp_hdr(skb);
  26.         }

  27.         if (udp4_csum_init(skb, uh, proto))
  28.                 goto csum_error;

  29.         if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
  30.                 return __udp4_lib_mcast_deliver(net, skb, uh,
  31.                                 saddr, daddr, udptable);

  32.         sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);

  33.         if (sk != NULL) {
  34.                 int ret = udp_queue_rcv_skb(sk, skb);
  35.                 sock_put(sk);

  36.                 /* a return value > 0 means to resubmit the input, but
  37.                  * it wants the return to be -protocol, or 0
  38.                  */
  39.                 if (ret > 0)
  40.                         return -ret;
  41.                 return 0;
  42.         }

  43.         if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
  44.                 goto drop;
  45.         nf_reset(skb);

  46.         /* No socket. Drop packet silently, if checksum is wrong */
  47.         if (udp_lib_checksum_complete(skb))
  48.                 goto csum_error;

  49.         UDP_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE);
  50.         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);

  51.         /*
  52.          * Hmm.  We got an UDP packet to a port to which we
  53.          * don't wanna listen.  Ignore it.
  54.          */
  55.         kfree_skb(skb);
  56.         return 0;
复制代码

论坛徽章:
0
2 [报告]
发表于 2011-11-03 16:00 |只看该作者
see udp_recvmsg()

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
3 [报告]
发表于 2011-11-03 16:49 |只看该作者
回复 1# qy5328464
的确是这样的。如果sk->sk_filter ==null,那么就直接放到对应的sock的sk_receive_queue,然后唤醒__skb_recv_datagram。

__skb_recv_datagram会调用udp_recvmsg,在udp_recvmsg中会进行校验和的检查。

论坛徽章:
0
4 [报告]
发表于 2011-11-04 09:39 |只看该作者
谢谢 crspo 和  瀚海书香 的回复。
的确,用户创建udp socket后,调用recvfrom()系统调用,会调用sock_common_recvmsg() -> udp_recvmsg(),它会从
sk_receive_queue上取报文,然后验证校验和是否正确。
也就是说,校验和不正确的udp报文,是在用户调用recvfrom等调用接收时才被检测出来的,而不是在报文刚被UDP模块处理时;这样,
一个检验和不正确的报文,仍会执行插入udp table,在udp table中查找这两步。
我的理解是:如果在UDP模块接收时处理,即__udp4_lib_rcv(),会节省插入和查找udp table的时间;
                 如果在用户接收时处理,即udp_recvmsg(),则会节省部分报文校验和的计算时间,因为到达UDP模块的报并不一定有socket来接收。
检验和的验证位置是因为上述原因吗?校验和计算比udp table查找更费时?

论坛徽章:
0
5 [报告]
发表于 2012-04-07 17:41 |只看该作者
本帖最后由 c04n05 于 2012-04-07 17:58 编辑
qy5328464 发表于 2011-11-04 09:39
谢谢 crspo 和  瀚海书香 的回复。
的确,用户创建udp socket后,调用recvfrom()系统调用,会调用sock_co ...

内核收到的报文要拷贝到用户空间,这个动作需要遍历一遍报文。计算报文的校验和也需要遍历一遍报文。
现在把这两个操作绑定到一块就节省了一次。

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP