VSOCK — коммуникация между гостем и хостом с минимальными затратами (Арсений Краснов, OSSDEVCONF-2023)
Материал из 0x1.tv
- Докладчик
- Арсений Краснов
В рамках работы над собственной операционной системой Salute OS для умных устройств мы в SberDevices активно проводили исследования по использованию виртуализации в целях повышения безопасности и использовали технологию VSOCK, о которой пойдёт речь в данном докладе.
Я являюсь одним из контрибьюторов в данную технологию в ядре Linux.
VSOCK-сокеты — это семейство сокетов, которые предназначены для создания канала передачи данных между приложением в гостевой ОС и приложением в хосте. Для работы с ними используется POSIX API-сокетов.
В докладе рассказывается про отличия VSOCK сокетов от привычных нам сокетов (например, TCP), описывается внутреннее устройство этой подсистемы в ядре Linux, описываются сценарии использования таких сокетов, их текущий статус в ядре Linux и планы по дальнейшему развитию.
Содержание
Видео
Презентация
Thesis
VSOCK — это акроним, который означает Virtual machine SOCKet. VSOCK-сокеты представляют собой POSIX-совместимый интерфейс сокетов, аналогичный TCP или UNIX-сокетам.
Доступны те же самые вызовы, которые используются для работы с другими типами сокетов и описаны в POSIX: socket(), connect(), listen(), bind(), accept() и т.д.
Разница с TCP, например, заключается в адресации: вместо IP-адреса используется так называемый CID (context ID). Некоторые значения CID являются зарезервированными: 1 — loopback (передача данных в пределах одной ОС, аналогично localhost), 2 — host, 3 и выше — для гостевых ОС. Порт же имеет тот же самый смысл, что и в TCP-сокетах. Таким образом, можно легко переделывать существующие приложения на данный тип сокетов. Также при создании VSOCK- сокета в вызов socket() нужно передавать параметр AF_VSOCK в отличие от TCP-сокетов, где используется AF_INET.
В чем преимущество использования таких сокетов, в отличие, например, от виртуальной сетевой карты и обычных сетевых протоколов? Основное отличие: VSOCK-коммуникация не требует никаких настроек — сразу после загрузки драйвера можно начинать обмен данными. Не нужно стартовать сетевой интерфейс, назначать ему адрес и другие параметры сети. CID хоста назначается автоматически и всегда равен 2 — таким образом, хост всегда доступен из гостя по данному адресу. CID же гостевых систем назначаются вручную либо автоматически при их запуске, и начинаются с 3.
На данный момент VSOCK используют следующие решения: Qemu guest agent, Kata container agent, Android debug bridge.
VSOCK подсистему можно представить как высокоуровневую реализацию AF_VSOCK сокетов и лежащую под ней транспортную часть, которая обеспечивает протокол передачи и саму передачу данных между гостем и хостом. Транспортная часть зависит от гипервизора. На данный момент реализованы четыре транспорта: virtio, Hyper-V(Microsoft), VMCI (VMWare) и loopback.
Поддерживаются три типа сокетов: SOCK_STREAM (на всех трех транспортах), SOCK_DGRAM (только на VMCI), SOCK_SEQPACKET (только на virtio).
Остановимся подробнее на virtio-транспорте. Как видно из названия, для передачи данных здесь используются virtio-очереди. Одна очередь для приема данных из гостя, вторая для передачи данных в гостя. В госте запускается virtio драйвер, со стороны хоста же работает vhost драйвер. Также реализуется внутренний протокол, который служит для двух целей:
1) Установка и разрыв соединения (аналогично например протоколу TCP). Это нужно для поддержки SOCK_STREAM и SOCK_SEQPACKET сокетов, так как они должны поддерживать установку соединения.
2) Контроль за объемом передаваемых данных. Это позволяет ограничивать объём передаваемых данных принимающей стороне, чтобы не вызвать большой расход памяти, т. е. когда пакеты копятся на принимающей стороне, но не вычитываются из сокета и, таким образом, не могут быть освобождены.
VSOCK-сокеты поддерживаются в следующих утилитах для работы с сокетами/сетью: wireshark, iproute2, tcpdump, nmap, iperf-vsock, socat-vsock.
Также имеется поддержка в следующих языках: C (glibc), python (3.7), Golang, Rust.
Дальнейшие планы по развитию VSOCK:
1) SOCK_DGRAM на virtio транспорте (code review)
2) передача в режиме zerocopy (code review). Используется флаг MSG_ZEROCOPY в вызове send()/sendto()/sendmsg(). В данном режиме память с данными, которые хочет передать пользовательское приложение, начинает использоваться как virtio-буфер и таким образом избегается копирование между userspace и ядром.
3) прием в режиме zerocopy (RFC). В данном режиме пользователь создает маппинг виртуальной памяти с помощью вызова mmap(), и далее ядро при получении данных будет отображать в данный маппинг страницы приемных virtio-буферов. Таким образом снова избегается копирование между userspace и ядром.
В заключение стоит отметить преимущества данного типа сокетов:
1) Легко адаптировать уже существующие сетевые приложения под данный тип сокетов.
2) Канал данных не требует никакой настройки по сравнению с виртуальной сетевой картой или механизмом обмена данными между гостем и хостом.
3) Уже имеется поддержка в библиотеках популярных языков программирования.