Die*_*yen 5 linux fragmentation linux-device-driver linux-kernel
sk_buff有两个地方可以存储下一个碎片数据:
skb_shinfo(head)->frag_list
skb_shinfo(head)->frags[]
Run Code Online (Sandbox Code Playgroud)
请有人解释这两种处理碎片的方法之间的差异.
谢谢,最诚挚的问候!
小智 7
两者都用于不同的情况.
断支[]
当您的设备支持分散 - 聚集I/O,并且您希望它进行数据组合等时,您可以frags[]从第二个片段开始填充结构直到第n个片段.第一个片段总是由data和tail指针指定.其余的碎片填充在frags[]结构中.如果不使用分散集合,则此变量为空.
frag_list
这是IP片段列表.这将在期间填补ip_push_pending_frames.说你sk_buffs在这个安排
sk_buff0->next = sk_buff1
sk_buff1->next = sk_buff2
...
sk_buffn-1->next = sk_buffn
Run Code Online (Sandbox Code Playgroud)
之后ip_push_pending_frames被召唤
sk_buff0->frag_list = sk_buff1
sk_buff1->next = sk_buff2
...
sk_buffn-1->next = sk_buffn
Run Code Online (Sandbox Code Playgroud)
简单的说
frags[] 用于分散 - 聚集I/O缓冲区frag_list 用于ip片段skb_shinfo(head)->frags[]
如果网卡支持SG I/O,__ip_append_data会将用户空间数据复制到skb_shinfo(head)->frags。NIC驱动程序(例如ixgbe_add_rx_frag)也可以使用这些frags[]来承载接收到的网络流量;请注意,frags[] 中的每个内容都是完整数据包的一部分。一个完整的数据包由所有frags[] + (skb->data ~ skb->tail)组成。
skb_shinfo(head)->frag_list
IP分片不直接使用该成员。在__ip_make_skb()中,frag_list用于收集sk->sk_write_queue中的所有skb;一些 NIC 驱动程序还使用此 frag_list 将数据包传送到上层网络堆栈。frag_list中的每个content/skb也不是一个完整的数据包;tcp_v4_send_ack -> ip_send_unicast_reply -> ip_push_pending_frames -> ip_finish_skb -> __ip_make_skb;