LoginSignup
1
0

More than 1 year has passed since last update.

LinuxでのTCP通信の処理(SYN_SENT)

Posted at

TCPプロトコルについて

struct proto tcp_prot = {
	.name			= "TCP",
	.owner			= THIS_MODULE,
	.close			= tcp_close,
	.pre_connect	= tcp_v4_pre_connect,
	.connect		= tcp_v4_connect,
	.disconnect		= tcp_disconnect,
	.accept			= inet_csk_accept,
	.ioctl			= tcp_ioctl,
	.init			= tcp_v4_init_sock,
    ...
}

TCPプロトコルのconnectは「tcp_v4_connect」関数から始まっているのが分かる

tcp_v4_connect関数

int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
    ...
	tcp_set_state(sk, TCP_SYN_SENT);
	...
	err = tcp_connect(sk);
    ...
	return 0;
    ...
}
EXPORT_SYMBOL(tcp_v4_connect);

送信ポートや宛先IPなどの処理は端折っていますが、「TCP_SYN_SENT」状態にした上でtcp_connectを行っている。

tcp_connect関数

SYNのパケットの作成、(IPレイヤへ)送信を行うため様々な関数を呼んでいます。

int tcp_connect(struct sock *sk)
{
    tcp_connect_init(sk);

	buff = tcp_stream_alloc_skb(sk, 0, sk->sk_allocation, true);
    tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN);
	tcp_connect_queue_skb(sk, buff);
	tcp_ecn_send_syn(sk, buff);
	tcp_rbtree_insert(&sk->tcp_rtx_queue, buff);

	/* Send off SYN; include data in Fast Open. */
	err = tp->fastopen_req ? tcp_send_syn_data(sk, buff) :
	      tcp_transmit_skb(sk, buff, 1, sk->sk_allocation);
	if (err == -ECONNREFUSED)
		return err;

	/* Timer for repeating the SYN until an answer. */
	inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
				  inet_csk(sk)->icsk_rto, TCP_RTO_MAX);
	return 0;
}
EXPORT_SYMBOL(tcp_connect);

参考文献

https://wiki.bit-hive.com/linuxkernelmemo/pg/IPv4%20%E9%80%81%E4%BF%A1%E5%87%A6%E7%90%86
https://elixir.bootlin.com/linux/latest/source/net/ipv4/tcp_output.c#L3807
https://elixir.bootlin.com/linux/latest/source/include/net/tcp.h#L458

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0