немного о QinQ

QinQ — технология, позволяющая тегировать траффик два раза, назначая ему сразу две метки. Зачем это надо, как настроить и какие грабли тут подстерегают — я решил описать в виде мини-статейки.
Предупреждаю сразу — если вы не относитесь к сетевикам-затейникам, то прочтение статьи может вызвать взрыв моска. …

Вообще разделение физических сетей на изолированные друг от друга виртуальные сетки или вланы (802.1q VLAN) существует уже давно. Протокол этот давно обкатан и одинаково работает везде. Но в какой-то момент стало понятно, что 12 бит для номера виртуальной сети — это всего лишь 4095 вланов. Кроме того, в сложных сетях согласование, учет и поддержание консистентных настроек для используемых номеров вланов вылился в отдельную проблему. Вдобавок, желая пропуская через свою сеть клиентский тегированный траффик, провайдерам совершенно не хотелось курить кривые и не шибко шустрые впн-ки, к тому же согласовывать свои номера вланов и номера вланов клиента — получалось далеко не всегда, и посему живительная идея пробрасывать пачку вланов между двумя точками сети, не разбираясь, что это за вланы и кто и зачем их настраивал — была востребована более чем. Поэтому разработчеги, не мудрствуя лукаво, сделали дешево и сердито — решили навешивать ещё одну метку.

Подобное извращение чаще всего встречается в двух случаях:
1). Там, где не хватило четырех с хером тысяч вланов. Это обычно провайдеры со схемой включения vlan-per-user. Схема достаточно жутенькая, но иногда встречается.
2). Там, где не удалось придти к соглашению о номерах вланов. Наиболее частый пример — это провайдеры и такие клиенты, у которых уже есть своя настроенная сеть с тегированным траффиком и сугубо со своими вланами, переделывать которую и портить костылями никому не хочется. В какой-то момент такие клиенты хотят построить единую сеть, и в этом случае клиент хочет, чтобы провайдер пробросил все его вланы каким-либо способом через свою сеть. QinQ — как раз один из таких методов.

Для примера посмотрим вот на такую схему:

Есть два клиента, у каждого из которых есть своя сложная сеть. И вот им приперло соединить свои филиалы в единую сеть, прозрачно пробросив свои вланы через сеть вышележащего прова. Понятно, что согласовать вланы и обойтись простым тегированием тут не выйдет. Влан 1 (он же влан по-умолчанию) у каждого клиента свой, а у провайдера — свой. Да и админ банка сильно удивится, если увидит в своем втором влане левый траффик от добывающей компании 😀 .

Суть QinQ вообщем-то проста и незатейлива — переводим клиентские порты в особый режим «туннелирования клиентских вланов». Режим этот у циско называется «dot1q-tunnel», у длинка- qinq-UNI. В этом случае железка для таких портов не занимается анализом тегов у входящих пакетов, а тупо наворачивает на них еще одну метку (внешнюю), по которой собственно и ориентируется провайдерское оборудование. На схеме выше тегированный траффик клиентских вланов 1 и 2 для одной компании будет дополнительно обернут тегом 3015, а для другой — тегом 3016. При выходе через такие хитрые порты с дважды тегированного траффика будет срезана только внешняя (провайдерская) метка с номером 301x, и клиенту будет направлен уже одиночно тегированный (его внутренними тегами!) траффик, который можно и нужно будет принять самым обычным 802.1q-транком.

Клиенту тут сплошные удобства — ему не надо вообще задумываться про QinQ, он строит свои собственные вланы как он хочет.

Теперь посмотрим, как это работает. Смотреть будем Wireshark-ом, втыкая его в нужный порт на тестовом стенде. Скажу честно — без раскурки дампов траффика поначалу въехать может быть тяжеловато.
Простое одиночное тегирование по 802.1q, оно же влан-вульгарис, работает вот так:
[Eth-Header; type: 0x0800] [IP] —802.1q—>
[Eth-Header; type: 0x8100] [802.1q; VLAN: 2; type: 0x0800] [IP]
Я постарался выделить добавленный заголовок и изменившиеся значения типа полезной нагрузки. Тут никаких особых проблем нет.

QinQ повторяет подобный трюк еще раз, и вот тут мы встречаем самые первые грабли.
По стандарту QinQ (он же 802.1ad) должен работать вот так:
[Eth-Header; type: 0x8100] [802.1q; VLAN: 2; type: 0x0800] [IP] —QinQ—>
[Eth-Header; type: 0x88a8] [802.1ad; VLAN: 3015; type: 0x8100] [802.1q; VLAN: 2; type: 0x0800] [IP]
В дампе траффика это выглядит вот так:

Однако такой тип в L2-заголовке, хоть и прописан в стандарте, нормально понимают только некоторые типы железок.

Приснопамятная циска решила, что нехх мутить воду, и решила специальное значение type = 0x88a8 для QinQ-траффика не использовать, вместо этого навешивая два совершенно одинаковых 802.1q-заголовка подряд:
[Eth-Header; type: 0x8100] [802.1q; VLAN: 2; type: 0x0800] [IP] —Cisco-QinQ—>
[Eth-Header; type: 0x8100] [802.1q; VLAN: 3015; type: 0x8100] [802.1q; VLAN: 2; type: 0x0800] [IP]
В дампе траффика это выглядит вот так:

Так вот — это вызывает определенную попаболь при попытке состыковать оборудование разных производителей. Вещь неочевидная, и детально особо нигде не описанная. Формально и то, и другое — дважды тегированный траффик, но QinQ по стандарту имеет право называться только первый вариант. К сожалению, у циско тут нашлись последователи, так что тип 0х8100 в QinQ-траффике вполне себе живет и здравствует. Так что если у вас все настроено, но траффик не ходит или ходит как-то странно и местами — проверьте тип. Это особенно актуально, если на разных концах туннеля используется оборудование от разных производителей. Например, в датацентре может стоять теплая ламповая циска, а на втором конце туннеля в Урюпинске — D-Link или ещё что похуже.

Внутренние интерфейсы, смотрящие внутрь провайдерской сети, настраиваются как обычные транки, для которых разрешается прохождение вланов 3015 и 3016, выделенных QinQ-клиентам. О внутренних вланах клиента провайдеру как правило знать ничего не требуется, и в настройке там ничего интересного нет.

Итак, вы познали дзен L2-типов, прописали везде 0x8100 (на некоторых цисках — 0x9100 и даже 0x9200 для пущего кайфа 😀 :D), и тут вас подстерегают следующие грабли.

Называются они MTU, он же максимальный размер кадра. Ясен хер, что использование двойного тегирования увеличивает размер кадра. Минимум увеличить надо до 1504 байт, но лучше прописать несколько больше. Можно без проблем поставить 1600 и забыть. Засада тут в том, что для цисок изменение System MTU требует … перезагрузки маршрутизатора. А точнее _всех_ цисок, у которых размер SystemMTU недостаточен и через которые пойдет QinQ-траффик. Это очень, очень гнусно, поэтому рекомендуется сделать это сильно заранее и как всякое настоящее злодейство — глубокой ночью.
Однако это только прелюдия к граблям. Самая суть граблей с MTU может обнаружиться в виде кетайского медиа-конвертера, который ясен фиг никак обнаруживаться не будет. Симптомы мерзейшие: пинг ходит, трейс ходит, SSH работает. А вот HTTP и RDP — хуй. Лучшее решение тут — выкинуть китайские конвертеры нахуй.
Ещё один возможный косяк — это MTU и работа протоколов динамической маршрутизации. Читать тут, бдить, грабли всегда где-то рядом 😀.

Остальные грабли более специфичны и фичасты, и по ним мы прогуляемся в процессе настройки.

На циске
Тут все достаточно просто. Убеждаемся, что SystemMTU — торт, создаем выделенный для клиента влан, в который завернем клиентские вланы, пропишем его на промежуточных транках, как обчно. Потом на порту, смотрящем в сторону ТвистГаза, пишем:

configure terminal
interface <интерфейс к клиенту>
switchport access vlan 3015
switchport mode dot1q-tunnel

Посмотреть на содеянные безобразия —

show dot1q-tunnel
show vlan dot1q tag native

Если безобразия нас устраивают — не забываем сохранить и забэкапить конфиг.
Если же есть желание изначально избежать встречи с этими граблями, то в помощь команда

dot1q tunneling ethertype {0x88a8|0x9100|0x????...}

Тут тоже лежит специальный бережно сохраненный костыль — у разных цисок набор допустимых к включению типов разный. Стороннее оборудование естественно иногда не понимает, что это за НЁХ с 0x9100 :cat: Собственно, всё. Более сложные случаи рассматриваются в документации, например на сайте циски.

на D-Link.
Там все гораздо, гораздо более запущено. Причем сильно запущено. Первое, с чего надо начать — с обновления версий прошивок. Кто не верит — может на форуме д-линка поискать про QinQ. На старых прошивках был занятнейший баг — настроить роли портов для QinQ можно было только после глобального включения этого самого QinQ. Однако его включение «по-тупому» (а это была единственная возможная команда) приводило к тому, что у такого свитча отваливалось управление. :bug: Так что мой вам добрый, очень добрый совет — перед использованием QinQ на д-линках смоделировать все на тестовом стенде, не забывая втыкать ноут со сниффером в разные интересные места тестового стенда. В отличие от циски, где самое серьезное изменение — это SystemMTU, а настройки QinQ затрагивают один-единственный порт, тут настройки затрагивают свитч целиком.

Особый фактор риска — это управление в не-нативном влане c VLAN_iD != 1. Тут вероятность отстрелить себе яйца в процессе настройки гораздо выше.
Поехали настраивать. Скажу сразу — мы не используем асимметричные вланы, и как оно стыкуется с QinQ конкретно на д-линке — без малейшего понятия. Я предполагаю, что следующие две настройки у вас вот такие:

disable asymmetric_vlan
enable pvid auto_assign

Настроим самый обычные вланы, какие мы делаем обычно, но назовем их понятным образом:

# R2
create vlan qinq_3015 tag 3015
config vlan qinq_3015 add tagged 9-10
config vlan qinq_3015 add untagged 8

# R3
create vlan qinq_3016 tag 3016
config vlan qinq_3016 add tagged 9-10
config vlan qinq_3016 add untagged 8

Вздрогнули, помолились, включаем:

enable qinq

Теперь настраиваем собственно QinQ. И вот мы получаем по лбу первыми граблями от д-линка. На свитче со включенным QinQ порт может быть в двух режимах — UNI и NNI. Д-линк прямо пишет в документации, что первый — для клиентского траффика, а NNI-порты должны смотреть в сторону ядра сети. После включения все порты однако будут именно в NNI-режиме. Отдельного Normal-режима или access-порта-вульгарис при включенном глобально qinq на д-линке не предусмотрено. Остерегайтесь граблей 😀

А что всё-таки делать с обычными клиентскими access-портами на этом же свитче ? Д-линк, насколько я понял, подразумевает их настройку как UNI, но в этом случае если клиент пошлет туда тегированный траффик — он отправится по нашей сети дважды тегированным. Если разобрать такой траффик будет некому — то для нас ничего страшного не случится. Если оставить их как NNI (то есть для тегированного траффика вторая метка не навешивается, режим включенный по умолчанию), то доступ порта к вланам все равно по-прежнему будет регулироваться настройками обычных вланов. В документации от д-линка этот вопрос освещен достаточно мутно. На DES-3200-10 обычный клиентский порт, добавленный как untagged в соответствующий клиентский влан, нормально работал как в UNI, так и в NNI-режиме. Я рекомендую оставить настройку в NNI, в этом случае вторая метка навешиваться точно не будет (нафиг эту головную боль на клиенстких портах), а членство во вланах регулироваться будет как обычно.

Тут грабли с TPiD встречаются нам ещё раз: при глобально действующем outer_tpid нужно ставить 0х8100. При любых других значениях обычные (не-QinQ) вланы работать не будут вовсе. Если кстати у вас управляющий влан — не нативен (то есть ходит тегированным), то смена outer_tpid на что-либо отличное от 0x8100 приведёт к невозможности приема одиночно тегированного траффика другим оборудованием, и соответственно к потере управления свитчем с последующим отлётом яиц в дальний космос. Да, д-линк такой д-линк. На свитчах типа DGS-3627G с этим получше — там в новых прошивках уже можно задавать TPiD для каждого порта отдельно. Не прошло и десяти лет.

Поскольку нам не интересно вмешиваться во внутренние теги (мы настраиваем Port-Based QinQ, про Selective QinQ пока не будем), то выключаем влан-трансляцию и доверие клиентским VLAN_iD:

config qinq ports all trust_cvid disable vlan_translation disable

Теперь надо решить, какой тип дважды тегированного траффика будет. У меня заработало на значении 0x8100 (dot1q-tunnel, который Cisco-QinQ), но поскольку у д-линка по умолчанию включен стандартный QinQ (0x88a8) — то меняем:

config qinq ports all outer_tpid 0x8100

Чтобы включить назад стандартный QinQ, соответственно:

config qinq ports all outer_tpid 0x88a8

Тут тоже у д-линка лежит ещё одна кучка садово-огородного инвентаря. На куче железок поменять можно только тип исходящих кадров, и только для _всех_ портов сразу. Попытка сменить outer_tpid только для одного порта — сопровождается оповещением, что параметр сменен глобально.

Теперь переводим порт, смотрящий в сторону клиента, в режим навешивания второй метки для тегированного траффика:

config qinq ports 8 role uni

После этого входящий в порт траффик будет независимо то наличия первой метки оборачиваться второй меткой из значения PVID для этого порта (именно для этого мы указали, что порт 8 — нетегированный в 3015-м влане) и отправляться в сеть внутри кадра с типом из outer_tpid.
Транк-порт оставляем в режиме NNI — там ничего трогать как правило не надо, разве что разрешить прохождение нового qinq-влана.

Какие ещё грабли могут подстерегать ? Могут возникнуть траблы с передачей нетегированного траффика внутри QinQ-туннеля. Решается вот такой командой для клиентского порта:

config gvrp 8 acceptable_frame admit_all

Опять же детали не скажу — тут надо много тестить, на каждой железке есть свои багофичи и прочие неисправимые преимущества.

О тестировании.

Мониторинг траффика Wireshark-ом — это конечно няшно и красиво, но хотелось бы ещё иметь возможность активно вмешиваться в тестирование, генерируя поток нужного типа траффика со своего ноута и проверяя, куда и как это траффик ходит. Короче, нам надо уметь поднимать сабинтерфейсы для дважды тегированного траффика как на железках, которые это умеют, так и на тестовой машине со сниффером.
На маршрутизаторах циско сабинтерфейс для дважды тегированного траффика поднимается легко, красиво и непринужденно:

interface GigabitEthernet0/1.3015
   encapsulation dot1Q 3015 second-dot1q 1
   ip address 192.168.1.0 255.255.255.0

Вообщем, также как и обычные сабинтерфейсы, только в параметре encapsulation указываем ещё и second-dot1q <номер внутреннего влана>.
Что касается д-линков, то там сабинтерфейсы для дважды тегированного траффика наши железки не умеют, увы.

На линуксе (Fedora17) QinQ-сабинтерефейс поднимается аналогично интерфейсу в одиночном влане, с помощью команды vconfig. Например, для анализа траффика в выше приведенной схеме делем вот так:

# vconfig add eth0 3015
# vconfig add eth0 3016
# vconfig add eth0.3015 1
# vconfig add eth0.3015 2
# vconfig add eth0.3016 1
# vconfig add eth0.3016 2

Этими командами мы создали для сетевой карты eth0 два сабинтерфейса для снятия внешних меток — eth0.3015 / eth0.3016 и еще четыре сабинтерфеса для qinq-траффика: eth0.3015.1, eth0.3015.2, eth0.3016.1 и eth0.3016.2 . Настройка параметров делается с помощью того же ifconfig:

# ifconfig eth0.3015.1 inet 192.168.1.0/24 up

После этих настроек перезапускаем Wireshark, и видим в списке шесть новых сетевых интерфейсов. Окно с общим списком интерфейсов позволяет сразу увидеть, сколько пакетов приходит на каждый сабинтерфейс, и посмотреть, куда какой траффик приходит и как снимаются метки на линуксе. Входящие дважды тегированные пакеты обрабатываются и нормально разбираются с любым TPiD (судя по статистике на сабинтерфейсах и дампам траффика), а вот исходящие пакеты по-умолчанию идут с TPID = 0x8100. Так что если на оборудовании как-то по-другому — траффик будет идти только в одну сторону (линуксовая машина принять и разобрать траффик сможет, а вот посланные её пакеты будут отброшены оборудованием из-за несовпадения TPiD). Если кто знает, как сделать так, чтобы только для дважды тегированных пакетов линукс ставил некий заранее заданный TPiD для тестирования других вариантов настройки QinQ — буду крайне признателен.

На FreeBSD (8.2) мне удалось поднять только одиночно тегированный сабинтерфейс, фокус с QinQ не прошел. Фряха без проблем работает с сабинтерфейсами для обычных вланов, а вот с QinQ не вышло — сабинтерфейс на сабинтерфейсе уже не создается.

На винде разбор QinQ вам не грозит ни в каком виде и никак, даже если вы сделаете миньет Баллмеру. Там и обычные-то вланы нихера нативно не поддерживаются (только на некоторых сетевухах, криво и после продолжительного секаса с дровами), а про qinq даже не мечтайте, не в этой жизни. В контексте данной статьи Windows Server 2008 Datacenter Edition и Windows 95 для нас одинаково убоги и для тестирования абсолютно непригодны.

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

Запись опубликована в рубрике *Сети, Сетевое. Добавьте в закладки постоянную ссылку.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Я не спамер This plugin created by Alexei91