> For the complete documentation index, see [llms.txt](https://linkmeup.gitbook.io/sdsm/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://linkmeup.gitbook.io/sdsm/12.-mpls-l2vpn/2.-vpls/3.-kompella-mode/2.-label-block.md).

# Распределение меток и механизм Label Block

Помните фразу "*Хочешь накормить человека один раз — дай ему рыбу. Хочешь накормить его на всю жизнь — дай ему удочку*"? Для выделения меток в VPLS Kompella mode используется механизм блоков меток. Один PE другому не сообщает точное значение — он даёт ему информацию для её вычисления.

Я по себе я знаю, что пытаться понять что-то пока ты не знаешь, зачем оно нужно — путь к несварению и трата лишнего времени. В конце этой главы я расскажу, зачем нужна такая странная схема, а пока вы разбираетесь, просто поверьте мне и Кирити Компелле — нужна.

> Есть мнение, что видео перед текстом помогает лучше разобраться.

Если не вдаваться в конфигурацию, то выглядит это так:

1. В каждом VSI настраивается RD и RT — их функции ровно те же самые, что в L3VPN. На CSR1000V это происходит автоматически, не требуя ручной настройки.

   RD позволяет разделять информацию разных VSI при передаче.

   RT позволяет маршрутизатору-получателю определить, в какой VSI нужно эту информацию транслировать.

   RD и RT позже будут передаваться в сообщении BGP Update.
2. В секции BGP настраивается новая адрес-фэмили L2VPN VPLS, внутри которой поднимается соседство со всеми PE.

   Вообще-то нужно создать полносвязную топологию соседства. Но мы же помним, что механизм Route-Reflector'ов позволяет обойти это требований, установив соседство только с одним RR (или несколькими в случае кластера RR)?
3. Под каждый VSI PE-маршрутизатор выделяет блок из пространства меток. И вот тут-то и начинается интересное. В BGP Update от локального PE удалённому передаётся следующая информация:
   * RD
   * RT
   * Порядковый номер узла в VPLS-домене.
   * Блок меток MPLS
     * VE ID
     * VE Block Offset
     * VE Block Size
     * Label Base

Напомню, что **VE** — VPLS Edge — граница сети VPLS — PE-маршрутизатор на котором запущен VPLS.

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

> Я искренне верю, что RFC является источником безусловной ясности, но порою в том же виде, в каком им является формула эквивалентности массы и энергии для Ньютона.

Когда на PE приходит L2VPN кадр со стороны MPLS сети, нужно точно знать, от какого он соседа — это нужно, чтобы изучить MAC-адрес, поэтому как и в случае с режимом Martini основная идея заключается в том, что PE каждому соседу в конкретном VSI должен сообщить уникальную метку, чтобы видеть, от кого пришёл кадр.

Вот на такой простой картинке посмотрим поподробнее:\
![](https://habrastorage.org/files/dc6/708/fea/dc6708feacf24a699704d26a1899c0a9.PNG)

Пусть R1 за главного.\
**0.** В Kompella mode R1 не передаёт метку в явном виде своим соседям R2 и R3.\
**1.** Вместо этого он им сообщает из какого диапазона нужно метки выбирать, чтобы идентифицировать данный VC.\
**2.** У каждого РЕ есть свой порядковый номер *n* в VPLS-домене. Зная **свой** номер и диапазон меток, соседи вычисляют исходящую сервисную метку: отсчитывают *n-ую* по счёту с начала. То есть R2 взял вторую (2), а R3 — третью (3).\
**3.** R2 и R3 сообщают свои номера R1, и он тоже вычисляет, какая входящая сервисная метка будет от R2, какая от R3, отсчитывая от начала диапазона 2 и 3.\
**4.** Аналогично свои собственные диапазоны определяют R2 и R3 и сообщают их друг другу и R1. И цикл вычислений повторяется.\
**5.** В конце концов все будут знать и исходящие метки для данного VPLS и входящие.

Теперь **вторая итерация**: поглубже копнём, какой матан лежит под этой простой идеей.

VE ID настраивается вручную — это идентификатор PE-маршрутизатора в домене VPLS (его порядковый номер). Должен быть уникален в пределах одного VSI.\
**LB** — Label Base — это начало диапазона, первая метка, которая может быть использована.\
**VBS** — VE Block Size — это длина блока меток — или проще, минимальное количество меток в этом VSI. Для Cisco по умолчанию это 10. Для Juniper — 8 (может быть уменьшен до 2 или увеличен).

Вот как будет выглядеть набор меток: {LB, LB+1, .., LB+VBS-1}.

В целом, схема простая:\
![](https://habrastorage.org/files/c5c/07f/996/c5c07f9969954734a47f9072db830e71.PNG)\
\&#xNAN;*VE ID 100-109 взяты от балды для примера*

На этой анимации показан процесс распределения меток на PE1: Если P&#x45;***X*** хочет отправлять трафик на PE1, он должен использовать соответствующую метку **X**.

Вот ещё пример для PE5:\
![](https://habrastorage.org/files/0c5/788/5fc/0c57885fc0e440acb71fdd33602ddfbf.PNG)

Метки выделяются по порядку — первая из блока — соседу с наименьшим VE-ID. Вторая — второму по величине итд.\
То есть такая ситуация **невозможна**:\
![](https://habrastorage.org/files/0b9/d86/b07/0b9d86b0793d49caa05625ba87c77256.PNG)

Однако если выделенного количества меток мало, то поможет параметр **VBO** — VE Block Offset — смещение блока. Он позволяет создать несколько блоков. И тем соседям, кому не хватило, метки распределяются по тому же принципу, но из нового блока, с новым LB.\
Необходимый VBO вычисляется по формуле: VBO = ЦЕЛОЕ(VE-ID/VBS)\*VBS.\
Хочется заметить, что VBO — это не про смещение меток, это про диапазон, в который попадает порядковый номер VE. Если попал в первый диапазон — берётся первый блок меток, если во второй — то второй итд.\
Таким образом в случае использования нескольких блоков, набор меток будет выглядеть так же, как и прежде {LB, LB+1,… LB+VBS-1}, но LB при этом зависит от VBO. То есть у нас связка\
![](https://habrastorage.org/files/11b/31f/0b5/11b31f0b5b4a4e309ffa72d0e775d4cc.png)

То есть имеем строгое соответствие: узлу с VE ID (VBO+n) соответствует метка (LB+n).

**Третья итерация** — на реальном примере.

Возьмём клиента с десятью сайтами.\
VBS у нас стандартный — 10.\
VE-ID соответствуют номеру маршрутизатора: PE1 — 101, PE2-102,… PE 10 — 110.\
Рассмотрим как будут взаимодействовать PE1 и PE5.

**1.** PE1 выбирает в качестве Label Base 1000 — то есть 1000-1009 — это блок меток, из которого его соседи смогут взять себе по одной.\
**2.** PE1 вычисляет VBO. VBO=ЦЕЛОЕ(101/10)\*10=100.\
**3.** PE1 передаёт собирает все данные в BGP Update всем своим соседям: LB: 1000, VBS:10, VBO:100, VE-ID:101. Ну и всякие RD, RT, которые нам сейчас не интересны.\
Сам PE1 пока никаких меток не считает — он ждёт Update от соседей.\
**4.** BGP Update от PE1 достигает PE5. Его VE-ID: 105. И сейчас ему нужно вычислить исходящую метку для данного VSI (чей RT указан так же в BGP Update)в сторону PE1.\
**5.** Первое, что делает PE5 — проверяет, а умещается ли он в блок, анонсированный PE1. Вот здесь и понадобится VBO. Должно выполниться неравенство VBO ≤ PE5 VE-ID ≤ VBO+VBS-1. И оно выполняется 100≤105≤109.\
Поясню. PE1 вычислил, что его ID в диапазоне 100-109 (со смещением 100 и длиной 10) — соответственно все узлы с VE ID из этого набора будут выбирать метку из первого блока.\
**6.** Итак PE5 в пределах анонсируемого диапазона, поэтому он может идти дальше и вычислить свою исходящую метку по формуле (PE1 LB + PE5 VE-ID — VBO) = (1000 + 105 — 100) = **1005**.\
Ещё раз вся эта арифметика, означает, что от LB нужно отсчитать столько меток, каким по счёту идёт VE-ID от VBO.\
Значит, PE5, чтобы отправить L2 кадр данного VSI на PE1 вставит в MPLS-заголовок VPN-метку 1005.\
PE1 пока не знает, про метку 1005 — ему предстоит её вычислить, как это сделал PE5. А для этого нужно узнать его VE ID.\
**7.** Теперь PE5 тоже должен отправить BGP Update всем соседям (технически, не надо дожидаться 7 шага — такую последовательность я взял для примера. PE5 отправляет свой BGP Update как только всё было настроено).

* а. Выбрал LB, например, 5000.
* б. Вычислил VBO = RND(105/10)\*10=100.
* в. Скомпоновал BGP Update. LB: 5000, VBS:10, VBO:100, VE-ID: 105.
* г. Отправил его всем PE.

**8.** Когда PE1 узнал VE-ID соседа (из BGP Update), он может посчитать входящую метку для данного соседа и VSI.\
И он делает то же самое:

* а. Проверяет неравенство по полученным VBO И VBS: VBO ≤ PE1 VE-ID ≤ VBO+VBS. 100≤101≤109. Отлично.
* б. Вычисляет **входящую** метку: (PE1 LB + PE5 VE-ID — VBO) = (1000 + 105 — 100) = **1005** — то же самое число, что посчитал и PE5 для исходящей метки. То есть когда PE1 получит кадр с меткой VPN 1005, он будет знать сразу и то, какому VPN он предназначен и от какого соседа пришёл, то есть как изучить его MAC, если необходимо.

**9.** Но это ещё не всё. PE1 должен теперь вычислить и исходящую метку к PE5. И все данные у него для этого имеются.\
(PE5 LB + PE1 VE-ID — VBO) = (5000 + 101 — 100) = **5001**. То есть PE1 при отправке кадров в этот VSI к PE5 вставит в них VPN-метку 5001.\
**10.** PE5 вычисляет входящую: (PE5 LB + PE1 VE-ID — VBO) = (5000 + 101 — 100) = **5001**.

Вот это я называю взаимовыручкой!

К сожалению, довольно очевидный и в корне своём логичный механизм я могу описать только таким сложным языком.\
Если вы ещё не эволюционировали до понимания механизма Label Block, вернитесь к [видео четырьмя экранами выше](https://github.com/eucariot/SDSM/tree/1bba87092a55c57ce614dabb1915aa8f1b76f650/12.-mpls-l2vpn/2.-vpls/3.-kompella-mode/12.-mpls-l2vpn.md#VPLS-LB).

Интересна судьба PE10, которая окажет своё влияние на жизни всех других PE.\
Дело в том, что он не укладывается в блок 100-109 со своим VE ID 110. Его VBO будет 110=ЦЕЛОЕ(110/10)\*10. А в качестве LB он выбрал 10000.\
Когда PE10 пришлёт результаты своих калькуляций PE5, неравенство **не** выполнится: 110 ≤ 105 ≤ 119.\
В этом случае запускается процесс выделения нового блока.\
**1.** PE5 выбирает новый LB 5030, VBS уже выбран PE10 — 10.\
**2.** Имея уже данные от PE10,

* А. PE5 вычисляет исходящую метку к PE10: (PE10 LB + PE5 VE-ID — PE5 VBO) = (10000 + 105 — 100) = **10005**. Обратите внимание, что отнимается **локальный VBO**.
* Б. Вычисляет входящую метку от PE10: (PE5 New LB + PE10 VE-ID — PE10 VBO) = (5030 + 110 — 110) = **5030**. Используется новый LB и VBO PE10.

**3.** PE5 высылает PE10 новый BGP Update, анонсируя уже два префикса: первый — старый, а второй — LB: 5030, VE ID: 105, VBS:10, VBO:110.\
**4.** VE-ID PE10 в этот раз входит в новый диапазон 110-119,

* А. поэтому он может вычислить исходящую метку: (PE5 LB + PE10 VE-ID — PE10 VBO) = (5030 + 110 — 110) = **5030**. То есть PE10 при отправке кадра этого VSI на PE5 должен вставить VPN-метку 5030.
* Б. Может он вычислить и входящую от PE5: (PE10 LB + PE5 VE-ID — PE5 VBO) = (10000 + 105- 100) = **10005**. Здесь он использует тот VBO, в который входит PE5, а не PE10.

**5.** Каждый PE должен будет выделить по второму блоку меток, чтобы общаться с PE10. Вычисления продолжаются.

Скрупулёзное объяснение механизма Label Block от виновников: [Juniper](https://kb.juniper.net/library/CUSTOMERSERVICE/technotes/Understanding_VPLS_Label_Blocks_Operation.pdf).

И в этот момент должно стать жутко.\
Во-первых мы только что потеряли 10 меток на КАЖДОМ PE (9 не использовано из второго блока и одна метка из первого — которая для самого этого PE).\
Во-вторых, от того, как мы назначим VE-ID, зависит, насколько рационально будут использованы метки.\
В-третьих, мы должны своими собственными руками настроить VE-ID и VE-range! Вот этими вот руками, которыми мы MPLS поднимали в пару команд!

Должны быть очень веские доводы, почему протокол реализован именно так, а не по аналогии с LDP или MBGP для L3VPN.

Знаете, что по этому поводу, говорит [RFC 4761](https://tools.ietf.org/html/rfc4761)?

> Using a distinct BGP Update message to send a demultiplexor to each\
> remote PE would require the originating PE to send N such messages\
> for N remote PEs. The solution described in this document allows a\
> PE to send a single (common) Update message that contains\
> demultiplexors for all the remote PEs, instead of N individual\
> messages. Doing this reduces the control plane load both on the\
> originating PE as well as on the BGP Route Reflectors that may be\
> involved in distributing this Update to other PEs.

*Не очень понятно, какие там нагрузки на Control Plane.*

Как это водится в СДСМ, дальше вы читаете эксклюзив. Причём на этот раз, вероятно, не только рунетовского уровня, но и вообще во всём Интернете я не нашёл адекватного пояснения, зачем эта система блоков была изобретена. *Не смейтесь сильно, но я даже писал Компелле, когда ни один из окружающих меня CCIE не ответил на этот вопрос*.

Всё это из-за столь желанной функции Auto-discovery (про которую уже было выше) и специфики L2, а именно изучения MAC-адресов. И всё будет понятнее в сравнении с L3VPN, где про назначения блока меток никто даже не думал.

Итак, как работает Auto-Discovery в L3VPN? Некоторый PE страждет рассказать всему миру о двух вещах — во-первых, о том, какие префиксы он знает, во-вторых о том, кому они предназначены. И он хочет рассказать об этом всем сразу без разбора — все, кто являются его MBGP соседями получат его Update, а по RT поймут, интересны ли им эти анонсы. На нет — и суда нет — отбросят. А если интересны, то в свою таблицу маршрутизации VPN занесут полученный префикс и его VPN-метку.

Всё то же самое верно и для L2VPN. **За исключением одного: изучения MAC-адресов**. BGP в L3VPN сообщает всем одну и ту же метку — ему совершенно без разницы, откуда потом придёт пакет с данными, главная его забота — передать его в правильный клиентский интерфейс.\
Но не таков VPLS. Чтобы в будущем отправлять данные конкретному соседу, нужно сначала изучить MAC-адреса клиента, подключенного к этому соседу. И сделать это можно только, если от разных соседей приходят кадры с разными метками.\
И здесь-то и кроется дьявол. **В BGP Auto-Discovery происходит в тот же момент, что и анонс префикса**.\
И, во-первых, совершенно не в духе BGP будет, если сначала отсылать пустой Update с целью поиска всех участников VPLS-домена, а потом отдельно то же самое, но с конкретными метками каждому из них.\
И даже, если вы приемлете «во-первых» (Фуфуфу), появляется, «во-вторых». Во-вторых, анонс конкретных меток найденным соседям. *Хорошо*, когда нет RR, и один PE может отправить другому Update адресно. Тогда каждый PE получит только своё сообщение и только свою метку. Но реальность такова, что RR стали её (реальности) частью и, имея соседство только с RR, PE шлёт Update ему, а тот рассылает всем своим клиентам. А если PE шлёт несколько Update'ов, то все они разлетятся по всем. Получается, что каждый его сосед получит не только свою метку, но и все остальные, которые ему даром не сдались.\
\&#xNAN;*Просто представьте себе дамп в котором вы видите сотню Update'ов для левых устройств.*

И вот тут механизм автоматического вычисления меток выходит на первый план, как весьма элегантное решение этой проблемы.\
Здесь стоит отдать должное гибкости мысли Кирити Компеллы.

И знаете, пока эта концепция блока меток не сформировалась в непротиворечивый набор синапсов в моём мозге, я с пренебрежением относился к ней. Она казалась мне топорной и устаревшей. Примерно, как [DVMRP](http://lookmeup.linkmeup.ru/#term371). Но теперь я проникся идеей и даже несколько удивлён тому, что внятного объяснения нигде нет.

Замечу также, что ситуацию с потерянными метками несколько пересмотрели с выпуском [RFC 6624](http://mail.networksorcery.com/enp/rfc/rfc6624.txt) (в котором, кстати, Компелла тоже принял непосредственное участие):

> Label blocks and label values are managed by the PEs. As sites get\
> added and removed, labels are allocated and released. The easiest\
> way to manage these is to use fixed-size label blocks rather than\
> variable-size blocks, although the signaling described here supports\
> either. If an implementation uses fixed-size blocks, then allocating\
> a label for a new site may requiring allocating a new block;\
> similarly, freeing a label may require freeing a block.\
> If the implementation requires fixed-size blocks, there is probably a\
> default block size, but the implementation SHOULD allow the\
> administrator to choose a size. Larger label block sizes mean more\
> potential «wasted» labels but less signaling overhead, a trade-off\
> that the administrator might want to control.

И более того, режим [LDP-Signalling + BGP Auto-Discovery](https://github.com/eucariot/SDSM/tree/1bba87092a55c57ce614dabb1915aa8f1b76f650/12.-mpls-l2vpn/2.-vpls/3.-kompella-mode/12.-mpls-l2vpn.md#LDP+BGP) позволяет совместить достоинства обоих методов. Хотя и появляется вот этот самый двухшаговый механизм — сначала изучаем соседей, потом рассылаем метки.
