大致的处理过程
TCP的接收流程:在tcp_v4_do_rcv中的相关处理(网卡收到报文触发)中,会首先通过tcp_check_urg设置tcp_sock的urg_data为TCP_URG_NOTYET(urgent point指向的可能不是本报文,而是后续报文或者前面收到的乱序报文),并保存最新的urgent data的sequence和对于的1 BYTE urgent data到tcp_sock的urg_data (如果之前的urgent data没有读取,就会被覆盖)。
用户接收流程:在tcp_recvmsg流程中,如果发现当前的skb的数据中有urgent data,首先拷贝urgent data之前的数据,然后tcp_recvmsg退出,提示用户来接收OOB数据;在用户下一次调用tcp_recvmsg来接收数据的时候,会跳过urgent data,并设置urgent data数据接收完成。
相关的数据结构和定义
tcp_sock结构:
1、 urg_data成员,其高8bit为urgent data的接收状态;其低8位为保存的1BYTE urgent数据。urgent data的接收状态对应的宏的含义描述:
#defineTCP_URG_VALID 0x0100/*urgent data已经读到了tcp_sock::urg_data*/
#defineTCP_URG_NOTYET 0x0200/*已经发现有urgent data,还没有读取到tcp_sock::urg_data*/
#defineTCP_URG_READ 0x0400/*urgent data已经被用户通过MSG_OOB读取了*/
2、 urg_seq成员,为当前的urgent data的sequence
流程详情
TCP的接收过程
在tcp_rcv_established的slow_path中
slow_path:
if (len < (th->doff << 2) || tcp_checksum_complete_user(sk, skb))
goto csum_error;
/*
* Standard slow path.
*/
if (!tcp_validate_incoming(sk, skb, th, 1))
return 0;
step5:
if (th->ack &&
tcp_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) < 0)
goto discard;
tcp_rcv_rtt_measure_ts(sk, skb);
/* 处理紧急数据. */
tcp_urg(sk, skb, th);
也就是在报文的CRC验证和sequence验证完成后,就会通过tcp_urg来处理接收到的urgent data :
static void tcp_urg(struct sock *sk, struct sk_buff *skb, const struct tcphdr *th)
{
struct tcp_sock *tp = tcp_sk(sk);
/*收到了urgent data,则检查