Linux内核分析 端口哈希桶

描述

端口哈希桶

在inet_csk_get_port函数中的变量声名中有如下几个结构体:

struct inet_hashinfo *hinfo = sk- >sk_prot- >h.hashinfo;
struct inet_bind_hashbucket *head;
struct inet_bind_bucket *tb = NULL;

其中strcut inet_hashinfo是用来封装各种协议的绑定哈希表,具体定义如下所示,这个结构体在[Linux内核角度分析服务器Listen细节中介绍过,具体地,struct inet_bind_hashbcket是bind相关的哈希桶,bhash_size是bind哈希桶的大小。

struct inet_hashinfo {
 struct inet_ehash_bucket *ehash;
 spinlock_t   *ehash_locks;
 unsigned int   ehash_mask;
 unsigned int   ehash_locks_mask;
 struct inet_bind_hashbucket *bhash;

 unsigned int   bhash_size;
 struct inet_listen_hashbucket listening_hash[INET_LHTABLE_SIZE]
     ____cacheline_aligned_in_smp;
};

struct inet_bind_hashbcket哈希桶的具体定义如下,其中chain代表着各个桶的哈希队列,用来链接具有同一哈希值的哈希元素

struct inet_bind_hashbucket {
 spinlock_t  lock;
 struct hlist_head chain;
};

具体每个桶结构是struct inet_bind_bucket:

struct inet_bind_bucket {
 possible_net_t  ib_net;
 unsigned short  port;
 signed char  fastreuse;
 signed char  fastreuseport;
 kuid_t   fastuid;
#if IS_ENABLED(CONFIG_IPV6)
 struct in6_addr  fast_v6_rcv_saddr;
#endif
 __be32   fast_rcv_saddr;
 unsigned short  fast_sk_family;
 bool   fast_ipv6_only;
 struct hlist_node node;
 struct hlist_head owners;
};

初次看到这几个结构体可能比较乱,下面用图进行描述:

Linux

由上图所示,每个绑定的端口号经过哈希计算都会挂在相应的chain链表上,chain链表上是一个个的桶结构,同一个chain上的节点具有相同的哈希值(通过端口号计算),桶结构inet_bind_bucket包含对应的端口号port、owners等信息,owners对应:该端口号对应的tcp_sock实例,如果该port支持复用,那么owners可能挂着多个tcp_sock节点。

在struct inet_bind_bucket中有一个关键的成员:signed char fastreuse

为了避免每次都遍历 inet_bind_bucket 的 owners 字段 来获知是否所有的 sock 都设置了 sk_reuse 字段,并且不是在 TCP_LISTEN 状态。在 inet_bind_bucket 结构体中设置了 fastreuse 字段。如果 owners 没有元素,那么这 个字段为真。此后每次添加一个新的 sock 到 owners 中的时候,如果它设置了 sk_reuse 并且不在 TCP_LISTEN 状态,就维持 fastreuse 为真,否则设置它为假。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分