Linux内核协议栈(附3)udp_lib_get_port函数
来源:互联网 发布:微信爬虫拦截域名 编辑:程序博客网 时间:2024/06/03 16:44
/** * udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6 * * @sk: socket struct in question * @snum: port number to look up * @saddr_comp: AF-dependent comparison of bound local IP addresses */int udp_lib_get_port(struct sock *sk, unsigned short snum, int (*saddr_comp)(const struct sock *sk1, const struct sock *sk2)){struct udp_hslot *hslot;struct udp_table *udptable = sk->sk_prot->h.udp_table; /**/udp_tableint error = 1;struct net *net = sock_net(sk);//得到inet_sockif (!snum) {//--------------------------------------------------如果是0,表示要系统分配int low, high, remaining;unsigned rand;unsigned short first, last;DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN);//--------------65535/128-------定义一个数组inet_get_local_port_range(&low, &high);//端口范围sysctl_local_portsremaining = (high - low) + 1;rand = net_random();first = (((u64)rand * remaining) >> 32) + low;//得到一个随机的端口/* * force rand to be an odd multiple of UDP_HTABLE_SIZE */rand = (rand | 1) * UDP_HTABLE_SIZE;//rand最后处理成哈希表大小的奇数倍,因为奇数+奇数=偶数,而偶数+偶数=偶数,强制为奇数,可以保证链表中所有值被访问for (last = first + UDP_HTABLE_SIZE; first != last; first++) {hslot = &udptable->hash[udp_hashfn(net, first)];//---------------->得到128项中的一项,hash公式可简写为num&mask。即本地端口对udptable大小取模bitmap_zero(bitmap, PORTS_PER_CHAIN);//bitmap置0spin_lock_bh(&hslot->lock);udp_lib_lport_inuse(net, snum, hslot, bitmap, sk, saddr_comp);snum = first;/* * Iterate on all possible values of snum for this hash. * Using steps of an odd multiple of UDP_HTABLE_SIZE * give us randomization and full range coverage. * *使用first值作为端口号,从udptable的hash表中找到hslot项,重置bitmap数组全0,调用函数udp_lib_lport_inuse()遍历hslot项的所有表项,将所有已经使用的sport对应于bitmap的位置置1。 */do {if (low <= snum && snum <= high && !test_bit(snum / UDP_HTABLE_SIZE, bitmap))goto found;//------------------------------------------------>如果对应的位没有置1,说明没有被使用,即找到了snum += rand;//哈希表大小的奇数倍UDP_HTABLE_SIZE,这样还在这个链表中找} while (snum != first);spin_unlock_bh(&hslot->lock);}goto fail;} else {hslot = &udptable->hash[udp_hashfn(net, snum)];//以本地端口号hashspin_lock_bh(&hslot->lock);if (udp_lib_lport_inuse(net, snum, hslot, NULL, sk, saddr_comp))//------------------------------------------------------>判断端口是否被占用goto fail_unlock;}found:inet_sk(sk)->num = snum;//设置端口sk->sk_hash = snum;if (sk_unhashed(sk)) {sk_nulls_add_node_rcu(sk, &hslot->head);//将sk添加到hash表中sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);}error = 0;fail_unlock:spin_unlock_bh(&hslot->lock);fail:return error;}
0 0
- Linux内核协议栈(附3)udp_lib_get_port函数
- Linux内核协议栈(附1)inet_create函数注释
- Linux内核协议栈(附2)内核如何通过file对象找到对应的socket对象?
- Linux内核协议栈(7)listen函数分析
- Linux内核协议栈(8)IO复用select函数
- Linux内核协议栈(附4) accept得到新的socket的本端端口号是什么?
- linux 内核协议栈
- linux内核协议栈
- Linux内核学习总结(附录linux协议栈函数调用图)
- Linux内核学习总结(附录linux协议栈函数调用图)
- Linux内核协议栈(附5) 协议栈中msghdr结构在2.6版本和4.0版本中的差异
- Linux内核-协议栈-主要函数调用栈
- Linux 内核网络协议栈 ------ 拥塞避免处理函数 tcp_reno_cong_avoid
- 【Linux 内核网络协议栈源码剖析】socket 函数剖析
- 【Linux 内核网络协议栈源码剖析】bind 函数剖析
- 【Linux 内核网络协议栈源码剖析】listen 函数剖析
- 【Linux 内核网络协议栈源码剖析】accept 函数剖析
- 【Linux 内核网络协议栈源码剖析】sendto 函数剖析
- Android Studio 开发opencv3应用
- JS DOM编程艺术学习笔记(一)
- weblogic启动不能锁定AdminServer.lok的故障处理
- 1004. 成绩排名 (20)
- Android中Parcelable接口用法
- Linux内核协议栈(附3)udp_lib_get_port函数
- 当指针指向一个字符串
- 磁条磁道介绍
- Android-Spinner的使用以及两种适配器
- 反汇编工具objdump的使用简介
- 正则表达式
- 关于理想团队的构建和对软件流程的理解
- 集合框架--LinkedList集合练习堆栈和队列
- Google开源单元测试框架Google Test:VS2012 配置