void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) { struct inet_sock *inet = inet_sk(sk); struct tcphdr *th = skb->h.th; if (skb->ip_summed == CHECKSUM_HW) { /* 只计算伪首部,TCP报头和TCP数据的累加由硬件完成 */ th->check = ~tcp_v4_check(th, len...
*/ if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL) return -1; /*构造syn-sck的包,并返回skb*/ skb = tcp_make_synack(sk, dst, req, foc, synack_type); if (skb) { __tcp_v4_send_check(skb, ireq->ir_loc_addr, ireq->ir_rmt_addr); /*添加ip包头并...
调用该函数后,会分配一个request_sock对象来代表这次连接请求(状态为TCP_NEW_SYN_RECV),再调用tcp_v4_send_synack回复客户端ack,开启第二次握手 复制staticinttcp_v4_send_synack(conststructsock *sk,structdst_entry *dst,structflowi *fl,structrequest_sock *req,structtcp_fastopen_cookie *foc,enumtcp_s...
}/* tcp_v4_do_rcv是个主要的报文处理函数。 */inttcp_v4_do_rcv(structsock *sk,structsk_buff *skb){ ...// SYN报文走这里if(sk->sk_state == TCP_LISTEN) {structsock*nsk =tcp_v4_cookie_check(sk, skb);if(!nsk)gotodiscard;if(nsk != sk) {if(tcp_child_process(sk, nsk, skb)) ...
req 负责在半连接队列里进行查找,找到以后返回一个半连接 request_sock 对象。然后进入到 tcp_check_...
tcp_v4_send_check(struct sock *sk, struct sk_buff *skb); Though no one explained how this is used, and whether I can actually use it at the receiving/sending the same way. My own attempt was to set checksum to 0 then call this function passing the skb I have and the skb->sk I...
只需要调用tcp_v4_check函数即可,当然,也可以调用更低层的函数,例如csum_tcpudp_magic()函数。计算tcp头部的checksum,csum_tcpudp_magic()的参数为源地址(网络字序),目的地址(网络字序)、skb->len、skbuff的校验和。skubuff的校验和是skb->csum,当然也需要自己计算,这其实是个中间值,用来计算出最终的tcp头部ch...
void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr) { struct tcphdr *th = tcp_hdr(skb); //如果需要offload,则th->check仅仅保存伪头部的校验和值,tcp头部及数据交给硬件计算 if (skb->ip_summed == CHECKSUM_PARTIAL) { ...
req 负责在半连接队列里进行查找,找到以后返回一个半连接 request_sock 对象。然后进入到 tcp_check_...
tcp_v4_conn_request()中注意两个函数就可以了:tcp_v4_send_synack()向客户端发送了SYN+ACK报文,inet_csk_reqsk_queue_hash_add()将sk添加到了syn_table中,填充了该客户端相关的信息。这样,再次收到客户端的ACK报文时,就可以在syn_table中找到相应项了。