cola de solicitud de conexión TCP de pila de protocolo del kernel de linux

Tabla de contenido

1. Descripción general de la cola de solicitudes

2. Toma orientada a la conexión inet_connection_sock

2.1 Cola de establecimiento de conexión request_sock_queue 

2.2 SYN request queue listen_sock     

3. Bloque de solicitud de conexión request_sock

3.1 estructura tcp_request_sock

3.1.1 Función de operación struct tcp_request_sock_ops


1. Descripción general de la cola de solicitudes

El programa del lado del servidor TCP primero crea un socket de escucha. Una vez que un cliente se conecta al socket de escucha, se crea un nuevo socket de comunicación para comunicarse con el cliente, y el socket de escucha continúa esperando a otros clientes. Solicitud de conexión. Este período es el proceso de protocolo de enlace de tres vías, este proceso puede fallar, por lo que para administrar el socket durante este período, el protocolo TCP define específicamente un conjunto de estructuras de datos. El propósito de esta nota es aclarar la relación entre estas estructuras de datos centrales. Primero, llegue a un diagrama de estructura general. Será más fácil entender las siguientes definiciones de estructura de datos en comparación con el diagrama de estructura.
Inserte la descripción de la imagen aquí

2. Toma orientada a la conexión inet_connection_sock

Cada conector orientado a la conexión es una estructura inet_connection_sock. Hay un miembro isck_accept_queue en esta estructura. Este miembro es la llamada cola de administración de conexión, que se utiliza para administrar todo el protocolo de enlace de tres vías en curso o el protocolo de enlace de tres vías en espera de aceptar (). Enchufe.

Nota: El socket del cliente no usa esta cola porque no es necesaria.

/** inet_connection_sock - INET connection oriented sock
 *
 * @icsk_accept_queue:	   FIFO of established children 
 */

struct inet_connection_sock {
	...
	struct request_sock_queue icsk_accept_queue;
}

2.1 Cola de establecimiento de conexión request_sock_queue 

struct request_sock_queue {
	//head和tail用于维护已经完成三次握手,等待用户程序accept的套接字,
	//后续称该队列为“accept连接队列”,其中的套接字为“已连接套接字”
	struct request_sock	*rskq_accept_head;
	struct request_sock	*rskq_accept_tail;
    
	//用于同步对listen_opt的操作
	rwlock_t		syn_wait_lock;
	//与TCP选选TCP_DEFER_ACCEPT有关,暂时忽略
	u8			rskq_defer_accept;
	/* 3 bytes hole, try to pack */
    
	//已经收到SYN,但是尚未完成三次握手的套接字保存在该结构中,其占用内存在listen()
	//系统调用期间分配,后续称该队列为“SYN请求队列”,其中的套接字为“半连接套接字”
	struct listen_sock	*listen_opt;
};

2.2 SYN request queue listen_sock     

struct listen_sock {
	//其取值为nr_table_entries以2为底的对数
	u8			max_qlen_log;
	/* 3 bytes hole, try to use */
	//当前syn_table哈希表中套接字的数目,即有多少个半连接套接字
	int			qlen;
	//服务器端会超时重传SYN+ACK段,该变量记录了那些还尚未重传过SYN+ACK段的套接字个数
	int			qlen_young;
    
	int			clock_hand;
	//该随机数用于访问listen_opt哈希表时计算哈希值
	u32			hash_rnd;
	
	//syn_table哈希表的桶大小,该值和listen()系统调用的backlog参数有关
	u32			nr_table_entries;
	//半连接套接字哈希表,管理的元素就是连接请求块,见下方
	struct request_sock	*syn_table[0];
};

3. Bloque de solicitud de conexión request_sock

Similar a los sockets ordinarios, hay una correspondencia TCB como struct tcp_sock. Los sockets conectados y los sockets semi-conectados también necesitan un TCB similar, pero no corresponden a la struct tcp_sock, sino a la estructura que se introducirá aquí. tcp_request_sock. La estructura también es jerárquica, seguida de struct tcp_request_sock, struct inet_request_sock, struct request_sock A continuación se muestra la definición de la estructura.

3.1 estructura tcp_request_sock

struct tcp_request_sock {
	struct inet_request_sock req;

#ifdef CONFIG_TCP_MD5SIG
	/* Only used by TCP MD5 Signature so far. */
	const struct tcp_request_sock_ops *af_specific;
#endif
	//客户端SYN段中携带的seq,即客户端的初始序列号 */
	u32 rcv_isn; 
	//SYN+ACK段携带的seq,即服务器端的初始序列号
	u32 snt_isn;
	//SYN+ACK段发送的时间戳,基于jiffies
	u32 snt_synack;
};

struct inet_request_sock {
    struct request_sock req;

#if IS_ENABLED(CONFIG_IPV6)
    u16 inet6_rsk_offset;
#endif

    __be16 loc_port; /* 服务器端端口号 */
    __be32 loc_addr; /* 服务器端IP地址 */
    __be32 rmt_addr; /* 客户端IP地址 */
    __be16 rmt_port; /* 客户端端口号 */

    kmemcheck_bitfield_begin(flags);
    u16 snd_wscale : 4, /* 客户端的窗口扩大因子 */
        rcv_wscale : 4, /* 服务器端的窗口扩大因子 */
        tstamp_ok : 1, /* 标识本连接是否支持TIMESTAMP选项 */
        sack_ok : 1, /* 标识本连接是否支持SACK选项 */
        wscale_ok : 1, /* 标识本连接是否支持Window Scale选项 */
        ecn_ok : 1, /* 标识本连接是否支持ECN选项 */
        acked : 1,
        no_srccheck : 1;
    kmemcheck_bitfield_end(flags);

    struct ip_options_rcu *opt; /* IP选项 */
};

/* struct request_sock - mini sock to represent a connection request
 */
struct request_sock {
	//和其它struct request_sock对象形成链表
	struct request_sock		*dl_next; /* Must be first member! */
	//SYN段中客户端通告的MSS
	u16				mss;
	//SYN+ACK段已经重传的次数,初始化为0
	u8				retrans;
	u8				__pad;
	u32				window_clamp; /* window clamp at creation time */
	u32				rcv_wnd;	  /* rcv_wnd offered first time */
	u32				ts_recent;
	//SYN+ACK段的超时时间
	unsigned long			expires;
	//指向tcp_request_sock_ops,该函数集用于处理第三次握手的
	//ACK段以及后续accept过程中struct tcp_sock对象的创建
	const struct request_sock_ops	*rsk_ops;
	//连接建立前无效,建立后指向创建的tcp_sock结构
	struct sock			*sk;
	u32				secid;
	u32				peer_secid;
};

3.1.1 Función de operación struct tcp_request_sock_ops

struct request_sock_ops {
    int family; /* 所属的协议族 */
    int obj_size; /* 连接请求块的大小 */
    struct kmem_cache *slab; /* 连接请求块的高速缓存 */
    char *slab_name;

    //SYN+ACK段重传时调用该函数
    int (*rtx_syn_ack) (struct sock *sk, struct request_sock *req, struct request_values *rvp);

    //发送ACK段时调用该函数
    void (*send_ack) (struct sock *sk, struct sk_buff *skb, struct request_sock *req);

    //发送RST段时调用该函数
    void (*send_reset) (struct sock *sk, struct sk_buff *skb);

    //析构函数
    void (*destructor) (struct request_sock *req);

    //SYN+ACK段超时处理函数
    void (*syn_ack_timeout) (struct sock *sk, struct request_sock *req);
};

//TCP的实际定义
struct request_sock_ops tcp_request_sock_ops__read_mostly = {
    .family = PF_INET,
    .obj_size = sizeof(struct tcp_request_sock),

    .rtx_syn_ack = tcp_v4_rtx_synack,
    .send_ack = tcp_v4_reqsk_send_ack,
    .destructor = tcp_v4_reqsk_destructor,
    .send_reset = tcp_v4_send_reset,
    .syn_ack_timeout = tcp_syn_ack_timeout,
};

Supongo que te gusta

Origin blog.csdn.net/wangquan1992/article/details/108885613
Recomendado
Clasificación