IPv4之数据包发送接口ip_append_data(一)

IPv4之发送接口概述所介绍,ip_append_data()主要是由udp使用。因为ip_append_data()的实现非常的复杂,涉及skb对数据的组织方式,以及各种出于性能考虑的分配策略,所以在分析其代码实现之前,有必要先讨论下内核实际采取的数据组织方式。

函数功能

首先需要明确ip_append_data()要实现的功能:

  1. ip_append_data()的任务就是将多个片段合并成一个大的IP报文,该函数仅仅做合并工作,并不实际发送报文,如果要发送,调用者后面应该主动调用ip_push_pending_frames();
  2. 这里要注意区分IP报文和IP片段的不同,发送端可以组织一个很大的IP报文,但是在实际发送时,为了适配设备的MTU,需要将这一个IP报文拆封成多个IP片段,这些拆分的IP片段的ipid相同,片内偏移不同;
  3. 该函数将参数指定的数据(from,length)按照MTU大小组织成一个个的方便后面IP协议处理的skb,并且将这些skb放入传输控制块的发送缓冲区中,这些skb在代码中被称之为pending数据;

skb数据组织策略

  1. 一个IP报文可能超过了MTU大小,这时一个IP报文就需要拆分成多个IP片段分开传输以适配设备的MTU;
  2. 为了方便IP协议后续处理,ip_append_data()调用之后,IP片段和skb是一一对应的,不管skb内部是如何存储数据的,这点都是确定的。

下面我们来看一些可能的情况。

情形1

在这里插入图片描述

如上图所示,这是一种不需要分段的情形,即传输的数据长度小于PTMU,只需要分配一个skb就可以容纳下要发送的数据了。这里有些关键点需要说明:

  1. 实际分配skb时,会将L2所需头部、IP头部、L4的头部和数据部分都考虑进来,这样后续协议在处理该数据包是就无需再次分配缓冲区了;
  2. 示例中还有IPsec header和IPsec tailer两部分,这属于扩展首部和扩展末尾,当启用IPsec时,需要在IP报文的首尾追加IPsec特有的信息,所以如果是这种情况,在分配skb时也会将这种开销考虑进来;
  3. 实际分配时,如果一个IP数据包总长度小于PMTU,分配的skb长度是按照需要的大小来分配的,不会造成浪费,这点同样适用于需要分段时的最后一个片段(可能小于PMTU)的情况。

额外需要说明的是:ip_append_data()在分配了skb后,会拷贝L4 payload部分,还会初始化skb中的某些字段,如上图缓冲区左侧的图示;其余的如L4 header由调用ip_push_pending_frames()的函数负责填充、IP header由ip_push_pending_frames()填充。

情形2

在这里插入图片描述

这个例子比上一个稍微复杂一点,这个例子我们不考虑IPsec的情形。左下角为L4协议想要传输的报文,长度为length并且大于PMTU,一次调用ip_append_data()需要将这整个报文拆分成skb放入到套接字的发送缓冲区中,这里假设分配两个skb可以容纳length长度的数据,这时第一个skb大小为PTMU,它拷贝了x字节的数据;第二个skb拷贝了剩余的y字节(x+y=length),并且第二个skb的长度小于PMTU。

由于调用者可能会连续调用ip_append_data()多次,然后再调用ip_push_pending_frames()启动发送,所以如果按照上图的方式分配最后一个skb,再来数据时就需要重新分配skb,然后将最后一个skb的数据拷贝到新的缓冲区中,然后删除最后一个缓冲区,执行这样的动作是耗时的,会带来性能的损耗。为了处理这种问题,引入了MSG_MORE标记,如果在前一次调用ip_append_data()时指定了MSG_MORE标记,那么表示后面马上还会添加新的数据,这时就可以在处理最后一部分数据时预先分配一个容纳PMTU大小的skb,如下图所示:
在这里插入图片描述
虽然当前无法填满最后一个skb,但是因为很快有数据到达,所以这么分配没有问题。

情形3

case1和case2所举的例子都是设备不支持S/G IO时能够采取的解决方案,如果设备支持S/G IO,那么即使L4是多次传入小片段调用ip_append_data(),ip_append_data()也可以按照下图所示方式组织数据:

在这里插入图片描述

上图a表示支持S/G IO的情形下第一次调用ip_append_data()后的缓冲区结构,注意skb的分配是按需分配的,其大小并不是PMTU。图b是第二次调用ip_append_data()后,新增的数据保存在了前一个skb的frags数组中,这两块区域并不连续,但是由于设备支持S/G IO,所以这么分配是没有问题的。

要特别注意的是,上图中的x+S1的大小依然要小于PMTU,如果超过,那么还是需要分配一个新的skb,这是因为一个skb对应一个IP片段的原则不能打破。

小结

理解了上面这几个图,基本上就可以理解ip_append_data()的处理逻辑了,下一篇来介绍ip_append_data()的实现细节。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: rte_pktmbuf_append 是DPDK中支持网络数据包的数据结构 rte_mbuf 的一种函数,用于向 rte_mbuf 数据结构中的缓冲区末尾添加数据。rte_pktmbuf_append 函数的函数原型如下: ``` struct rte_mbuf *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len); ``` 其中,参数 m 是指向 rte_mbuf 数据结构的指针,参数 len 是要添加的数据长度。该函数会将数据添加到 rte_mbuf 缓冲区的末尾,并返回添加后的 rte_mbuf 指针。需要注意的是,该函数只会向 rte_mbuf 的缓冲区添加数据,不会更新 rte_mbuf 的数据包长度字段,因此需要在添加完数据后手动更新数据包长度字段。 ### 回答2: rte_pktmbuf_append是DPDK(Data Plane Development Kit)的一个函数,在网络数据包的mempool的空闲空间后追加数据。该函数可以用于将数据包的数据追加到已经创建的rte_mbuf结构中,并且会自动更新rte_mbuf的相关字段。 当我们在DPDK应用程序中处理网络数据包时,数据包的内容通常会被分成多个部分,每个部分可能来自不同的来源或用于不同的目的。rte_pktmbuf_append函数可以将新的数据追加到现有的mbuf的末尾,而无需复制或重新分配内存。 使用rte_pktmbuf_append函数,我们可以方便地将数据包从不同的源拼接在一起,将其作为一个整体传递给后续的处理步骤。这对于网络包的处理和转发非常有用。 函数的签名为:rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len) 其中,m是rte_mbuf结构的指针,它包含了存储数据包的内存区域和相关的信息。len是要追加的数据的长度。 在调用rte_pktmbuf_append函数时,必须确保m还有足够的空闲空间来容纳要追加的数据。如果空间不足,追加操作将会失败。 总之,rte_pktmbuf_append函数在DPDK中用于向rte_mbuf结构追加数据,实现了在不重新分配内存的情况下拼接数据包的能力,方便了网络包的处理和转发。 ### 回答3: rte_pktmbuf_append是DPDK提供的一个函数,用于向rte_mbuf数据包缓冲区的尾部添加数据。rte_mbuf是DPDK中用于存储网络数据包的数据结构,它包含了网络数据包的各个部分,如数据,头部信息等。 rte_pktmbuf_append函数的主要功能是将一段数据追加到数据包的末尾。它接受三个参数:rte_mbuf指针pkt、数据指针data和数据长度len。 当调用rte_pktmbuf_append函数时,数据将会被复制到rte_mbuf数据包缓冲区中的一个空闲区域。该函数会自动更新rte_mbuf的数据长度、数据偏移量和尾部偏移量等相关信息。 这个函数有一些限制和要求。首先,rte_mbuf必须是有效的(即不能为NULL),否则函数将会失败。其次,数据指针data也必须是有效的,并且包含足够的数据供复制到rte_mbuf中。最后,数据长度len必须大于0,否则函数将会忽略该调用。 使用rte_pktmbuf_append函数可以很方便地向rte_mbuf中添加数据。例如,当网络数据包接收时,可以使用该函数将数据追加到rte_mbuf中,以便后续的数据处理和转发操作。此外,该函数也常用于构造网络数据包发送时,将数据追加到rte_mbuf中的空闲区域。 总之,rte_pktmbuf_append函数是DPDK中一个非常常用的函数,它能够将数据追加到rte_mbuf数据包缓冲区的末尾,方便数据的处理和传输操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值