Common mistakes

I decided to write about a common error in network applications and network devices. I will try to explain the problem using the Linux stack as an example. And I will argue more Abstractly, trying to explain the principle. After all, all applications are different, even though the essence is the same. (They transfer bits back and forth.) And each network application, or a network device, needs its own approach in order to correct mistakes made in it.






The problem lies in the small chunks of data that systems exchange. More precisely, not in these portions themselves, but in how they are further collected and processed.





For example, one system sends the phrase “ Hello World! "





How can I do that? Yes, whatever. Any data transfer protocol is selected : TCP , MPTCP , UDP . The data is split into chunks, which we will call packets. And they are sent to the final system. (How exactly? It doesn't matter at all.)





The important thing is what (and how) the final system will do with the received data. If the string “ Hello World! "Was split into two packages:





" Hello " - This is the content of the first package.





World! "- And this is the second package.





, ( ) , (). ( . )





, . , , . , .. . — .





, . ,





«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