Как учесть Q-in-Q в NetBox: где хранить CVLAN, SVLAN и внешний тег порта
Q-in-Q — это не «ещё один VLAN», а отдельная модель данных: клиентский тег живёт внутри сервисного, и если завести оба тега как обычный trunk, связь между ними потеряется при первой же миграции. В NetBox с версии 4.2 для этого есть отдельные поля у VLAN и у интерфейса. Ниже — как я их использую, где обычно путают customer и service VLAN и что происходит, если оператор поменял внешний тег, а в базе об этом никто не узнал.
Почему обычный VLAN не описывает Q-in-Q
Q-in-Q, он же IEEE 802.1ad, — это инкапсуляция одного тега VLAN внутрь другого. Провайдер заворачивает трафик клиента в свой сервисный тег (SVLAN), а клиентский тег (CVLAN) едет внутри него нетронутым через всю сеть оператора. На интерфейсе клиента это выглядит как обычный access или trunk-порт, но на границе с оператором это уже два заголовка 802.1Q подряд. Когда я веду внедрение NetBox для компании, которая арендует L2-канал у оператора, я сразу спрашиваю: как размечен канал — простой VLAN, транк или именно Q-in-Q. Ответ определяет, какие поля заполнять в карточке VLAN и интерфейса, и я видел, как в двух разных проектах путали это до потери связи с филиалом.
До версии 4.2 в NetBox не было выделенной модели для этой связки. Администраторы либо заводили SVLAN как обычный VLAN и писали «сервисный, оператор X» в комментарии, либо вообще не документировали внешний тег — он жил только в конфиге коммутатора и в переписке с оператором. Оба варианта работают, пока об инфраструктуре помнит один человек. В момент, когда его сменяет коллега, инвентаризация или ITSM-система пытаются построить отчёт по VLAN, а два тега на одном порту неотличимы от обычного trunk с двумя вланами.
Как устроена модель Q-in-Q в NetBox
С релиза 4.2.0 (вышел 6 января 2025 года) в NetBox добавлена прямая поддержка обозначения клиентских (CVLAN) и сервисных (SVLAN) VLAN для инкапсуляции IEEE 802.1ad. Фича прошла путь от issue #13428 в репозитории netbox-community/netbox, где изначально предлагалась отдельная модель «svlan» и режим интерфейса «Double tagged»; в итоговой реализации от отдельной модели отказались в пользу двух новых полей у существующей модели VLAN — так проще фильтровать, строить отчёты и не плодить сущности.
У модели VLAN появилось необязательное поле qinq_role — оно указывает, чем является этот VLAN в топологии Q-in-Q: Customer (клиентский, CVLAN) или Service (сервисный, SVLAN). В интерфейсе вы видите эти подписи, а в базе и REST API хранятся короткие значения cvlan и svlan — это важно, если заполняете поля скриптом. Второе новое поле — qinq_svlan, рекурсивная связь VLAN на VLAN: в ней клиентский VLAN ссылается на свой сервисный VLAN. Документация прямо оговаривает: это поле можно задать только для клиентского VLAN, связь всегда идёт от CVLAN к SVLAN, а обратная сторона видна как список привязанных клиентских VLAN. Валидация в коде работает в обе стороны: qinq_svlan у VLAN с другой ролью NetBox не сохранит, а клиентский VLAN без указанного сервисного — тоже, с ошибкой «A Q-in-Q customer VLAN must be assigned to a service VLAN».
Практический вывод из этого ограничения: сначала заводите сервисный VLAN с ролью Service, и только потом клиентский с ролью Customer — связь указывается только на стороне клиентского VLAN и обязательна при его сохранении. Роль VLAN не заменяет обычные поля vid и name: у клиентского и сервисного VLAN по-прежнему свои идентификаторы, они просто дополнительно помечены ролью и связаны друг с другом.
Настройка интерфейса: режим Q-in-Q и qinq_svlan
Второе изменение 4.2 — новый режим 802.1Q на интерфейсе. У Interface (и у VMInterface — виртуальные интерфейсы получили ту же логику) в списке mode теперь четыре варианта: Access — весь трафик порта относится к одному VLAN без тега; Tagged — один нетегированный «родной» VLAN плюс любое число тегированных; Tagged (all) — интерфейс несёт все VLAN сразу; и новый Q-in-Q — на интерфейсе выполняется инкапсуляция IEEE 802.1ad с использованием назначенного сервисного VLAN. Это отдельный, самостоятельный режим, а не комбинация Tagged плюс комментарий.
Когда вы выставляете интерфейсу режим Q-in-Q, у него появляется поле qinq_svlan — «назначенный сервисный VLAN (для интерфейсов Q-in-Q/802.1ad)», как формулирует документация. Обратите внимание: у VLAN поле называется qinq_svlan и указывает на сервисный VLAN текущего клиентского VLAN, а у интерфейса поле с тем же именем qinq_svlan указывает, какой сервисный VLAN инкапсулируется на этом порту. Это не одно и то же поле в базе, у них разные модели и разные внешние ключи, но одинаковое смысловое назначение — обе привязки в итоге должны указывать на один и тот же объект VLAN с ролью Service. Форма редактирования интерфейса, кстати, сама предлагает в этом поле только VLAN с ролью Service, а API вернёт ошибку, если передать qinq_svlan интерфейсу в любом режиме, кроме q-in-q.
Клиентские теги на Q-in-Q-порту я задаю так же, как на обычном trunk: через tagged_vlans со ссылкой на VLAN с ролью Customer. Оговорюсь честно: страница документации про интерфейс описывает tagged_vlans как поле режима Tagged, но валидация API запрещает его только для Access и Tagged (all), а в 4.2 отдельно чинили отображение tagged VLAN у Q-in-Q-интерфейсов — то есть такой способ записи разработчики предусматривают. Иначе говоря, полная картина порта в сторону оператора — это режим Q-in-Q, один qinq_svlan (сервисный VLAN оператора) и один или несколько tagged_vlans (клиентские VLAN, которые реально едут внутри туннеля).
Пошагово: заводим канал с двойным тегированием
На практике я завожу связку в четыре шага. Сначала создаю сервисный VLAN — VID, который назначил оператор для вашего канала, с ролью Service (qinq_role = svlan) и понятным именем вроде SVLAN-Operator-Branch2. Затем создаю клиентский VLAN — тот VID, что реально используется в вашей сети (например, VLAN 10 с трафиком филиала), с ролью Customer (qinq_role = cvlan), и в его поле qinq_svlan сразу указываю только что созданный сервисный VLAN — без этого NetBox клиентский VLAN не сохранит. Дальше нахожу пограничный интерфейс — тот порт коммутатора, который физически смотрит в сторону оператора, — и меняю его mode на Q-in-Q, а в qinq_svlan интерфейса подставляю тот же сервисный VLAN. Последний шаг — добавляю клиентский VLAN в tagged_vlans этого интерфейса.
Через REST API это делается двумя PATCH-запросами: сначала клиентскому VLAN проставляется роль и ссылка на сервисный VLAN, затем интерфейсу — режим и сервисный VLAN.
curl -s -X PATCH https://netbox.example.local/api/ipam/vlans/142/ \
-H "Authorization: Token $NETBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"qinq_role": "cvlan", "qinq_svlan": 98}'
curl -s -X PATCH https://netbox.example.local/api/dcim/interfaces/551/ \
-H "Authorization: Token $NETBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"mode": "q-in-q", "qinq_svlan": 98, "tagged_vlans": [142]}'Обратите внимание: в API роль передаётся значением cvlan/svlan, а не словом customer — на него NetBox ответит ошибкой выбора. ID здесь условные — их нужно подставить свои, взятые из /api/ipam/vlans/ и /api/dcim/interfaces/. Токен создаётся в разделе учётных данных NetBox и должен иметь право записи в IPAM и DCIM для этой операции.
Отдельно проверяю обратную сторону: если у клиента несколько филиалов через одного оператора, сервисный VLAN обычно один на канал (или на точку присоединения), а клиентских VLAN может быть несколько — по одному на VRF или сегмент внутри туннеля. В этом случае у одного service-VLAN будет несколько клиентских VLAN со ссылкой qinq_svlan на него — модель это позволяет, ограничение стоит на направлении связи (от клиентского к сервисному), а не на количестве. Есть одно полезное ограничение уникальности: внутри одного сервисного VLAN не может быть двух клиентских с одинаковым VID или одинаковым именем. При этом один и тот же клиентский VID под разными SVLAN допустим — ровно так, как это и работает у оператора.
Кейс: подключение филиала через Q-in-Q у «Подбор без ошибок»
Условный клиент — рекрутинговая компания «Подбор без ошибок», 9 рабочих мест в головном офисе и небольшой филиал на три человека в другом бизнес-центре того же города. Вместо второго интернет-канала и VPN-туннеля компания арендовала у местного оператора L2-канал: порт в головном офисе и порт в филиале объединены в один Ethernet-сегмент через сеть провайдера. Оператор выдал сервисный VLAN 3401 на своей стороне и сказал, что клиентский трафик компании — VLAN 10 — «поедет прозрачно». До внедрения NetBox эта информация жила в одном письме от оператора и в конфиге пограничного коммутатора, без какой-либо записи в системе учёта.
Когда я заводил инфраструктуру компании в NetBox, я создал VLAN 3401 с ролью Service и именем SVLAN-Operator-L2-Branch, и VLAN 10 с ролью Customer и ссылкой qinq_svlan на VLAN 3401. Пограничный интерфейс на коммутаторе головного офиса получил режим Q-in-Q, qinq_svlan = VLAN 3401 и tagged_vlans = [VLAN 10]. Отдельно я оставил карточку устройства с комментарием, какой именно физический порт оператора это подключение занимает — эта информация в модель Q-in-Q не входит, но нужна для эскалации, если канал упадёт ночью.
Пользы от этого оказалось больше, чем я ожидал изначально. Через полгода оператор менял оборудование на своей стороне и попросил подтвердить, какой сервисный VLAN использует канал компании — ответ был получен за минуту прямым запросом к VLAN 3401 в NetBox, без поиска старой переписки. Ещё раз это пригодилось, когда в компании расширяли филиал и нужно было понять, можно ли добавить второй клиентский VLAN в тот же туннель без переговоров с оператором о новом сервисном VLAN — фильтр списка VLAN по qinq_svlan_vid=3401 сразу показал, что к этому сервисному VLAN привязан только VLAN 10, и новый VID 20 не конфликтует с уже заведёнными. Пропускную способность NetBox, конечно, не считает — её мы сверили с договором отдельно.
Частые ошибки при заведении Q-in-Q
Самая частая ошибка — перепутать направление связи. Администратор пытается указать qinq_svlan сервисному VLAN, ссылаясь на клиентский, — NetBox отклоняет такую попытку, потому что поле допустимо только для роли Customer. Если вам кажется, что нужно связать в обратную сторону, скорее всего, вы перепутали, какой VLAN клиентский, а какой сервисный: сервисный — тот, что назначил оператор для инкапсуляции, клиентский — тот, что реально используется вашей локальной сетью.
Вторая ошибка — заводить сервисный VLAN как обычный VLAN без заполненного qinq_role, потому что «он всё равно не используется напрямую в вашей сети». Формально трафик действительно продолжит ходить: коммутатор не проверяет заполненность полей в NetBox. Но тогда при следующем аудите или генерации отчёта по VLAN сервисный тег окажется неотличим от обычного неиспользуемого VLAN, и кто-то удалит его как «мёртвый», разорвав канал в самый неподходящий момент.
Третья, более редкая ситуация — интерфейс оставлен в режиме Tagged вместо Q-in-Q, а оба VLAN просто добавлены в tagged_vlans. Синтаксически это допустимо и ничего не сломает в самом NetBox, но модель перестаёт отражать реальность: Tagged означает «несколько независимых VLAN на одном порту», а не «один VLAN внутри другого». Отчёты по использованию VLAN и любая автоматизация, которая опирается на mode интерфейса, в этом случае будут работать с неверными допущениями о топологии. Такая же дисциплина точных полей вместо приблизительных нужна и в других сетевых механизмах — например, в синхронизации времени по PTPv2, где микросекундная точность тоже не описывается на словах.
Когда заводить Q-in-Q, а когда достаточно общей документации сети
Если в компании нет L2-каналов через операторов и никакой инкапсуляции VLAN в VLAN, отдельно разбираться с полями qinq_role и qinq_svlan не нужно — это узкая модель именно под 802.1ad, и обычные VLAN с tagged_vlans полностью покрывают внутреннюю сеть офиса. Я подробно писал про то, с чего вообще начинать документацию инфраструктуры в NetBox: DCIM, IPAM, стойки и кабели — там про Q-in-Q почти ничего нет специально, потому что для большинства компаний до 50 рабочих мест этот сценарий не встречается.
Q-in-Q стоит заводить, как только у вас появляется хотя бы один канал, где провайдер оперирует сервисным VLAN, а вы — клиентским: аренда L2-канала между офисами, подключение к сети оператора ЦОД через его агрегирующий коммутатор. Даже если у вас один такой канал на всю компанию, разница между «просто trunk» и корректно описанным Q-in-Q проявится в первый же раз, когда придётся объясняться с оператором или передавать инфраструктуру новому администратору. Десять минут на заполнение двух полей у VLAN и двух у интерфейса стоят дешевле часа переписки с техподдержкой провайдера.
Частые вопросы
С какой версии NetBox доступна поддержка Q-in-Q?
С версии 4.2.0, вышедшей 6 января 2025 года. Тогда у модели VLAN появились поля qinq_role и qinq_svlan, а у Interface и VMInterface — режим mode «Q-in-Q» и поле qinq_svlan.
Можно ли задать qinq_svlan у сервисного VLAN?
Нет. Поле qinq_svlan допустимо только у VLAN с ролью Customer (в API — cvlan): оно указывает, какому сервисному VLAN подчинён клиентский. Более того, клиентский VLAN без qinq_svlan NetBox не сохранит.
Чем отличается режим интерфейса Q-in-Q от Tagged?
Tagged означает несколько независимых VLAN на одном порту с одним нетегированным «родным» VLAN. Q-in-Q — отдельный режим (в API значение q-in-q), где выполняется инкапсуляция IEEE 802.1ad с использованием сервисного VLAN из поля qinq_svlan интерфейса.
Может ли у одного сервисного VLAN быть несколько клиентских?
Да: несколько VLAN с ролью Customer могут ссылаться через qinq_svlan на один сервисный VLAN. Ограничение одно — внутри одного SVLAN клиентские VID и имена должны быть уникальны.
Нужно ли поддерживать Q-in-Q, если в офисе один интернет-канал без операторских VLAN?
Нет. Поля qinq_role и qinq_svlan нужны только когда провайдер или другая сторона реально инкапсулирует ваш VLAN в свой сервисный. Для обычной внутренней сети офиса хватает стандартных VLAN и режима Tagged/Access.
Работает ли Q-in-Q для виртуальных интерфейсов, а не только физических портов коммутаторов?
Да, у VMInterface та же логика: режим 802.1Q с вариантом Q-in-Q и поле qinq_svlan появились в 4.2 одновременно и для Interface, и для VMInterface.
Источники
- NetBox Documentation — VLAN model — Поля qinq_role (Customer/Service, в коде cvlan/svlan — ipam/choices.py VLANQinQRoleChoices) и qinq_svlan (только для customer; customer обязан иметь SVLAN — ipam/models/vlans.py clean()). https://netboxlabs.com/docs/netbox/models/ipam/vlan/
- NetBox Documentation — Interface model — Режимы 802.1Q Mode (Access, Tagged, Tagged all, Q-in-Q) и поле Q-in-Q SVLAN у Interface. https://netboxlabs.com/docs/netbox/models/dcim/interface/
- NetBox Documentation — VMInterface model — Подтверждение, что режим Q-in-Q и поле qinq_svlan доступны и для виртуальных интерфейсов. https://netboxlabs.com/docs/netbox/models/virtualization/vminterface/
- NetBox Release Notes — Version 4.2 — Дата релиза 4.2.0 (2025-01-06), добавление CVLAN/SVLAN для IEEE 802.1ad/Q-in-Q, новые поля qinq_role, qinq_svlan, новый выбор mode «Q-in-Q». https://netboxlabs.com/docs/netbox/release-notes/version-4.2/
- GitHub netbox-community/netbox — Issue #13428 — Исходное предложение поддержки QinQ, обсуждение изначального варианта с отдельной моделью svlan и режимом Double tagged, итоговая реализация в 4.2. https://github.com/netbox-community/netbox/issues/13428
- GitHub netbox-community/netbox — Releases — Актуальная стабильная версия на 23.09.2026 — v4.7.1 (15 сентября 2026), v4.7.0 (2 сентября 2026). https://github.com/netbox-community/netbox/releases



