Skip to content

Instantly share code, notes, and snippets.

@mvandermeulen
Forked from vorlon001/readme.md
Created September 23, 2026 11:43
Show Gist options
  • Select an option

  • Save mvandermeulen/a0e8f37ac03835761e893093ab09665f to your computer and use it in GitHub Desktop.

Select an option

Save mvandermeulen/a0e8f37ac03835761e893093ab09665f to your computer and use it in GitHub Desktop.
FRR EVPN Multi-Homing A или диалоги с Гугл ИИ

Для реализации FRR EVPN Multi-Homing (MH) в режиме All-Active (AA) ключевым элементом является настройка ESI (Ethernet Segment Identifier) на интерфейсах, смотрящих в сторону клиента (CE).
Ниже приведен базовый пример конфигурации для одного из двух VTEP (коммутаторов доступа), работающих в паре.
Конфигурация интерфейса (Bond/LACP)
Интерфейс должен быть объединен в Bond, чтобы ядро Linux и FRR понимали логику Multi-Homing.

# В системе (Linux)
ip link add bond0 type bond mode balance-lacp
ip link set eth1 master bond0
ip link set eth2 master bond0

Конфигурация FRR (frr.conf)
В FRR MH настраивается через демон zebra (для связи с ядром) и bgp (для анонса маршрутов Type-1 и Type-4).

!
interface bond0
  ! Установка идентификатора сегмента (ESI)
  ! Должен быть одинаковым на обоих VTEP для одного клиента
  evpn mh es-id 00:11:22:33:44:55:66:77:88:99
  ! Режим All-Active (интерфейс активен на обоих узлах)
  evpn mh es-sys-mac 00:00:00:00:00:01
!
router bgp 65001
  neighbor 10.0.0.1 remote-as 65001
  !
  address-family l2vpn evpn
    neighbor 10.0.0.1 activate
    ! Активация передачи MH маршрутов
    advertise-all-vni
    advertise-svi-ip
  exit-address-family
!

Что важно проверить:

   1. ES-ID: Должен быть уникальным для каждого сегмента (клиента), но идентичным на паре VTEP, к которым этот клиент подключен.
   2. ES-SYS-MAC: Общий LACP System ID для обоих VTEP, чтобы клиент видел их как один логический коммутатор.
   3. Маршруты: В таблице EVPN должны появиться маршруты Type-1 (Ethernet Auto-Discovery) и Type-4 (Ethernet Segment), которые отвечают за обнаружение соседей и исключение петель (Split Horizon).

Вам помочь с командами show для проверки статуса синхронизации сегментов между VTEP?

Для проверки статуса EVPN Multi-Homing (MH) в FRR используйте следующие команды в консоли vtysh. Они помогут убедиться, что сегменты согласованы и трафик будет распределяться корректно.
1. Проверка локальных сегментов (Ethernet Segments)
Эта команда показывает состояние настроенных ESI и их статус (активен ли интерфейс и определен ли DF — Designated Forwarder).

show evpn es


* На что смотреть: Статус должен быть Up, а в поле DF должен быть выбран один из узлов для каждого VNI (обычно для BUM-трафика).

2. Детальная информация по конкретному сегменту
Если нужно проверить конкретный интерфейс (например, bond0):

show evpn es bond0


* На что смотреть: Здесь отображается ES-SYS-MAC и список удаленных VTEP, которые также анонсировали этот ESI. Если удаленных VTEP в списке нет, MH не заработает.

3. Проверка удаленных маршрутов Type-4 (ES Route)
Маршруты 4-го типа используются для обнаружения соседей по сегменту.

show bgp l2vpn evpn route type es


* На что смотреть: Вы должны видеть IP-адреса обоих VTEP (своего и соседа) для общего ESI.

4. Проверка фильтрации (Split Horizon)
В режиме All-Active важно, чтобы трафик, пришедший от одного VTEP, не улетел обратно клиенту через второй VTEP. За это отвечает Local Bias или фильтрация по меткам.

show evpn mh local-bias

5. Проверка состояния интерфейса в Zebra
Так как именно Zebra управляет состоянием интерфейсов в ядре:

show zebra interface bond0


* На что смотреть: Наличие флагов protodown (могут выставляться, если MH не согласован) и правильность установки параметров evpn mh.

Нужно ли подготовить сценарий для Containerlab, чтобы вы могли протестировать это в виртуальной среде?

Для тестирования EVPN MH All-Active лучше всего использовать Containerlab. Это позволит запустить топологию с двумя Leaf (VTEP) и одним клиентом (CE), соединенным по LACP.
1. Файл топологии (topology.yml)
Этот файл описывает связи. Мы подключим клиента CE1 к двум разным Leaf.

name: frr-evpn-mh
topology:
  nodes:
    spine:  { kind: linux, image: frrouting/frr:latest }
    leaf1:  { kind: linux, image: frrouting/frr:latest }
    leaf2:  { kind: linux, image: frrouting/frr:latest }
    ce1:    { kind: linux, image: alpine:latest } # Клиент

  links:
    - endpoints: ["leaf1:eth1", "spine:eth1"]
    - endpoints: ["leaf2:eth1", "spine:eth2"]
    - endpoints: ["ce1:eth1", "leaf1:eth2"]
    - endpoints: ["ce1:eth2", "leaf2:eth2"]

2. Конфигурация Leaf (ключевые моменты для FRR)
На обоих Leaf (leaf1 и leaf2) создаем bond-интерфейс в Linux перед запуском FRR или через скрипт. В самом FRR (frr.conf) прописываем:

# Настройка на Leaf1 и Leaf2
interface eth2
  # Включаем поддержку MH на физическом порту
  evpn mh es-id 00:11:22:33:44:55:66:77:88:99
  evpn mh es-sys-mac 00:00:00:00:00:01
  evpn mh df-preference 100

router bgp 65000
  neighbor SPINES peer-group
  neighbor SPINES remote-as 65000
  neighbor 192.168.0.1 peer-group SPINES # IP Spine
  
  address-family l2vpn evpn
    neighbor SPINES activate
    advertise-all-vni
  exit-address-family

3. Настройка клиента (CE1)
Чтобы проверить All-Active, на стороне клиента нужно собрать обычный LACP (bond):

# Внутри контейнера ce1
ip link add bond0 type bond mode balance-lacp
ip link set eth1 master bond0
ip link set eth2 master bond0
ip addr add 10.0.0.10/24 dev bond0
ip link set bond0 up

Как запустить и проверить:

   1. Развернуть: sudo containerlab deploy -t topology.yml
   2. Проверить согласование ES: На Leaf1 выполните vtysh -c "show evpn es". Вы должны увидеть, что leaf2 обнаружен как удаленный участник сегмента.
   3. Проверить трафик: Запустите ping с CE1 на какой-нибудь адрес за Spine. При выключении одного из линков (например, ip link set eth2 down на Leaf1), трафик должен продолжать идти через второй Leaf мгновенно.

Вам помочь с полным текстом frr.conf для Spine и Leaf, чтобы просто скопировать и запустить?

Ниже приведены полные конфигурационные файлы для минимальной рабочей топологии.
1. Spine (BGP Route Reflector)
Его задача — просто пересылать EVPN маршруты между Leaf-узлами.

# frr.conf для Spine
hostname spine
!
router bgp 65000
 bgp router-id 1.1.1.1
 no bgp default ipv4-unicast
 neighbor LEAFS peer-group
 neighbor LEAFS remote-as 65000
 neighbor 192.168.1.1 peer-group LEAFS
 neighbor 192.168.1.2 peer-group LEAFS
 !
 address-family l2vpn evpn
  neighbor LEAFS activate
  neighbor LEAFS route-reflector-client
 exit-address-family

2. Leaf-1 (VTEP 1)
Здесь настраивается сам Multi-Homing.

# frr.conf для Leaf-1
hostname leaf1
!
interface eth1
 description to-spine
 ip address 192.168.1.1/24
!
interface eth2
 description to-ce1
 evpn mh es-id 00:11:22:33:44:55:66:77:88:99
 evpn mh es-sys-mac 00:00:00:00:00:01
!
router bgp 65000
 bgp router-id 1.1.1.2
 no bgp default ipv4-unicast
 neighbor 192.168.1.1 remote-as 65000
 !
 address-family l2vpn evpn
  neighbor 192.168.1.1 activate
  advertise-all-vni
 exit-address-family
!# Настройка VNI для моста (L2 Stretch)
vnc defaults
 exit-vnc

3. Leaf-2 (VTEP 2)
Конфигурация почти идентична Leaf-1, но с другим IP и Router-ID. ESI и ES-SYS-MAC должны совпадать.

# frr.conf для Leaf-2
hostname leaf2
!
interface eth1
 description to-spine
 ip address 192.168.1.2/24
!
interface eth2
 description to-ce1
 evpn mh es-id 00:11:22:33:44:55:66:77:88:99
 evpn mh es-sys-mac 00:00:00:00:00:01
!
router bgp 65000
 bgp router-id 1.1.1.3
 no bgp default ipv4-unicast
 neighbor 192.168.1.1 remote-as 65000
 !
 address-family l2vpn evpn
  neighbor 192.168.1.1 activate
  advertise-all-vni
 exit-address-family

Важное дополнение по Linux Bridge
Чтобы FRR корректно обрабатывал EVPN на Leaf, в самой ОС (внутри контейнера) нужно создать бридж и привязать к нему интерфейс:

# Выполнить на Leaf1 и Leaf2
ip link add br0 type bridge
ip link set br0 type bridge vlan_filtering 1
ip link set eth2 master br0
ip link set br0 up
ip link set eth2 up

Как проверить готовность:
Зайдите на любой Leaf и введите:
vtysh -c "show evpn es detail"
Если всё настроено верно, в поле "Remote VTEPs" вы увидите IP-адрес соседнего Leaf. Это означает, что процедура DF Election (выбор основного узла для BUM-трафика) прошла успешно.
Вам подготовить bash-скрипт для автоматизации создания бриджей и интерфейсов внутри контейнеров?

Этот скрипт автоматизирует настройку сетевых интерфейсов и бриджей внутри контейнеров после их запуска. Сохраните его как setup.sh и запустите (chmod +x setup.sh && ./setup.sh).

#!/bin/bash
# Настройка Leaf1
docker exec -it clab-frr-evpn-mh-leaf1 bash -c "
  ip link add br0 type bridge
  ip link set br0 type bridge vlan_filtering 1
  ip link set eth2 up
  ip link set eth2 master br0
  ip link set br0 up
"
# Настройка Leaf2
docker exec -it clab-frr-evpn-mh-leaf2 bash -c "
  ip link add br0 type bridge
  ip link set br0 type bridge vlan_filtering 1
  ip link set eth2 up
  ip link set eth2 master br0
  ip link set br0 up
"
# Настройка клиента CE1 (создание LACP Bond)
docker exec -it clab-frr-evpn-mh-ce1 bash -c "
  ip link add bond0 type bond mode balance-lacp
  ip link set eth1 down
  ip link set eth2 down
  ip link set eth1 master bond0
  ip link set eth2 master bond0
  ip addr add 10.0.0.10/24 dev bond0
  ip link set bond0 up
"

echo "Конфигурация завершена. Проверка статуса ESI на Leaf1:"
docker exec -it clab-frr-evpn-mh-leaf1 vtysh -c "show evpn es"

Что делает этот скрипт:

   1. На Leaf: Создает br0 с поддержкой VLAN. Это необходимо, так как FRR (Zebra) привязывает параметры EVPN MH к портам, находящимся в бридже.
   2. На CE1: Создает агрегированный канал LACP (802.3ad). Именно благодаря ему клиент воспринимает два разных Leaf как одно устройство.
   3. Проверка: В конце выводит таблицу Ethernet Segments.

Как проверить работу:

   1. DF Election: В выводе show evpn es убедитесь, что один из Leaf помечен как Primary или имеет флаг DF для VNI.
   2. Отказоустойчивость: Запустите ping 10.0.0.1 (если есть шлюз) или пингуйте другой конец сегмента. Выключите интерфейс eth2 на leaf1 — связь не должна прерваться.

Нужно ли добавить в схему VLAN-интерфейсы (SVI) для тестирования маршрутизации между разными подсетями через этот же MH-сегмент?

Для настройки SVI (Switch Virtual Interface) в среде EVPN MH используется концепция Anycast Gateway. Это позволяет обоим Leaf иметь один и тот же IP и MAC-адрес для клиентского шлюза, обеспечивая бесшовную мобильность и отказоустойчивость.
1. Дополнение в bash-скрипт (настройка SVI в Linux)
Добавьте эти команды для создания VLAN-интерфейса поверх бриджа на обоих Leaf:

# Выполнить на Leaf1 и Leaf2
docker exec -it clab-frr-evpn-mh-leaf1 bash -c "
  # Создаем VLAN 10 на бридже
  ip link add link br0 name br0.10 type vlan id 10
  # Назначаем Anycast IP (одинаковый на обоих Leaf)
  ip addr add 10.0.10.1/24 dev br0.10
  ip link set br0.10 up
"

2. Обновление конфигурации FRR (frr.conf)
Чтобы FRR начал анонсировать этот шлюз и мак-адреса через EVPN, добавьте следующие секции:

! Настройка на Leaf1 и Leaf2
interface br0.10
  ! Общий виртуальный MAC для Anycast Gateway
  ip address 10.0.10.1/24
  mac-address 00:00:5e:00:01:01

router bgp 65000
  address-family l2vpn evpn
    ! Анонсируем IP шлюза (маршруты Type-2)
    advertise-svi-ip
  exit-address-family

3. Настройка клиента (CE1)
Теперь на стороне клиента нужно поместить bond-интерфейс в тот же VLAN и задать адрес из новой подсети:

docker exec -it clab-frr-evpn-mh-ce1 bash -c "
  ip link add link bond0 name bond0.10 type vlan id 10
  ip addr add 10.0.10.100/24 dev bond0.10
  ip link set bond0.10 up
  # Проверка доступности шлюза
  ping -c 4 10.0.10.1
"

Как проверить Anycast GW и MH:

   1. Просмотр MAC/IP: vtysh -c "show evpn mac vni 10" — вы должны увидеть MAC клиента, привязанный к вашему ESI.
   2. Проверка ARP: vtysh -c "show evpn arp-cache vni 10" — здесь должен появиться IP клиента 10.0.10.100.
   3. Отказоустойчивость: Если вы "уроните" один Leaf, клиент продолжит пинговать 10.0.10.1 через второй Leaf, так как IP и MAC шлюза там идентичны.

Хотите добавить еще один Leaf или имитировать выход из строя линка между Spine и одним из Leaf, чтобы проверить перестроение трафика?

Для этого сценария мы добавим Leaf3 (чтобы увидеть, как EVPN работает через несколько прыжков) и протестируем сценарий Core Isolation (когда Leaf теряет связь со Spine).
1. Обновление топологии (topology.yml)
Добавьте Leaf3 в список узлов и соедините его со Spine.

    leaf3:  { kind: linux, image: frrouting/frr:latest }
    # ... в секции links:
    - endpoints: ["leaf3:eth1", "spine:eth3"]

2. Тест 1: Имитация аварии на Uplink (Core Isolation)
В EVPN MH, если Leaf теряет связь со Spine (Core), он должен отключить свои клиентские порты (ESI), чтобы трафик не уходил в «черную дыру».
Как проверить:

   1. Запустите постоянный пинг с CE1 до CE2 (подключенного к Leaf3).
   2. «Уроните» линк между Leaf1 и Spine:
   
   docker exec -it clab-frr-evpn-mh-leaf1 ip link set eth1 down
   
   3. Результат: FRR в Leaf1 увидит потерю BGP-соседства и через механизм protodown должен выключить bond0. Клиент (CE1) мгновенно переключит весь трафик на Leaf2.

3. Тест 2: Проверка удаленной видимости (Leaf3)
Зайдите на новый Leaf3 и проверьте, как он видит наш Multi-Homing сегмент.

docker exec -it clab-frr-evpn-mh-leaf3 vtysh -c "show evpn mac vni 10"


* Ожидаемый результат: MAC-адрес клиента (CE1) будет иметь в качестве Next-Hop оба IP-адреса (Leaf1 и Leaf2). Это означает, что Leaf3 будет выполнять ECMP (балансировку) при отправке трафика в сторону клиента.

4. Полезные команды отладки при сбоях
Если трафик не идет, проверьте эти статусы на Leaf:

* Синхронизация MH: show evpn es detail (убедитесь, что удаленный VTEP виден).
* DF Election: show evpn es vni (проверьте, кто назначен Designated Forwarder для конкретного VNI).
* BGP трасса: show bgp l2vpn evpn route type 1 (маршруты Auto-Discovery, критичны для работы MH).

Хотите, чтобы я подготовил финальный конфиг для Leaf3 и обновленный Spine, чтобы они автоматически подхватили нового соседа?

Для завершения топологии необходимо обновить Spine (чтобы он принял третьего соседа) и настроить Leaf3 как классический VTEP.
1. Обновленный Spine (RR)
Добавляем Leaf3 в группу соседей. Если вы использовали peer-group, достаточно просто прописать IP нового Leaf.

# frr.conf для Spine
hostname spine
!
router bgp 65000
 bgp router-id 1.1.1.1
 no bgp default ipv4-unicast
 neighbor LEAFS peer-group
 neighbor LEAFS remote-as 65000
 neighbor 192.168.1.1 peer-group LEAFS  # Leaf1
 neighbor 192.168.1.2 peer-group LEAFS  # Leaf2
 neighbor 192.168.1.3 peer-group LEAFS  # Leaf3 (Новый)
 !
 address-family l2vpn evpn
  neighbor LEAFS activate
  neighbor LEAFS route-reflector-client
 exit-address-family

2. Конфигурация Leaf3 (Single-Homed)
Leaf3 будет обычным узлом. Ему не нужен evpn mh, если к нему подключен клиент только одним линком, но он должен понимать Anycast Gateway.

# frr.conf для Leaf3
hostname leaf3
!
interface eth1
 description to-spine
 ip address 192.168.1.3/24
!
interface br0.10
 ip address 10.0.10.1/24
 mac-address 00:00:5e:00:01:01  # Тот же Anycast MAC
!
router bgp 65000
 bgp router-id 1.1.1.4
 no bgp default ipv4-unicast
 neighbor 192.168.1.1 remote-as 65000
 !
 address-family l2vpn evpn
  neighbor 192.168.1.1 activate
  advertise-all-vni
  advertise-svi-ip
 exit-address-family

3. Автоматизация настройки Leaf3 (Bash)
Не забудьте подготовить интерфейсы внутри контейнера Leaf3:

docker exec -it clab-frr-evpn-mh-leaf3 bash -c "
  ip link add br0 type bridge
  ip link set br0 type bridge vlan_filtering 1
  ip link add link br0 name br0.10 type vlan id 10
  ip addr add 10.0.10.1/24 dev br0.10
  ip link set br0 up
  ip link set eth2 up
  ip link set eth2 master br0
  ip link set br0.10 up
"

Итоговая проверка всей сети:

   1. Балансировка (ECMP): Зайдите на Leaf3 и введите vtysh -c "show bgp l2vpn evpn". Для MAC-адреса клиента за MH-сегментом вы должны увидеть два Next-Hop (Leaf1 и Leaf2).
   2. Пинг: Запустите ping 10.0.10.100 с клиента, подключенного к Leaf3.
   3. Отказоустойчивость: Выключите eth1 на Leaf1. Трафик от Leaf3 к клиенту должен автоматически перестроиться на Leaf2 через 1-2 секунды (BGP Convergence).

Нужно ли пояснить, как работает DF Election (выбор главного узла для рассылки Multicast) в этой тройной связке?

Вот схема вашей лабораторной среды в формате ASCII, которая наглядно показывает связи между устройствами, уровни сети и логику Multi-Homing:

          +-----------------------+

          |         SPINE         |
          |    (Route Reflector)  |
          |      ID: 1.1.1.1      |
          +----------+------------+

                     |
       +-------------+-------------+
       |             |             |
  (192.168.1.1) (192.168.1.2) (192.168.1.3)
 +-----------+ +-----------+ +-----------+

 |   LEAF1   | |   LEAF2   | |   LEAF3   |
 | (VTEP 1)  | | (VTEP 2)  | | (VTEP 3)  |
 +-----------+ +-----------+ +-----------+
       \             /             |
        \           /              |
     [ ESI: 00:11... ]             |
     [ All-Active MH ]             |
          \       /                |
           \     /                 |
        +-----------+        +-----------+

        |    CE1    |        |    CE2    |
        | (Client)  |        | (Client)  |
        | IP: .100  |        | IP: .200  |
        +-----------+        +-----------+
          (LACP Bond)         (Single Link)

       <----- VLAN 10 (10.0.10.0/24) ----->
       <--- Anycast GW: 10.0.10.1/24 ---->

Основные элементы схемы:

   1. IP Fabric (Underlay): Связи между Spine и Leaf. Здесь работает обычный OSPF/IS-IS или iBGP для обеспечения связности между Loopback-адресами VTEP.
   2. EVPN Multi-Homing Segment (ESI): Красным выделена зона, где Leaf1 и Leaf2 работают как пара. Они анонсируют один и тот же ESI в сторону Spine.
   3. All-Active LACP: Клиент CE1 думает, что он подключен к одному коммутатору (через Bond), хотя физически провода идут к разным Leaf.
   4. Anycast Gateway: На всех трех Leaf (1, 2 и 3) настроен один и тот же IP 10.0.10.1 на интерфейсе br0.10. Это позволяет клиенту перемещаться или переключать трафик без смены шлюза.
   5. ECMP на Leaf3: Когда CE2 отправляет пакет для CE1, Leaf3 видит два пути (через Leaf1 и Leaf2) и балансирует трафик между ними.

Хотите добавить на схему обозначения конкретных интерфейсов (eth1, eth2) или меток VNI для большей точности?

Вот детализированная схема с указанием портов (ethX), VNI и IP-адресов. Она полностью соответствует конфигурации и скриптам, которые мы подготовили.

                     +-----------------------+

                     |         SPINE         |
                     |    (ASN 65000)        |
                     |    ID: 1.1.1.1        |
                     +--+--------+--------+--+
           eth1 (.254)  |  eth2  |  eth3  |  (.254)
                 _______|        |        |_______
                /                |                \
    (192.168.1.1)           (192.168.1.2)           (192.168.1.3)
   +------------+          +------------+          +------------+

   |   LEAF1    |          |   LEAF2    |          |   LEAF3    |
   | (VTEP 1)   |          | (VTEP 2)   |          | (VTEP 3)   |
   +-----+------+          +-----+------+          +-----+------+

         | eth2                  | eth2                  | eth2
         |                       |                       |
         +-----------+-----------+                       |

                     |                                   |
           [ ESI: 00:11...22 ]                 [ Single Port ]
           [ VNI 10 (L2)     ]                 [ VNI 10 (L2) ]
           [ Anycast GW .1   ]                 [ Anycast GW .1]

                     |                                   |
               +-----+-----+                       +-----+-----+

               |    CE1    |                       |    CE2    |
               | (bond0)   |                       | (eth1)    |
               | IP: .100  |                       | IP: .200  |
               +-----------+                       +-----------+
              (VLAN 10 Tag)                       (VLAN 10 Tag)

   -----------------------------------------------------------------
   VNI 10:   Broadcast Domain (10.0.10.0/24)
   Anycast:  MAC 00:00:5e:00:01:01 / IP 10.0.10.1 (на всех Leaf)
   -----------------------------------------------------------------

Краткая легенда по интерфейсам:

   1. Upstream (Fabric):
   * Leaf1 eth1: Подключение к Spine. IP 192.168.1.1.
      * Leaf2 eth1: Подключение к Spine. IP 192.168.1.2.
      * Leaf3 eth1: Подключение к Spine. IP 192.168.1.3.
   2. Downstream (Client):
   * Leaf1 eth2 & Leaf2 eth2: Физические порты, образующие Ethernet Segment (ESI). На них настроен evpn mh.
      * CE1 bond0: Агрегированный интерфейс клиента. Пакеты балансируются между Leaf1 и Leaf2.
   3. Логические сущности (VNI):
   * VNI 10: Связывает все три Leaf в одну L2-сеть.
      * Anycast Gateway: Виртуальный шлюз 10.0.10.1 активен на всех трёх Leaf одновременно.
   
Все ли порты и адреса теперь понятны, или нужно добавить еще какие-то детали (например, Loopback-адреса VTEP)?

Добавим финальные штрихи: Loopback-интерфейсы, которые в реальных сетях служат терминирующими точками для VXLAN-туннелей (VTEP IP), и уточним распределение подсетей.

                     +---------------------------+

                     |          SPINE            |
                     |    Loopback: 10.255.0.1   |
                     |       (ASN 65000)         |
                     +--+----------+----------+--+
           eth1 (.254)  |    eth2  |    eth3  |  (.254)
                 _______|          |          |_______
                /                  |                  \
    (192.168.1.1)             (192.168.1.2)             (192.168.1.3)
   +------------+            +------------+            +------------+

   |   LEAF1    |            |   LEAF2    |            |   LEAF3    |
   | VTEP: .11  |            | VTEP: .12  |            | VTEP: .13  |
   +-----+------+            +-----+------+            +-----+------+

         | eth2 (ESI)              | eth2 (ESI)              | eth2
         |                         |                         |
         +------------+------------+                         |

                      |                                      |
            [ ESI: 00:11...22 ]                    [ Single Port ]
            [ VNI 10 (L2)     ]                    [ VNI 10 (L2) ]
            [ Anycast GW .1   ]                    [ Anycast GW .1]

                      |                                      |
                +-----+-----+                          +-----+-----+

                |    CE1    |                          |    CE2    |
                | (bond0)   |                          | (eth1)    |
                | IP: .100  |                          | IP: .200  |
                +-----------+                          +-----------+

Таблица адресации для стенда:

| Устройство | Интерфейс | IP-адрес | Назначение |
|---|---|---|---|
| Spine | lo | 10.255.0.1/32 | BGP Router-ID / RR |
| Leaf1 | lo | 10.255.0.11/32 | VTEP IP (Источник VXLAN) |
| Leaf1 | eth1 | 192.168.1.1/24 | Underlay (к Spine) |
| Leaf2 | lo | 10.255.0.12/32 | VTEP IP (Источник VXLAN) |
| Leaf2 | eth1 | 192.168.1.2/24 | Underlay (к Spine) |
| Leaf3 | lo | 10.255.0.13/32 | VTEP IP (Источник VXLAN) |
| Anycast | br0.10 | 10.0.10.1/24 | Шлюз для всех CE (MAC: 00:00:5e:00:01:01) |

Что это дает в работе:

   1. VTEP IP: Все VXLAN пакеты будут иметь Source IP одного из Loopback адресов Leaf.
   2. Redundancy: Если Leaf1 упадет, Leaf3 узнает об этом через BGP и перестанет балансировать трафик на 10.255.0.11, направив всё на 10.255.0.12.
   3. LACP: Клиент CE1 использует хеширование (обычно по L3/L4), чтобы распределять исходящие пакеты между двумя линками к разным Leaf.

Нужно ли подготовить финальный docker-compose или YAML-файл для запуска всей этой структуры одной командой?

Для запуска всего стенда одной командой используйте этот финальный файл конфигурации для Containerlab. Он объединяет все узлы, связи и настройки в единую структуру.
1. Файл топологии evpn-mh.clab.yml
Создайте файл с этим содержимым. Я добавил автоматическую проброску конфигов через binds, чтобы вам не пришлось настраивать FRR вручную внутри контейнеров.

name: frr-evpn-mh-lab
topology:
  nodes:
    spine:
      kind: linux
      image: frrouting/frr:latest
      binds:
        - configs/spine.conf:/etc/frr/frr.conf
        - configs/daemons:/etc/frr/daemons
    leaf1:
      kind: linux
      image: frrouting/frr:latest
      binds:
        - configs/leaf1.conf:/etc/frr/frr.conf
        - configs/daemons:/etc/frr/daemons
    leaf2:
      kind: linux
      image: frrouting/frr:latest
      binds:
        - configs/leaf2.conf:/etc/frr/frr.conf
        - configs/daemons:/etc/frr/daemons
    leaf3:
      kind: linux
      image: frrouting/frr:latest
      binds:
        - configs/leaf3.conf:/etc/frr/frr.conf
        - configs/daemons:/etc/frr/daemons
    ce1:
      kind: linux
      image: alpine:latest
      exec:
        - apk add pkgconf build-base # для утилит сети если нужно
    ce2:
      kind: linux
      image: alpine:latest

  links:
    - endpoints: ["leaf1:eth1", "spine:eth1"]
    - endpoints: ["leaf2:eth1", "spine:eth2"]
    - endpoints: ["leaf3:eth1", "spine:eth3"]
    - endpoints: ["ce1:eth1", "leaf1:eth2"]
    - endpoints: ["ce1:eth2", "leaf2:eth2"]
    - endpoints: ["ce2:eth1", "leaf3:eth2"]

2. Подготовка папки с конфигами
Перед запуском создайте директорию configs и положите туда файл daemons (включите в нем zebra=yes и bgpd=yes), а также файлы spine.conf, leaf1.conf и т.д., используя примеры из наших предыдущих шагов.
3. Скрипт быстрого старта deploy.sh
Этот скрипт поднимет лабу и выполнит системные настройки Linux (Bridges/Bonds), которые FRR не делает сам:

#!/bin/bash
# 1. Запуск контейнеров
sudo containerlab deploy -t evpn-mh.clab.yml
# 2. Настройка сетевого стека на Leaf (Bridge + VLAN)for i in {1..3}; do
  docker exec -it clab-frr-evpn-mh-lab-leaf$i bash -c "
    ip link add br0 type bridge
    ip link set br0 type bridge vlan_filtering 1
    ip link set eth2 up
    ip link set eth2 master br0
    ip link add link br0 name br0.10 type vlan id 10
    ip addr add 10.0.10.1/24 dev br0.10
    ip link set br0 up
    ip link set br0.10 up
  "done
# 3. Настройка клиента CE1 (LACP Bond)
docker exec -it clab-frr-evpn-mh-lab-ce1 bash -c "
  ip link add bond0 type bond mode balance-lacp
  ip link set eth1 master bond0
  ip link set eth2 master bond0
  ip link add link bond0 name bond0.10 type vlan id 10
  ip addr add 10.0.10.100/24 dev bond0.10
  ip link set bond0 up
  ip link set bond0.10 up
"
# 4. Настройка клиента CE2 (Single Port)
docker exec -it clab-frr-evpn-mh-lab-ce2 bash -c "
  ip link add link eth1 name eth1.10 type vlan id 10
  ip addr add 10.0.10.200/24 dev eth1.10
  ip link set eth1 up
  ip link set eth1.10 up
"

echo "Лабораторная работа готова! Проверьте пинг: docker exec clab-frr-evpn-mh-lab-ce2 ping 10.0.10.100"

Как запустить:

   1. Убедитесь, что установлен Containerlab.
   2. Положите все файлы в одну папку.
   3. Выполните chmod +x deploy.sh && ./deploy.sh.

Хотите, чтобы я прислал содержимое файла daemons или проверочные команды для мониторинга LACP-статуса на стороне клиента?

Вот содержимое файла daemons и команды для проверки состояния LACP и ESI.
1. Файл configs/daemons
Этот файл указывает FRR, какие процессы нужно запустить. Для EVPN MH обязательны zebra (ядро/интерфейсы) и bgpd (протокол).

# /etc/frr/daemons
zebra=yes
bgpd=yes
ospfd=no
ospf6d=no
ripd=no
ripngd=no
isisd=no
pimd=no
ldpd=no
nhrpd=no
eigrpd=no
babeld=no
sharpd=no
pbrd=no
bfdd=no
fabricd=no
vrrpd=no
pathd=no
# Настройки терминала
vtysh_enable=yes
zebra_options="  -A 127.0.0.1 -s 90000000"
bgpd_options="   -A 127.0.0.1"

------------------------------
2. Проверка LACP на стороне клиента (CE1)
Чтобы убедиться, что клиент объединил два канала от разных Leaf в один логический bond0, используйте:

# Просмотр общего статуса бонда
docker exec clab-frr-evpn-mh-lab-ce1 cat /proc/net/bonding/bond0

На что смотреть:

* Bonding Mode: IEEE 802.3ad Dynamic link aggregation (LACP).
* MII Status: up.
* Slave Interface (eth1/eth2): Оба должны быть в состоянии Aggregator ID (одинаковом) и иметь статус Active.

------------------------------
3. Проверка синхронизации ESI на Leaf
На любом из Leaf (1 или 2) проверьте, "договорились" ли они между собой:

# Проверка Ethernet Segment
docker exec clab-frr-evpn-mh-lab-leaf1 vtysh -c "show evpn es detail"

Ключевые поля:

* Access interface: eth2 (должен быть Up).
* ESI: 00:11:22:33:44:55:66:77:88:99 (должен совпадать на обоих Leaf).
* Remote VTEPs: Здесь должен появиться IP соседа (например, 10.255.0.12).
* DF Election: Статус Winner или Losing для конкретных VNI.

------------------------------
4. Проверка таблицы MAC-адресов
Убедитесь, что Leaf3 видит клиента CE1 через оба пути сразу (ECMP):

docker exec clab-frr-evpn-mh-lab-leaf3 vtysh -c "show evpn mac vni 10"

Ожидаемый результат:
Для MAC-адреса клиента CE1 в колонке Endpoint (или Next-Hop) должны быть указаны IP обоих Leaf (Leaf1 и Leaf2).
------------------------------
Итоговый тест "Убийство линка"
Для проверки отказоустойчивости выполните:

   1. Запустите пинг: docker exec clab-frr-evpn-mh-lab-ce2 ping 10.0.10.100.
   2. В другом терминале выключите порт: docker exec clab-frr-evpn-mh-lab-leaf1 ip link set eth2 down.
   3. Результат: Пинг должен продолжиться практически без потерь (выпадет максимум 1 пакет), так как CE1 переключит трафик на второй линк через LACP.

Хотите, чтобы я подготовил полный набор файлов (spine.conf, leaf1.conf и т.д.) в виде одного блока текста для копирования?

Ниже представлен полный набор конфигурационных файлов для всех узлов. Создайте папку configs/ и разместите в ней эти файлы перед запуском deploy.sh.
1. configs/spine.conf

hostname spine
password zebra
!
router bgp 65000
 bgp router-id 10.255.0.1
 no bgp default ipv4-unicast
 neighbor LEAFS peer-group
 neighbor LEAFS remote-as 65000
 neighbor 192.168.1.1 peer-group LEAFS
 neighbor 192.168.1.2 peer-group LEAFS
 neighbor 192.168.1.3 peer-group LEAFS
 !
 address-family l2vpn evpn
  neighbor LEAFS activate
  neighbor LEAFS route-reflector-client
 exit-address-family
!
line vty

2. configs/leaf1.conf (Multi-Homing VTEP 1)

hostname leaf1
!
interface eth1
 description to-spine
 ip address 192.168.1.1/24
!
interface eth2
 description to-ce1
 evpn mh es-id 00:11:22:33:44:55:66:77:88:99
 evpn mh es-sys-mac 00:00:00:00:00:01
!
interface br0.10
 ip address 10.0.10.1/24
 mac-address 00:00:5e:00:01:01
!
router bgp 65000
 bgp router-id 10.255.0.11
 no bgp default ipv4-unicast
 neighbor 192.168.1.254 remote-as 65000
 !
 address-family l2vpn evpn
  neighbor 192.168.1.254 activate
  advertise-all-vni
  advertise-svi-ip
 exit-address-family
!

3. configs/leaf2.conf (Multi-Homing VTEP 2)

hostname leaf2
!
interface eth1
 description to-spine
 ip address 192.168.1.2/24
!
interface eth2
 description to-ce1
 evpn mh es-id 00:11:22:33:44:55:66:77:88:99
 evpn mh es-sys-mac 00:00:00:00:00:01
!
interface br0.10
 ip address 10.0.10.1/24
 mac-address 00:00:5e:00:01:01
!
router bgp 65000
 bgp router-id 10.255.0.12
 no bgp default ipv4-unicast
 neighbor 192.168.1.254 remote-as 65000
 !
 address-family l2vpn evpn
  neighbor 192.168.1.254 activate
  advertise-all-vni
  advertise-svi-ip
 exit-address-family

4. configs/leaf3.conf (Single-Homed VTEP)

hostname leaf3
!
interface eth1
 description to-spine
 ip address 192.168.1.3/24
!
interface br0.10
 ip address 10.0.10.1/24
 mac-address 00:00:5e:00:01:01
!
router bgp 65000
 bgp router-id 10.255.0.13
 no bgp default ipv4-unicast
 neighbor 192.168.1.254 remote-as 65000
 !
 address-family l2vpn evpn
  neighbor 192.168.1.254 activate
  advertise-all-vni
  advertise-svi-ip
 exit-address-family

Инструкция по применению:

   1. Создайте файл configs/daemons (из предыдущего ответа).
   2. Создайте файл evpn-mh.clab.yml (из раздела с топологией).
   3. Разместите файлы выше в configs/.
   4. Запустите скрипт deploy.sh.

Важно: В конфигурации Leaf в качестве соседа указан IP .254 (интерфейс Spine). Убедитесь, что Spine имеет эти IP на соответствующих eth-портах или настройте OSPF для связности Loopback-адресов.
Хотите добавить OSPF конфигурацию для Underlay, чтобы сделать схему максимально приближенной к реальности (Production-ready)?


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment