sk_buff有两个地方可以存储下一个分片数据:
skb_shinfo(head)->frag_list
skb_shinfo(head)->frags[]
这两种处理碎片的方法有什么区别?
sk_buff有两个地方可以存储下一个分片数据:
skb_shinfo(head)->frag_list
skb_shinfo(head)->frags[]
这两种处理碎片的方法有什么区别?
两者都用于不同的情况。
碎片[]
当您的设备支持 scatter-gather I/O,并且您希望它进行数据组合等操作时,您可以frags[]
从第二个片段开始填充结构,直到第 n 个片段。第一个片段总是由data
andtail
指针指定。其余的碎片填充在frags[]
结构中。如果您不使用分散聚集,则此变量为空。
碎片列表
这是IP片段的列表。这将在 期间填充ip_push_pending_frames
。
说你sk_buffs
在这个安排中,
sk_buff0->next = sk_buff1
sk_buff1->next = sk_buff2
...
sk_buffn-1->next = sk_buffn
之后ip_push_pending_frames
被调用
sk_buff0->frag_list = sk_buff1
sk_buff1->next = sk_buff2
...
sk_buffn-1->next = sk_buffn
简单的说
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;