TCP_NEW_SYN_RECV
source link: http://abcdxyzk.github.io/blog/2020/09/10/kernel-tcp-new-syn-recv/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
TCP_NEW_SYN_RECV
2020-09-10 04:40:00
结合以上patch,在 kernel-3.10.0-693.11.1.el7.src.rpm 内核上引入 TCP_NEW_SYN_RECV patch
好处:mptcp和4.15.0的基本一样。
不再需要spin_lock(listen_sk),最大的互斥变成atomic。(去除atomic看 tcp连接查找 )
ipv6_addr_v4mapped
sk_ehashfn 被 ipv4, ipv6 共用,req hash 的时候可用的变量不多,用的是 ipv6_addr_v4mapped(&sk->sk_v6_daddr) 判断是否mapped,所以原先的sk->sk_daddr = addr; sk->sk_rcv_saddr = addr; 换成下面两个函数。
static inline void sk_daddr_set(struct sock *sk, __be32 addr)
{
sk->sk_daddr = addr; /* alias of inet_daddr */
#if IS_ENABLED(CONFIG_IPV6)
ipv6_addr_set_v4mapped(addr, &sk->sk_v6_daddr);
#endif
}
static inline void sk_rcv_saddr_set(struct sock *sk, __be32 addr)
{
sk->sk_rcv_saddr = addr; /* alias of inet_rcv_saddr */
#if IS_ENABLED(CONFIG_IPV6)
ipv6_addr_set_v4mapped(addr, &sk->sk_v6_rcv_saddr);
#endif
}
ir_iif, ireq_net, ireq_state
ir_iif, ireq_net, ireq_state 需要在 req 创建时赋值,因为插入ehash表后的查找需要用到这些变量。
reqsk_put
原先部分reqsk_free需要换成reqsk_put,因为req已经和sk一样,靠自己的refcnt维护
backlog
if (sk->sk_state == TCP_LISTEN) {
ret = tcp_v4_do_rcv(sk, skb);
goto put_and_return;
}
listen_sk 的包要在tcp_v4_rcv里处理完,不能再加入listen_sk的backlog处理,因为req已经不在listen_sk->icsk_accept_queue.listen_opt.syn_table里,而backlog(=tcp_v4_do_rcv)又不会再lookup_sk,导致无法找到req。
原来的处理是:按listen_sk的收到包的顺序处理,并且需要spin_lock。按照下面的顺序,即使syn、ack、GET包都在backlog里也能处理(GET包查不到req,能查到establish)。TCP_NEW_SYN_RECV 主要是优化调spin_lock(listen_sk)
tcp_v4_hnd_req() {
req = inet_csk_search_req()
if (req)
return tcp_check_req()
nsk = inet_lookup_established()
if (nsk && nsk->sk_state != TCP_TIME_WAIT)
return nsk;
}
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK