在同一主机上设置 Firecracker microVM tap 设备之间的延迟

在同一主机上设置 Firecracker microVM tap 设备之间的延迟

我已经在 Ubuntu 18.04 LTS 主机上使用 Firecracker 设置了两个 microVM,并为每个 microVM 连接了一个 tun/tap 设备。现在我尝试在两个 VM 之间设置延迟(例如 100ms),tc以便在它们之间获得 200ms 的 RTT,但我似乎无法让它正常工作。

理想情况下,我希望直接指定这两个设备,tc但似乎我必须指定它们的网络才能使其工作。

以下是水龙头的设置方法(按照Firecracker 文档),机器 A 和 B 各一个:

# create a tap device
sudo ip tuntap add tapA mode tap
sudo ip tuntap add tapB mode tap
# set up tap device ip address
sudo ip addr add 10.0.0.29/30 dev tapA
sudo ip addr add 10.0.0.33/30 dev tapB
# set up tap device
sudo ip link set tapA up
sudo ip link set tapB up
# enable forwarding
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
# add iptables config
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i tapA -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i tapB -o eth0 -j ACCEPT

如您所见,我为每台机器提供了一个小型专用网络(10.0.0.28/30用于 A 和10.0.0.32/30B),并指定了主机端的分接头将获得的 IP 地址。我使用10.0.0.30/30A 和10.0.0.34/30B 的地址启动机器(启动时设置的配置),并且可以成功地从彼此和主机 ping 通它们。

通过研究,我发现tc我期望可以起作用的命令:

# create a qdisc for tapA
tc qdisc add dev tapA root handle 1: htb default 1
tc class add dev tapA parent 1: classid 1:1 htb rate 10.0Gbit
tc class add dev tapA parent 1: classid 1:2 htb rate 10.0Gbit ceil 10.0Gbit
# add a delay of 100ms
tc qdisc add dev tapA parent 1:2 handle 2: netem delay 100.0ms
# only apply that delay when the packet comes from A's network and goes to B's network
tc filter add dev tapA protocol ip parent 1: prio 5 u32 match ip dst 10.0.0.32/30 match ip src 10.0.0.28/30 flowid 1:2

# do the same for tapB
tc qdisc add dev tapB root handle 1: htb default 1
tc class add dev tapB parent 1: classid 1:1 htb rate 10.0Gbit
tc class add dev tapB parent 1: classid 1:2 htb rate 10.0Gbit ceil 10.0Gbit
tc filter qdisc add dev tapB parent 1:2 handle 2: netem delay 100.0ms
# but this time going from B's network to A's network
tc filter add dev tapB protocol ip parent 1: prio 5 u32 match ip dst 10.0.0.28/30 match ip src 10.0.0.32/30 flowid 1:2

我本以为这会给从 A 到 B 以及从 B 到 A 的所有传出数据包增加延迟,但什么也没发生。奇怪的是,设置这些过滤器有效:

# matching destination of A on A's tap
# this should match incoming packets from B to A on tapA
tc filter add dev tapA protocol ip parent 1: prio 5 u32 match ip dst 10.0.0.28/30 match ip src 10.0.0.32/30 flowid 1:2

# and vice versa for tapB
tc filter add dev tapB protocol ip parent 1: prio 5 u32 match ip dst 10.0.0.32/30 match ip src 10.0.0.28/30 flowid 1:2

如果我理解正确,这意味着tc检查传入的数据包并应用正确的过滤器。但这并不是我真正期望发生的事情,我更希望传出的数据包被过滤和延迟。还是我遗漏了什么?

答案1

我做了一些进一步的研究,我想我开始明白这里发生了什么。如果有人确定细节,请在下面留下答案,但为了任何可能遇到这个问题的人,我也在这里留下了我的解释。

ping 命令中的数据包概述

我认为 tap 对于 microVM 和主机来说看起来是一样的,但我认为这不太正确。正如您在图片中看到的(显示简单命令的步骤ping),当我从机器 A 向机器 B 发送 ping 时,数据包从 A 的角度来看是传出的,但从主机的角度来看是传入的,因为主机设备tapA连接到eth0A 中的设备。这两个设备实际上一起构成了tun/tap。因此,数据包在“tapB”上也是传出的,并且(这是有道理的)在 B 上是传入的。

由于tc只能管理传出的数据包而不能管理传入的数据包(至少如果您不通过其他虚拟接口重定向它们),我只能在 上应用 A->B 延迟tapB(其中数据包传出到 B)并在 上应用 B->A 延迟tapA

现在我将保留这个解决方法,直到出现更好的方法。

相关内容