- struct sock * __inet_lookup_established(struct net *net,
-
struct inet_hashinfo *hashinfo,
-
const __be32 saddr, const __be16 sport,
-
const __be32 daddr, const u16 hnum,
-
const int dif)
-
{
-
INET_ADDR_COOKIE(acookie, saddr, daddr)
-
const __portpair ports = INET_COMBINED_PORTS(sport, hnum);
-
struct sock *sk;
-
const struct hlist_nulls_node *node;
-
/* Optimize here for direct hit, only listening connections can
-
* have wildcards anyways.
-
*/
-
unsigned int hash = inet_ehashfn(net, daddr, hnum, saddr, sport);
-
unsigned int slot = hash & hashinfo->ehash_mask;
/* 获得处于连接状态(established<=state
-
struct inet_ehash_bucket *head = &hashinfo->ehash[slot];
-
-
rcu_read_lock();
-
begin:
-
-
sk_nulls_for_each_rcu(sk, node, &head->chain) {
-
if (INET_MATCH(sk, net, hash, acookie,
-
saddr, daddr, ports, dif)) {
- /* 地址端口等均匹配 */
/* 大致的看了一下进入TIME_WAIT的函数,当socket进入TW时,并没有从ehash中移除,所以可能需 要检查TW*/
- if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt)))
-
goto begintw; /* 该socket的引用计数为0,必须检测是处于TIME_WAIT状态 */
/*
这里为什么要两次检验:通过google搜索,直到当时加上2次检验的原因是因为RCU的缘故。想了半天,终于明白了。在第一次INET_MATCH时,该sk还没有被hold。只有执行了atomic_inc_not_zero,才相当于hold了这个sk。但是正常的RCU的操作,应该是先hold,才能保证内容没有变化。所以需要二次判断。
*/
-
if (unlikely(!INET_MATCH(sk, net, hash, acookie,
-
saddr, daddr, ports, dif))) {
-
sock_put(sk);
-
goto begin;
-
}
/* 找到了socket */
-
goto out;
-
}
-
}
-
/*
-
* if the nulls value we got at the end of this lookup is
-
* not the expected one, we must restart lookup.
-
* We probably met an item that was moved to another chain.
-
*/
-
if (get_nulls_value(node) != slot)
-
goto begin;
-
-
begintw:
-
/* Must check for a TIME_WAIT'er before going to listener hash. */
- /* 确保该socket不处于TIME_WAIT状态 */
-
sk_nulls_for_each_rcu(sk, node, &head->twchain) {
-
if (INET_TW_MATCH(sk, net, hash, acookie,
-
saddr, daddr, ports, dif)) {
-
if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt))) {
- /*
- 该socket的引用计数为0,那么意味着该socket已经无人使用,所以可视为该socket无效。
- */
-
sk = NULL;
-
goto out;
-
}
/* 二次比较。原因同上 */
-
if (unlikely(!INET_TW_MATCH(sk, net, hash, acookie,
-
saddr, daddr, ports, dif))) {
-
sock_put(sk);
-
goto begintw;
-
}
-
goto out;
-
}
-
}
-
/*
-
* if the nulls value we got at the end of this lookup is
-
* not the expected one, we must restart lookup.
-
* We probably met an item that was moved to another chain.
-
*/
-
if (get_nulls_value(node) != slot)
-
goto begintw;
-
sk = NULL;
-
out:
-
rcu_read_unlock();
-
return sk;
-
}