Erreurs fréquentes

J'ai décidé d'écrire sur une erreur courante dans les applications réseau et les périphériques réseau. Je vais essayer d'expliquer le problème en utilisant la pile Linux comme exemple. Et je vais argumenter de manière plus abstraite, en essayant d'expliquer le principe. Après tout, toutes les applications sont différentes, même si l'essence est la même. (Ils transfèrent des bits dans les deux sens.) Et chaque application réseau, ou un périphérique réseau, a besoin de sa propre approche afin de corriger les erreurs qui y sont commises.






Le problème réside dans les petits morceaux de données que les systèmes échangent. Plus précisément, pas dans ces portions elles-mêmes, mais dans la manière dont elles sont ensuite collectées et traitées.





Par exemple, un système envoie la phrase « Hello World! "





Comment puis je faire ça? Oui, peu importe. Tout protocole de transfert de données est sélectionné : TCP , MPTCP , UDP . Les données sont divisées en morceaux, que nous appellerons paquets. Et ils sont envoyés au système final. (Comment exactement? Cela n'a pas d'importance du tout.)





L'important est ce que (et comment) le système final fera des données reçues. Si la chaîne « Hello World! "A été divisé en deux packages:





" Bonjour " - Ceci est le contenu du premier package.





« Monde! "- Et ceci est le deuxième paquet.





, ( ) , (). ( . )





, . , , . , .. . — .





, . ,





«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