Установка задержки между устройствами Firecracker microVM tap на одном хосте

Установка задержки между устройствами Firecracker microVM tap на одном хосте

Я настроил две микровиртуальные машины с помощью Firecracker на моем хосте Ubuntu 18.04 LTS и подключил устройство tun/tap к каждой из них. Теперь я пытаюсь установить задержку между двумя виртуальными машинами (скажем, 100 мс), используя tcтак, чтобы получить RTT между ними в 200 мс, но, похоже, я не могу заставить это работать должным образом.

В идеале я бы хотел указать оба устройства напрямую, tcно, похоже, для этого мне придется указать их сети.

Вот как устроены краны (в соответствии сДокументация по фейерверкам), по одному для каждой машины 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/30для B) и указываю IP-адреса, которые получат ответвители на стороне хоста. Я загружаю машины с адресами 10.0.0.30/30для A и 10.0.0.34/30для B (конфигурация устанавливается при загрузке) и могу успешно пинговать их друг с друга и с хоста.

В результате моих исследований я нашел 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 и наоборот, но ничего не происходит. Как ни странно, установка этих фильтров работает:

# 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), когда я отправляю ping с машины A на машину B, пакет исходит с точки зрения A, но входит с точки зрения хоста, поскольку tapAустройство хоста подключено к eth0устройству в A. Оба устройства вместе фактически образуют tun/tap. Следовательно, пакет также исходит на `tapB`` и (это имеет смысл) входит на B.

Поскольку tcя могу управлять только исходящими пакетами, но не входящими (по крайней мере, если вы не перенаправляете их через какой-либо другой виртуальный интерфейс), я могу применить задержку A->B только к tapB(когда пакет исходит в B) и задержку B->A к tapA.

На данный момент я придерживаюсь этого решения, пока не появится что-то лучшее.

Связанный контент