よくある間違い

ネットワークアプリケーションとネットワークデバイスの一般的なエラーについて書くことにしました。Linuxスタックを例として使用して問題を説明しようと思います。そして、私はもっと抽象的に議論し、原理を説明しようとします。結局のところ、本質は同じですが、すべてのアプリケーションは異なります。(ビットを前後に転送します。)そして、各ネットワークアプリケーション、またはネットワークデバイスは、ミスを修正するために独自のアプローチを必要とします。






問題は、システムが交換するデータの小さなチャンクにあります。より正確には、これらの部分自体ではなく、それらがさらに収集および処理される方法です。





たとえば、あるシステムは「Hello World!「」





どうやってやるの?はい、何でも。TCPMPTCPUDPなどの任意のデータ転送プロトコル選択されますデータはチャンクに分割され、これをパケットと呼びます。そして、それらは最終システムに送られます。(正確には?それはまったく問題ではありません。)





重要なことは、最終的なシステムが受信したデータをどのように(そしてどのように)処理するかです。文字列「HelloWorld!「2つのパッケージに分割されました:





こんにちは」-これは最初のパッケージの内容です。





世界!"-そしてこれは2番目のパッケージです。





, ( ) , (). ( . )





, . , , . , .. . — .





, . ,





«World !» - .









«Hello » - .





, , : «World !Hello ». ( , , « » «seq»).





: seq. , « ». , , . seq? , , «Hello World !»





Linux TCP ( Linux-5.10.7 ) net/ipv4/tcp_ipv4.c tcp_v4_fill_cb, . ,





TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
				    skb->len - th->doff * 4);
      
      



end_seq — . ( , ( , )





: «Hello » - . 6 .





, seq = 0x1 end_seq = 0x7





«World !» - . 7 .





, seq = 0x7 end_seq = 0xe





«Hello World !»





, seq = 0x4 end_seq = 0xb





«Hello ld !»





«Wor» . ( , ) . tcp_rcv_nxt_update net/ipv4/tcp_input.c rcv_nxt struct tcp_sock. , end_seq ( ). ( rcv_nxt tcp )





: end_seq. , copied_seq struct tcp_sock. , ( ) , rcv_nxt end_seq. .





. : seq = 0xfffffff0 0x64 (100)





TCP_SKB_CB(skb)->end_seq = (0xfffffff0  + 0x1 + 0 +  0x140 - 0x40);
(  doff = 5  tcp )

TCP_SKB_CB(skb)->end_seq = 0xfffffff0 + 0x65 = 0x100000055
      
      



. . , end_seq = 0x55 (85 ) rcv_nxt = 0xfffffff0 , . . .





, end_seq < seq ( 0x55 < 0xfffffff0 )





, , . ( , skb_len )





. seq = 0xfffffc6e 1000 (end_seq = 0x56 ) , URG . : 16- . , (urgent) .





, . , urg . . . ( TCP Offload Engine )





seq ( ), ( ), urg 0 - 0xffff,

rcv_nxt. . ( ) . .





, : after before. , "" , "" "".





, .





inline bool before(__u32 seq1, __u32 seq2)
{
   return (__s32)(seq1-seq2) < 0;
}
#define after(seq2, seq1) 	before(seq1, seq2)

after( 0x80000000,  0x7fffffff ) = 1   
after( 0x7fffffff,  0x80000000 ) = 0   
after( 0x80000000,  0x80000000 ) = 0  

before( 0x80000000,  0x7fffffff ) = 0   
before( 0x7fffffff,  0x80000000 ) = 1   
before( 0x80000000,  0x80000000 ) = 0  
      
      



, , .





, , . , end_seq , .





end_seq < seq ( 0x55 < 0xfffffff0 )





, , __,





if(TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq >= __) {
__ } else { _ }

if(0x55 - 0xfffffff0 >= __)
if(0xffffff9 >=  __)

      
      



drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c .





handle_urg_ptr .





if (skb && tp->copied_seq - ULP_SKB_CB(skb)->seq >= skb->len)
			chtls_free_skb(sk, skb);
      
      



: copied_seq, seq, skb->len .





(- , ULP_SKB_CB(skb)->seq ). (skb)->seq, seq, copied skb->len , , . ( , )





, : chtls_cm.c





chtls_recv_data





	if (unlikely(hdr->urg))
		handle_urg_ptr(sk, tp->rcv_nxt + ntohs(hdr->urg));
	if (unlikely(tp->urg_data == TCP_URG_NOTYET &&
		     tp->urg_seq - tp->rcv_nxt < skb->len))
		tp->urg_data = TCP_URG_VALID |
			       skb->data[tp->urg_seq - tp->rcv_nxt];
      
      



handle_urg_ptr(sk, tp->rcv_nxt + ntohs(hdr->urg)); : tp->rcv_nxt + ntohs(hdr->urg) .





rcv_nxt , hdr->urg . , __ handle_urg_ptr . , .





if (unlikely(tp->urg_data == TCP_URG_NOTYET &&
		     tp->urg_seq - tp->rcv_nxt < skb->len))
		tp->urg_data = TCP_URG_VALID |
			       skb->data[tp->urg_seq - tp->rcv_nxt];
      
      



tp->urg_seq - tp->rcv_nxt < skb->len , , , ( ). skb->data[tp->urg_seq - tp->rcv_nxt];





, tp->urg_seq - tp->rcv_nxt. , - ???





tp->urg_seq - tp->rcv_nxt < skb->len 
   ,      skb->data

urg_seq - tp->rcv_nxt   ,    .
     skb->len,      
tp->urg_seq - tp->rcv_nxt < skb->len


      
skb->data[0xffffffff];
skb->data[0xfffffff0];
skb->data[0xffffff00];  .
      
      



, . .





.





(, ). , , ( ). , .





, " " , .





tcp , / , . . , ( , .). , "" ( - ), , - . , ( ), . , . . , . , . . , , , .





, . .





, ( ) . . , . ( ) ( . , )





: chtls_main.c





chtls_recv , .





void chtls_recv(struct chtls_dev *cdev,
		       struct sk_buff **skbs, const __be64 *rsp)
{
	struct sk_buff *skb = *skbs;
	unsigned int opcode;
	int ret;

	opcode = *(u8 *)rsp;   //       

	__skb_push(skb, sizeof(struct rss_header));
	skb_copy_to_linear_data(skb, rsp, sizeof(struct rss_header));

	ret = chtls_handlers[opcode](cdev, skb); //   ,   
	if (ret & CPL_RET_BUF_DONE)
		kfree_skb(skb);
}

      
      



, .





opcode = *(u8 *)rsp; , .





, , seq urg, , .









ret = chtls_handlers[opcode](cdev, skb);
      
      



NULL. .





.





, TCP urg. , UDP (. , , ). , . , .





( ). , . . ( + , ) , , ) .





.








All Articles