Häufige Fehler

Ich habe mich entschlossen, über einen häufigen Fehler in Netzwerkanwendungen und Netzwerkgeräten zu schreiben. Ich werde versuchen, das Problem am Beispiel des Linux-Stacks zu erklären. Und ich werde abstrakter argumentieren und versuchen, das Prinzip zu erklären. Schließlich sind alle Anwendungen unterschiedlich, obwohl das Wesentliche dasselbe ist. (Sie übertragen Bits hin und her.) Und jede Netzwerkanwendung oder ein Netzwerkgerät benötigt einen eigenen Ansatz, um darin gemachte Fehler zu korrigieren.






Das Problem liegt in den kleinen Datenblöcken, die die Systeme austauschen. Genauer gesagt, nicht in diesen Teilen selbst, sondern in der Art und Weise, wie sie weiter gesammelt und verarbeitet werden.





Beispielsweise sendet ein System den Satz „ Hallo Welt! ""





Wie kann ich das machen? Ja, was auch immer. Jedes Datenübertragungsprotokoll wird ausgewählt : TCP , MPTCP , UDP . Die Daten werden in Blöcke aufgeteilt, die wir Pakete nennen werden. Und sie werden an das endgültige System gesendet. (Wie genau? Es spielt überhaupt keine Rolle.)





Wichtig ist, was (und wie) das endgültige System mit den empfangenen Daten macht. Wenn die Zeichenfolge „ Hallo Welt! "Wurde in zwei Pakete aufgeteilt:





" Hallo " - Dies ist der Inhalt des ersten Pakets.





Welt! "- Und das ist das zweite Paket.





, ( ) , (). ( . )





, . , , . , .. . — .





, . ,





«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