Errores comunes

Decidí escribir sobre un error común en aplicaciones de red y dispositivos de red. Intentaré explicar el problema usando la pila de Linux como ejemplo. Y discutiré de manera más abstracta, tratando de explicar el principio. Después de todo, todas las aplicaciones son diferentes, aunque la esencia es la misma. (Transfieren bits de un lado a otro). Y cada aplicación de red, o un dispositivo de red, necesita su propio enfoque para corregir los errores cometidos en él.






El problema radica en los pequeños fragmentos de datos que intercambian los sistemas. Más precisamente, no en estas porciones en sí mismas, sino en cómo se recolectan y procesan posteriormente.





Por ejemplo, un sistema envía la frase “ ¡Hola mundo! "





¿Cómo puedo hacer eso? Si, lo que sea. Se selecciona cualquier protocolo de transferencia de datos: TCP , MPTCP , UDP . Los datos se dividen en trozos, que llamaremos paquetes. Y se envían al sistema final. (¿Cómo exactamente? No importa en absoluto).





Lo importante es qué (y cómo) hará el sistema final con los datos recibidos. Si la cadena “ ¡Hola mundo! "Se dividió en dos paquetes:





" Hola ": este es el contenido del primer paquete.





¡ Mundo! "- Y este es el segundo paquete.





, ( ) , (). ( . )





, . , , . , .. . — .





, . ,





«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