VPP 移植到了 FreeBSD:基础用法

Vector Packet Process (VPP) 是一个高性能的框架,用于在用户空间处理数据包。得益于 FreeBSD 基金会和 RGNets 的项目,我获得资助将 VPP 移植到 FreeBSD,并且非常高兴与《FreeBSD 期刊》的读者分享一些基本的使用方法。

VPP 使得转发和路由应用程序可以在用户空间编写,并提供一个 API 可控的接口。通过 DPDK(在 Linux 上)和 DPDK 及 netmap(在 FreeBSD 上),VPP 实现了高性能的网络处理。这些 API 允许直接的零拷贝数据访问,并可用于创建可以显著超过主机转发性能的转发应用程序。

VPP 是一个完整的网络路由器替代方案,因此需要一些主机配置才能使用。本文展示了如何在 FreeBSD 上使用 VPP 的完整示例,大多数用户应该能够通过自己的虚拟机来跟随这些步骤。VPP 在 FreeBSD 上也可以运行在真实硬件上。

本文将介绍如何在 FreeBSD 上使用 VPP,并给出设置示例,展示如何在 FreeBSD 上完成各种任务。VPP 的资源可能较难找到,项目的文档质量很高,可以访问https://fd.io获取。

构建一个路由器

VPP 可以用于许多用途,其中最常见且最容易配置的是作为某种形式的路由器或桥接器。以将 VPP 用作路由器为例,我们需要构建一个包含三个节点的小型网络——一个客户端,一个服务器和一个路由器。

为了展示如何在 FreeBSD 上使用 VPP,我将构建一个最小开销的示例网络。你只需要 VPP 和一个 FreeBSD 系统。我还将安装 iperf3,以便我们能够生成并观察通过我们的路由器传输的一些流量。

在具有最新 Ports 的 FreeBSD 系统中,可以使用 pkg 命令安装我们所需的两个工具,如下所示:

为了为我们的网络创建三个节点,我们将利用 FreeBSD 最强大的功能之一——VNET jail。VNET jail 为我们提供了完全隔离的网络堆栈实例,它们的操作方式类似于 Linux 的网络命名空间(Network Namespaces)。为了创建一个 VNET,我们需要在创建 jail 时添加vnet选项,并传递它将使用的接口。

最后,我们将使用epair接口连接我们的节点。epair接口提供了以太网电缆两端的功能——如果你熟悉 Linux 上的veth接口,它们提供了类似的功能。

我们可以通过以下 5 个命令构建我们的测试网络:

在这些 jail 命令中需要注意的标志是persist,如果没有这个选项,jail 将会因为没有运行进程而自动删除;vnet使这个 jail 成为一个 VNET jail;以及vnet.interface=,它将指定的接口分配给 jail。

当一个接口被移到新的 VNET 时,它的所有配置都会被清除——这是需要注意的,因为如果你配置了一个接口然后将其移到 jail,可能会困惑于为什么一切都不工作。

设置对等端

在转到 VPP 之前,我们先设置网络的客户端和服务器端。每一方都需要分配一个 IP 地址,并将接口设置为启用状态。我们还需要为客户端和服务器 jail 配置默认路由。

我们的客户端和服务器 jail 现在已经有了 IP 地址,并且配置了通向 VPP 路由器的路由。

Netmap 要求

在我们的示例中,我们将使用 VPP 与 Netmap,Netmap 是一个高性能的用户空间网络框架,作为 FreeBSD 的默认组件提供。使用 Netmap 之前,接口需要进行一些配置——接口需要处于启用状态,并且需要配置promisc选项。

现在我们可以开始使用 VPP 了!

VPP 的基本命令

VPP 非常灵活,提供通过配置文件、命令行接口和具有成熟 Python 绑定的 API 进行配置。VPP 需要一个基础配置文件,告诉它从哪里获取命令,以及它使用的控制文件的名称(如果这些文件不是默认的)。我们可以在命令行中将一个最小配置文件作为 VPP 的参数之一。对于这个示例,我们让 VPP 进入交互模式——提供给我们一个 CLI,并告诉 VPP 只加载我们将使用的插件(netmap),这是一个合理的默认设置。

如果我们不禁用所有插件,我们将需要配置机器使用 DPDK,或者单独禁用该插件。禁用插件的语法与启用 netmap 插件的语法相同。

如果一切设置正确,你将看到 VPP 的横幅和默认的 CLI 提示符(vpp#)。

VPP 命令行界面提供了很多选项,用于创建和管理接口、像桥接一样的组、添加路由以及用于检查 VPP 实例性能的工具。

接口配置命令的语法类似于 Linux 的 iproute2 命令——对于来自 FreeBSD 的用户来说,这些命令可能稍显陌生,但待开始使用,它们还是相当清晰的。

我们的 VPP 服务器还没有配置任何主机接口,show int只列出了默认的local0接口。

要在 VPP 中使用我们的 netmap 接口,我们需要先创建它们,然后再进行配置。

创建命令允许我们创建新的接口,我们使用netmap子命令和主机接口。

每个 netmap 接口都以netmap-为前缀创建。接口创建完成后,我们可以配置它们以供使用,并开始将 VPP 用作路由器。

命令 show int addrshow interface address 的简写)确认了我们的 IP 地址分配已经成功。然后,我们可以将接口启用:

配置好接口后,我们可以通过使用 ping 命令来测试 VPP 的功能:

如果我们跳到客户端 jail,我们可以验证 VPP 正在充当路由器:

作为初始设置的最后一步,我们将在服务器 jail 中启动一个 iperf3 服务器,并使用客户端进行 TCP 吞吐量测试。

VPP 分析

现在我们已经通过 VPP 发送了一些流量,show int 命令的输出包含了更多信息:

接口命令现在给出了通过 VPP 接口传输的字节和数据包的摘要。这在调试流量如何流动时非常有用,特别是当你的数据包丢失时。

VPP 中的 V 代表向量(vector),这在项目中有两层含义。VPP 旨在使用向量化指令加速数据包处理,同时它还将一组数据包打包成向量,以优化处理。其理论是将一组数据包一起通过处理图,从而减少缓存争用并提供最佳性能。

VPP 提供了许多工具来查询数据包处理过程中的情况。深度调优超出了本文的讨论范围,但一个了解 VPP 内部发生情况的初步工具是运行时命令。

运行时数据会在每个向量通过 VPP 处理图时收集,记录每个节点的传输时间以及处理的向量数量。

要使用运行时工具,最好有一些流量。可以像这样启动一个长时间运行的 iperf3 吞吐量测试:

现在在 VPP jail 中,我们可以清除迄今为止收集到的运行时统计信息,稍等片刻,然后查看我们的运行情况:

show runtime 输出中的列为我们提供了关于 VPP 内部运行的极好洞察。它们告诉我们自从运行时计数器被清除以来,哪些节点已经被激活,它们的当前状态,每个节点被调用的次数,所使用的时间,以及每次调用处理的向量数量。默认情况下,VPP 的最大向量大小是 255。

一个最终的调试任务是使用 show vlib graph 命令检查整个数据包处理图。此命令显示每个节点及其潜在的父节点和子节点,帮助我们理解数据流向。

下一步

VPP 是一款令人印象深刻的软件——待解决了兼容性问题,VPP 的核心部分就相对容易移植。即使仅进行最小的调优,VPP 在 FreeBSD 上与 netmap 配合使用时也能够达到相当令人印象深刻的性能,并且如果配置了 DPDK,它的表现会更好。VPP 的文档正在逐步增加关于在 FreeBSD 上运行的信息,但开发者们确实需要更多关于 FreeBSD 上使用 VPP 的示例案例。

从这个简单网络的例子开始,将其移植到一个拥有更快接口的大型网络上应该是相对直接的。


Tom Jones 是一名 FreeBSD 提交者,致力于保持网络堆栈的高效运行。

最后更新于

这有帮助吗?