网络层对数据包处理完成后,会调用传输层的handler进行后续处理,UDP层的handler是在inet初始化注册的。

inet_initinet_add_protocol(&udp_protocol, IPPROTO_UDP)

udp_protocol定义如下:

static struct net_protocol udp_protocol = {.early_demux =  udp_v4_early_demux,.early_demux_handler =  udp_v4_early_demux,.handler =  udp_rcv,.err_handler = udp_err,.no_policy =   1,
};

udp_rcv 直接调用__udp4_lib_rcv进行处理:

  1. 对udp数据包进行检查
  2. 查找到数据包对应的socket(udp_table)
  3. 将数据包放入socket的队列中。
int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,int proto)
{struct sock *sk;struct udphdr *uh;unsigned short ulen;struct rtable *rt = skb_rtable(skb);__be32 saddr, daddr;struct net *net = dev_net(skb->dev);bool refcounted;/**  Validate the packet.*/if (!pskb_may_pull(skb, sizeof(struct udphdr)))goto drop;        /* No space for header. */uh   = udp_hdr(skb);ulen = ntohs(uh->len);saddr = ip_hdr(skb)->saddr;daddr = ip_hdr(skb)->daddr;if (ulen > skb->len)goto short_packet;if (proto == IPPROTO_UDP) {/* UDP validates ulen. */if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen))goto short_packet;uh = udp_hdr(skb);}if (udp4_csum_init(skb, uh, proto))goto csum_error;sk = skb_steal_sock(skb, &refcounted);if (sk) {struct dst_entry *dst = skb_dst(skb);int ret;if (unlikely(rcu_dereference(sk->sk_rx_dst) != dst))udp_sk_rx_dst_set(sk, dst);ret = udp_unicast_rcv_skb(sk, skb, uh);if (refcounted)sock_put(sk);return ret;}if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))return __udp4_lib_mcast_deliver(net, skb, uh,saddr, daddr, udptable, proto);sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);if (sk)return udp_unicast_rcv_skb(sk, skb, uh);if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))goto drop;nf_reset_ct(skb);/* No socket. Drop packet silently, if checksum is wrong */if (udp_lib_checksum_complete(skb))goto csum_error;__UDP_INC_STATS(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE);icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);/** Hmm.  We got an UDP packet to a port to which we* don't wanna listen.  Ignore it.*/kfree_skb(skb);return 0;short_packet:net_dbg_ratelimited("UDP%s: short packet: From %pI4:%u %d/%d to %pI4:%u\n",proto == IPPROTO_UDPLITE ? "Lite" : "",&saddr, ntohs(uh->source),ulen, skb->len,&daddr, ntohs(uh->dest));goto drop;csum_error:/** RFC1122: OK.  Discards the bad packet silently (as far as* the network is concerned, anyway) as per 4.1.3.4 (MUST).*/net_dbg_ratelimited("UDP%s: bad checksum. From %pI4:%u to %pI4:%u ulen %d\n",proto == IPPROTO_UDPLITE ? "Lite" : "",&saddr, ntohs(uh->source), &daddr, ntohs(uh->dest),ulen);__UDP_INC_STATS(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE);
drop:__UDP_INC_STATS(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE);kfree_skb(skb);return 0;
}

socket查找函数:__udp4_lib_lookup

struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,__be16 sport, __be32 daddr, __be16 dport, int dif,int sdif, struct udp_table *udptable, struct sk_buff *skb)1. 查找指定了IP+port的socket.hash2 = ipv4_portaddr_hash(net, daddr, hnum);slot2 = hash2 & udptable->mask;hslot2 = &udptable->hash2[slot2];/* Lookup connected or non-wildcard socket */result = udp4_lib_lookup2(net, saddr, sport,daddr, hnum, dif, sdif,hslot2, skb);2. 查找指只指定port的socket./* Lookup wildcard sockets */hash2 = ipv4_portaddr_hash(net, htonl(INADDR_ANY), hnum);slot2 = hash2 & udptable->mask;hslot2 = &udptable->hash2[slot2];result = udp4_lib_lookup2(net, saddr, sport,htonl(INADDR_ANY), hnum, dif, sdif,hslot2, skb);

UDP protocol--udp_rcv相关推荐

  1. tcp/ip 协议栈Linux内核源码分析15 udp套接字接收流程二

    内核版本:3.4.39 上篇我们分析了UDP套接字如何接收数据的流程,最终它是在内核套接字的接收队列里取出报文,剩下的问题就是谁会去写入这个队列,当然,这部分工作由内核来完成,本篇剩下的文章主要分析内 ...

  2. Linux内核分析 - 网络[十二]:UDP模块 - 收发

    内核版本:2.6.34 UDP报文接收        UDP报文的接收可以分为两个部分:协议栈收到udp报文,插入相应队列中:用户调用recvfrom()或recv()系统调用从队列中取出报文,这里的 ...

  3. udp协议基本数据包结构

    udp是不可靠.无连接的协议,不可靠是指不能检查到数据包是否安全到达对端,但应用程序可以做保证数据包到达的机制,udp是无连接的协议说明udp的开销小.数据包传输效率高,如果传输的数据小,创建连接的开 ...

  4. Linux内核网络数据包发送(二)——UDP协议层分析

    Linux内核网络数据包发送(二)--UDP协议层分析 1. 前言 2. `udp_sendmsg` 2.1 UDP corking 2.2 获取目的 IP 地址和端口 2.3 Socket 发送:b ...

  5. Java中UDP协议的基本原理和简单用法

    UDP协议是非面向连接的,相对于TCP协议效率较高,但是不安全.UDP协议类似发信息的过程,不管接收方是在线还是关机状态,都会把信息发送出去.但是如果接收方不处于接收信息的状态,发送出去的数据包就会丢 ...

  6. 分析udp数据报_Linux内核网络udp数据包发送(二)——UDP协议层分析

    1. 前言 本文分享了Linux内核网络数据包发送在UDP协议层的处理,主要分析了udp_sendmsg和udp_send_skb函数,并分享了UDP层的数据统计和监控以及socket发送队列大小的调 ...

  7. 内核中的UDP socket流程(5)——inet_create

    进入函数inet_create static int inet_create(struct net *net, struct socket *sock, int protocol,           ...

  8. Linux内核网络协议栈:udp数据包发送(源码解读)

    <监视和调整Linux网络协议栈:接收数据> <监控和调整Linux网络协议栈的图解指南:接收数据> <Linux网络 - 数据包的接收过程> <Linux网 ...

  9. tcp协议和udp协议区别_TCP和UDP协议有什么区别?

    tcp协议和udp协议区别 TCP and UDP are two protocols that are part of the transport layer in a TCP/IP model o ...

  10. 如何使用Nmap扫描所有TCP和UDP端口?

    Nmap is a very useful and popular tool used to scan ports. Nmap by default scans the most popular 10 ...

最新文章

  1. torch量化训练后导出onnx模型并运行
  2. 清华本科、港科大准博士被指论文抄袭,网友:这是有技巧的“洗稿”
  3. 激活手表显示无法登陆服务器,在Firefox中使用Nightwatch运行测试无法连接到Selenium服务器...
  4. c语言程序设计开卷考试b卷,C语言程序设计(B)试卷_杨崇联(A1).doc
  5. 【dfs】无穷迷宫(jzoj 3924)
  6. lc滤波电路电感电容值选择_电感器变压器选型与应用
  7. 团队开发冲刺1.2(2015.5.10)
  8. 安装postgreSQL出现configure: error: zlib library not found解决方法
  9. 解决: 您目前无法访问 因为此网站使用了 HSTS。网络错误和攻击通常是暂时的,因此,此网页稍后可能会恢复正常。
  10. 电源模块DC-DC隔离型测试方法
  11. iis6 增加PHP+MYSQL等时,记得 PHP目录要给EVERYONE权限
  12. 操作系统 面试问题_操作系统面试问答
  13. Highcharts 操作series 的data里的数据
  14. 交换机crc错误是什么意思_OSN1800设备LDX对接S9706交换机,交换机持续有CRC错误告警...
  15. ArcSDE版本学习总结
  16. 下载谷歌play应用_在Google Play控制台上为应用设置发布并发布到内部曲目
  17. 第4章-5 求e的近似值 (15分)python
  18. CC2640R2F BLE5.0 TI-RTOS概述
  19. 图片标题生成器(literature:Show and Tell: A Neural Image Caption Generator)
  20. 树形数据库查询优化方案

热门文章

  1. win7虚拟机_虚拟机VMware 15安装教程
  2. 什么是API接口?给大家举例说明
  3. linux vi 命令,Linux之VI命令详解
  4. 踩坑记---Win10安装anaconda及tensorflow-cpu版
  5. Visio安装失败 无法打开注册表项 解决方案
  6. 拼多多---多多果园怎么玩
  7. sh股票是什么意思?
  8. 家庭账本应该怎样记简洁明了
  9. Bugku-web-秋名山老司机
  10. 【大数据技术详解】搭建redis集群服务的步骤和配置以及解决创建集群时会遇到的错误:NodeX replied with error:ERRInvalid node address specified