0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

本記事では、Containerlabを使ってマルチベンダー Clos トポロジを構築し、BGP Unnumbered による IP Underlay と、EVPN-VXLAN Overlay による L2 接続を試してします。

今回作ったのは、2 Spine / 4 Leaf のマルチベンダーでのClosです。

  • spine1/spine2: Arista cEOS
  • leaf1: VyOS
  • leaf2: Arista cEOS
  • leaf3: SONiC VS (コンテナ版の SONiC )
  • leaf4: Juniper cJunosEvolved

構成イメージ

UnderlayはBGP Unnumbered、OverlayはBGP EVPN、Data PlaneはVXLANです。
各Leaf配下のclientを同じ192.168.100.0/24に置き、VLAN 100 / VNI 10100でL2延伸できることを確認します。

image.png

今回のポイントは、以下の部分で BGP Unnumbered を利用することで装置間のIPv4アドレスを設定しないで構成した部分です

Physical : 2 Spine / 4 Leaf Clos
Underlay : BGP Unnumbered
Overlay  : BGP EVPN
DataPlane: VXLAN

image.png

今回は、L2延伸用のVLAN/VNIとして以下を利用しました。

VLAN: 100
VNI : 10100
RT  : 10100:10100

EVPNでは、MP-BGPで交換されるEVPN経路に対してRT(Route Target)とVNIを対応付けることで、同一のL2VPNとしてLeaf間を接続します。今回は単一のVNI/RTのみを利用していますが、VNI/RTを分けることで複数のL2VPNを構成できるため、マルチテナント環境におけるL2分離も実現できます。

利用環境

Ubuntu             : 24.04.4 LTS
Containerlab       : 0.76.1
Arista cEOS        : 4.36.0.1F
VyOS               : 2026.03-stream
SONiC VS           : 202511
Juniper cJunosEvo  : 25.4R1.13-EVO
Alpine Linux       : client用

事前準備

Containerlab のインストール

Ubuntu 環境では以下のコマンドでインストールできます。

curl -sL https://containerlab.dev/setup | sudo -E bash -s "all"

インストール後にバージョンを確認します。

containerlab version

今回利用したバージョンは以下です。

containerlab : 0.76.1

Dockerイメージの準備

今回のネットワーク機器のコンテナを準備

Arista cEOS と Juniper cJunosEvo

「Arista cEOS 」と「Juniper cJunosEvo」に関しては過去の以下の記事を参考にしてください

VyOS

containerlabの公式サイトの手順を参考に以下を実施

以下のサイトから VyOS の ISO イメージをダウンロード。今回は「vyos-2026.03-generic-amd64.iso」をダウンロード

ISOファイルと同じ場所に以下のDockerfileを作成

Dockerfile
FROM scratch

ADD rootfs.tar /

RUN for service in\
    getty.target \
    auditd.service \
    ;do systemctl mask $service; done && \
    systemctl disable kea-dhcp-ddns-server.service 

HEALTHCHECK --start-period=10s CMD systemctl is-system-running

CMD ["/sbin/init"]

以下をサーバ上で実施

# ISO の展開に使う bsdtar と、squashfs を tar に変換する sqfs2tar をインストールする
sudo apt-get update
sudo apt-get install -y squashfs-tools-ng libarchive-tools

# VyOS の ISO イメージから live/filesystem.squashfs を取り出す
bsdtar -xf vyos-2026.03-generic-amd64.iso live/filesystem.squashfs

# filesystem.squashfs を tar 形式へ変換し、Docker イメージ作成用の rootfs.tar を生成する
sqfs2tar live/filesystem.squashfs > rootfs.tar

# Dockerfile があるカレントディレクトリを使って Docker イメージをビルドし、
# vyos:2026.03-stream という名前とタグを付ける
# 最後の "." はビルドコンテキストを表しており、忘れずに指定する
docker build -t vyos:2026.03-stream .

SONiC (container)

containerlabの公式サイトの手順を参考に以下を実施

以下のサイトから docker 用のファイルをダウンロード

今回は「Branch 202511」の docker-sonic-vs.gzをダウンロードしサーバに保存
以下をサーバ上で実施

# SONiC VS の Docker イメージを読み込む
docker load -i docker-sonic-vs.gz

# 読み込まれたイメージを確認する
docker images

# 読み込まれたイメージに、Containerlabで使いやすいタグを付ける
docker tag docker-sonic-vs:latest docker-sonic-vs:202511

# 元の docker-sonic-vs:latest タグを削除する
docker rmi docker-sonic-vs:latest

以下の4つができれば、ネットワーク機器側の準備は OK です

$ docker images

IMAGE                               DISK USAGE
ceos:4.36.0.1F                          2.25GB
cjunosevolved:25.4R1.13-EVO             2.11GB
docker-sonic-vs:202511                   813MB
vyos:2026.03-stream                      1.8GB
$

今回の構成やコンフィグを一式 GitHub からダウンロード

# 今回の構成やコンフィグを一式 GitHub からダウンロード
git clone --depth=1 https://github.com/katsumi2018/clab-multivendor-evpn-vxlan-clos.git

# ディレクトリ移動
cd clab-multivendor-evpn-vxlan-clos

ディレクトリ構成は以下の通りとなります

clab-multivendor-evpn-vxlan-clos/
├── clab-multivendor-evpn-vxlan-clos.clab.yml
├── clab-multivendor-evpn-vxlan-clos.clab.yml.annotations.json
└── configs/
    ├── spine1.cfg
    ├── spine2.cfg
    ├── leaf1.cfg
    ├── leaf2.cfg
    ├── leaf3-init.sh
    ├── leaf3-linux.sh
    ├── leaf3-frr.conf
    └── leaf4.cfg

SONiCのleaf3だけは、startup-config一発ではなく、以下の3ファイルに分けています。

  • leaf3-init.sh: SONiCコンテナ起動後の初期化
  • leaf3-linux.sh: Linux/SONiC側のInterface、VLAN、VXLAN設定
  • leaf3-frr.conf: FRRのBGP/EVPN設定

Containerlab topology

clientはすべて同じ192.168.100.0/24に置いています。
今回はL2延伸の確認なので、client側にはdefault gatewayを設定していません。

全コンフィグ

今回利用した各機器の設定です。
長くなるため折りたたみにしています。

spine1.cfg / Arista cEOS
spine1.cfg / Arista cEOS
hostname spine1
!
spanning-tree mode none
!
ip routing
ipv6 unicast-routing
!
!
interface Ethernet1
   description to leaf1 vyos Ethernet1
   no switchport
   ip address unnumbered Loopback0
   ipv6 enable
!
interface Ethernet2
   description to leaf2 ceos Ethernet1
   no switchport
   ip address unnumbered Loopback0
   ipv6 enable
!
interface Ethernet3
   description to leaf3 sonic Ethernet0
   no switchport
   ip address unnumbered Loopback0
   ipv6 enable
!
interface Ethernet4
   description to leaf4 cjunosevo et-0/0/0
   no switchport
   ip address unnumbered Loopback0
   ipv6 enable
!
interface Loopback0
   ip address 10.255.0.101/32
!
!
router bgp 65000
   router-id 10.255.0.101
   maximum-paths 8
   neighbor EVPN peer group
   neighbor EVPN update-source Loopback0
   neighbor EVPN route-reflector-client
   neighbor EVPN send-community extended
   neighbor LEAF-UNDERLAY peer group
   neighbor LEAF-UNDERLAY local-as 65101 no-prepend replace-as
   neighbor LEAF-UNDERLAY send-community
   neighbor 10.255.0.1 peer group EVPN
   neighbor 10.255.0.1 remote-as 65000
   neighbor 10.255.0.2 peer group EVPN
   neighbor 10.255.0.2 remote-as 65000
   neighbor 10.255.0.3 peer group EVPN
   neighbor 10.255.0.3 remote-as 65000
   neighbor 10.255.0.4 peer group EVPN
   neighbor 10.255.0.4 remote-as 65000
   neighbor interface Ethernet1 peer-group LEAF-UNDERLAY remote-as 65001
   neighbor interface Ethernet2 peer-group LEAF-UNDERLAY remote-as 65002
   neighbor interface Ethernet3 peer-group LEAF-UNDERLAY remote-as 65003
   neighbor interface Ethernet4 peer-group LEAF-UNDERLAY remote-as 65004
   !
   address-family evpn
      neighbor EVPN activate
   !
   address-family ipv4
      bgp next-hop address-family ipv6
      neighbor LEAF-UNDERLAY activate
      neighbor LEAF-UNDERLAY next-hop address-family ipv6 originate
      no neighbor 10.255.0.1 activate
      no neighbor 10.255.0.2 activate
      no neighbor 10.255.0.3 activate
      no neighbor 10.255.0.4 activate
      network 10.255.0.101/32
!
username admin privilege 15 secret admin
!
end
spine2.cfg / Arista cEOS
spine2.cfg / Arista cEOS
hostname spine2
!
spanning-tree mode none
!
ip routing
ipv6 unicast-routing
!
!
interface Ethernet1
   description to leaf1 vyos Ethernet2
   no switchport
   ip address unnumbered Loopback0
   ipv6 enable
!
interface Ethernet2
   description to leaf2 ceos Ethernet2
   no switchport
   ip address unnumbered Loopback0
   ipv6 enable
!
interface Ethernet3
   description to leaf3 sonic Ethernet4
   no switchport
   ip address unnumbered Loopback0
   ipv6 enable
!
interface Ethernet4
   description to leaf4 cjunosevo et-0/0/1
   no switchport
   ip address unnumbered Loopback0
   ipv6 enable
!
interface Loopback0
   ip address 10.255.0.102/32
!
!
router bgp 65000
   router-id 10.255.0.102
   maximum-paths 8
   neighbor EVPN peer group
   neighbor EVPN update-source Loopback0
   neighbor EVPN route-reflector-client
   neighbor EVPN send-community extended
   neighbor LEAF-UNDERLAY peer group
   neighbor LEAF-UNDERLAY local-as 65102 no-prepend replace-as
   neighbor LEAF-UNDERLAY send-community
   neighbor 10.255.0.1 peer group EVPN
   neighbor 10.255.0.1 remote-as 65000
   neighbor 10.255.0.2 peer group EVPN
   neighbor 10.255.0.2 remote-as 65000
   neighbor 10.255.0.3 peer group EVPN
   neighbor 10.255.0.3 remote-as 65000
   neighbor 10.255.0.4 peer group EVPN
   neighbor 10.255.0.4 remote-as 65000
   neighbor interface Ethernet1 peer-group LEAF-UNDERLAY remote-as 65001
   neighbor interface Ethernet2 peer-group LEAF-UNDERLAY remote-as 65002
   neighbor interface Ethernet3 peer-group LEAF-UNDERLAY remote-as 65003
   neighbor interface Ethernet4 peer-group LEAF-UNDERLAY remote-as 65004
   !
   address-family evpn
      neighbor EVPN activate
   !
   address-family ipv4
      bgp next-hop address-family ipv6
      neighbor LEAF-UNDERLAY activate
      neighbor LEAF-UNDERLAY next-hop address-family ipv6 originate
      no neighbor 10.255.0.1 activate
      no neighbor 10.255.0.2 activate
      no neighbor 10.255.0.3 activate
      no neighbor 10.255.0.4 activate
      network 10.255.0.102/32
!
username admin privilege 15 secret admin
!
end
leaf1.cfg / VyOS
leaf1.cfg / VyOS
interfaces {
    bridge br0 {
        enable-vlan
        member {
            interface eth3 {
                native-vlan "100"
            }
            interface vxlan0 {
            }
        }
    }
    ethernet eth1 {
        description "to spine1 Ethernet1"
        offload {
            gso
            sg
        }
    }
    ethernet eth2 {
        description "to spine2 Ethernet1"
        offload {
            gso
            sg
        }
    }
    ethernet eth3 {
        description "client vlan100"
        offload {
            gso
            sg
        }
    }
    loopback lo {
        address "10.255.0.1/32"
    }
    vxlan vxlan0 {
        parameters {
            external
        }
        source-interface "lo"
        vlan-to-vni 100 {
            vni "10100"
        }
    }
}
protocols {
    bgp {
        address-family {
            ipv4-unicast {
                maximum-paths {
                    ebgp "8"
                }
                network 10.255.0.1/32 {
                }
            }
            l2vpn-evpn {
                advertise-all-vni
                vni 10100 {
                    route-target {
                        both "10100:10100"
                    }
                }
            }
        }
        neighbor 10.255.0.101 {
            address-family {
                l2vpn-evpn {
                }
            }
            remote-as "65000"
            update-source "lo"
        }
        neighbor 10.255.0.102 {
            address-family {
                l2vpn-evpn {
                }
            }
            remote-as "65000"
            update-source "lo"
        }
        neighbor eth1 {
            interface {
                peer-group "SPINE1-UNDERLAY"
            }
        }
        neighbor eth2 {
            interface {
                peer-group "SPINE2-UNDERLAY"
            }
        }
        parameters {
            router-id "10.255.0.1"
        }
        peer-group SPINE1-UNDERLAY {
            address-family {
                ipv4-unicast {
                }
            }
            local-as 65001 {
                no-prepend {
                    replace-as
                }
            }
            remote-as "65101"
        }
        peer-group SPINE2-UNDERLAY {
            address-family {
                ipv4-unicast {
                }
            }
            local-as 65001 {
                no-prepend {
                    replace-as
                }
            }
            remote-as "65102"
        }
        system-as "65000"
    }
}
service {
    ssh {
        listen-address "0.0.0.0"
    }
}
system {
    config-management {
        commit-revisions "100"
    }
    console {
        device ttyS0 {
            speed "115200"
        }
    }
    host-name "leaf1"
    login {
        user admin {
            authentication {
                encrypted-password "$6$rounds=656000$FMq5TfVE2/YPu5cs$m14t0Gn1.4SuLPBy1l8OITanrWBA63aZIMDqAACnz91MQWr5KzfJtywoDWKOsg1AFil.8pqBmX1un00yYCOFf0"
                public-keys clab {
                    key "AAAAC3NzaC1lZDI1NTE5AAAAICX1AgzRrUL6N/ZaxhdWsr+a206TA8tiYe42qHFx1ur3"
                    type "ssh-ed25519"
                }
            }
        }
    }
    syslog {
        local {
            facility all {
                level "info"
            }
            facility local7 {
                level "debug"
            }
        }
    }
}


// Warning: Do not remove the following line.
// vyos-config-version: "bgp@6:broadcast-relay@1:cluster@2:config-management@1:conntrack@6:conntrack-sync@2:container@3:dhcp-relay@2:dhcp-server@11:dhcpv6-server@6:dns-dynamic@4:dns-forwarding@4:firewall@20:flow-accounting@3:https@7:ids@2:interfaces@34:ipoe-server@4:ipsec@14:isis@3:l2tp@9:lldp@3:mdns@1:monitoring@2:nat@8:nat66@3:nhrp@1:ntp@3:openconnect@3:openvpn@5:ospf@2:pim@1:policy@8:pppoe-server@12:pptp@5:qos@2:quagga@12:reverse-proxy@3:rip@1:rpki@2:salt@1:snmp@3:ssh@3:sstp@6:system@31:vpp@6:vrf@4:vrrp@4:vyos-accel-ppp@2:wanloadbalance@4:webproxy@2"
// Release version: 2026.03

leaf2.cfg / Arista cEOS
leaf2.cfg / Arista cEOS
hostname leaf2
!
spanning-tree mode none
!
ip routing
ipv6 unicast-routing
!
vlan 100
   name CLIENT_VLAN100
!
interface Ethernet1
   description to spine1 Ethernet2
   no switchport
   ip address unnumbered Loopback0
   ipv6 enable
!
interface Ethernet2
   description to spine2 Ethernet2
   no switchport
   ip address unnumbered Loopback0
   ipv6 enable
!
interface Ethernet3
   description client vlan100
   switchport access vlan 100
!
interface Loopback0
   ip address 10.255.0.2/32
!
interface Management0
   ip address 172.20.20.102/24
!
interface Vxlan1
   vxlan source-interface Loopback0
   vxlan udp-port 4789
   vxlan vlan 100 vni 10100
!
!
router bgp 65000
   router-id 10.255.0.2
   no bgp default ipv4-unicast
   maximum-paths 8
   neighbor EVPN peer group
   neighbor EVPN update-source Loopback0
   neighbor EVPN send-community extended
   neighbor SPINE-UNDERLAY peer group
   neighbor SPINE-UNDERLAY local-as 65002 no-prepend replace-as
   neighbor SPINE-UNDERLAY send-community
   neighbor 10.255.0.101 peer group EVPN
   neighbor 10.255.0.101 remote-as 65000
   neighbor 10.255.0.102 peer group EVPN
   neighbor 10.255.0.102 remote-as 65000
   neighbor interface Ethernet1 peer-group SPINE-UNDERLAY remote-as 65101
   neighbor interface Ethernet2 peer-group SPINE-UNDERLAY remote-as 65102
   !
   vlan 100
      rd 10.255.0.2:10100
      route-target import 10100:10100
      route-target export 10100:10100
      redistribute learned
   !
   address-family evpn
      neighbor EVPN activate
   !
   address-family ipv4
      bgp next-hop address-family ipv6
      neighbor SPINE-UNDERLAY activate
      neighbor SPINE-UNDERLAY next-hop address-family ipv6 originate
      network 10.255.0.2/32
!
username admin privilege 15 secret admin
!
end
leaf3-init.sh / SONiC init
leaf3-init.sh / SONiC init
#!/usr/bin/env bash
set -euo pipefail

# ============================================================
# Host-specific values
# ------------------------------------------------------------
# 別の leaf へ流用する場合は、基本的に NODE_NAME だけを変更する。
# 例: leaf4 なら NODE_NAME=leaf4 とし、/configs/leaf4-linux.sh と
#     /configs/leaf4-frr.conf を用意する。
# ============================================================
NODE_NAME="leaf3"

# ラボ操作用ユーザー。containerlab の管理アクセス確認に使う。
ADMIN_USER="admin"
ADMIN_PASSWORD="admin"

# NODE_NAME から派生する設定ファイル。
LINUX_CONFIG="/configs/${NODE_NAME}-linux.sh"
FRR_CONFIG="/configs/${NODE_NAME}-frr.conf"

# config vlan / config vxlan を投入する前に必要な SONiC manager。
SONIC_MANAGER_SERVICES="portmgrd intfmgrd vlanmgrd vxlanmgrd"

# このラボで使う FRR daemon。mgmtd は vtysh -f が詰まることがあるため停止する。
FRR_DAEMONS_ENABLE="zebra bgpd ospfd"
FRR_DAEMONS_DISABLE="mgmtd staticd"

# 起動待ちの最大時間。
SONIC_MANAGER_WAIT_RETRIES="60"
VTYSH_WAIT_RETRIES="60"

# BGP sessions that should be ready after FRR config is applied.
# The retry loop uses only local clears on this SONiC leaf; spines are not touched.
BGP_UNDERLAY_NEIGHBORS="Ethernet0 Ethernet4"
BGP_EVPN_NEIGHBORS="10.255.0.101 10.255.0.102"
BGP_WAIT_RETRIES="12"
BGP_WAIT_INTERVAL="5"

# ConfigDB を保存するかどうか。再起動後の再現性を優先して標準は保存する。
SAVE_CONFIG_DB="1"

log() {
  echo "[${NODE_NAME}-init] $*"
}

install_lab_packages() {
  # SONiC VS コンテナ内で診断しやすいよう、ラボ用の最小ツールを入れる。
  log "install lab packages"
  export DEBIAN_FRONTEND=noninteractive

  if ! apt update || ! apt install -y sudo openssh-server traceroute iputils-tracepath iputils-ping tcpdump; then
    log "WARNING: package install failed, continue with existing packages"
  fi
}

setup_admin_user() {
  # SSH で入って状態確認できるよう、ラボ用 admin ユーザーを用意する。
  log "setup ${ADMIN_USER} user"
  id "${ADMIN_USER}" >/dev/null 2>&1 || useradd -m -s /bin/bash "${ADMIN_USER}"

  echo "${ADMIN_USER}:${ADMIN_PASSWORD}" | chpasswd
  echo "root:${ADMIN_PASSWORD}" | chpasswd
  usermod -aG sudo,frrvty,frr "${ADMIN_USER}" || true

  cat >"/etc/sudoers.d/${ADMIN_USER}" <<EOF
${ADMIN_USER} ALL=(ALL) NOPASSWD:ALL
EOF
  chmod 440 "/etc/sudoers.d/${ADMIN_USER}"
  visudo -cf "/etc/sudoers.d/${ADMIN_USER}" >/dev/null
}

start_sshd() {
  # containerlab の管理ネットワークからログインできるよう sshd を起動する。
  log "start sshd"
  mkdir -p /run/sshd
  /usr/sbin/sshd || true
}


install_dummy_docker_command() {
  # SONiC VS コンテナ内の補完や一部 CLI が docker コマンドを探すことがある。
  # ラボではコンテナ内から Docker を操作しないため、空実装を置いて警告だけを抑える。
  log "install dummy docker command"

  cat >/usr/bin/docker <<'EOF'
#!/usr/bin/env bash
# Dummy docker command for sonic-vs lab shells and completion hooks.
exit 0
EOF

  chmod 755 /usr/bin/docker
}


ensure_mgmt_interface() {
  # SONiC manager 起動後に management interface eth0 が DOWN になることがある。
  # containerlab の管理ネットワークから SSH できるよう、最後に必ず eth0 を上げる。
  log "ensure management interface eth0 is up"
  ip link set eth0 up || true
  ip -br addr show eth0 || true
}

start_sonic_managers() {
  # vlanmgrd / vxlanmgrd が起動する前に config を入れると、
  # Vlan100 -> VNI 10100 が実デバイスへ反映されないことがある。
  log "start SONiC managers: ${SONIC_MANAGER_SERVICES}"

  for svc in ${SONIC_MANAGER_SERVICES}; do
    supervisorctl start "${svc}" || true
  done
}

wait_for_sonic_managers() {
  # supervisor 上で対象 manager が RUNNING になるまで待つ。
  log "wait for SONiC managers"

  for i in $(seq 1 "${SONIC_MANAGER_WAIT_RETRIES}"); do
    all_running=1

    for svc in ${SONIC_MANAGER_SERVICES}; do
      if ! supervisorctl status "${svc}" 2>/dev/null | grep -q RUNNING; then
        all_running=0
      fi
    done

    if [ "${all_running}" -eq 1 ]; then
      log "SONiC managers ready"
      return 0
    fi

    log "waiting SONiC managers... ${i}"
    sleep 2
  done

  log "ERROR: SONiC managers are not ready"
  supervisorctl status ${SONIC_MANAGER_SERVICES} || true
  return 1
}

apply_linux_config() {
  # Interface / IP / MTU / sysctl / VLAN / VXLAN など、
  # Linux と SONiC ConfigDB 側の設定は node 別ファイルへ分離する。
  if [ ! -f "${LINUX_CONFIG}" ]; then
    log "${LINUX_CONFIG} not found, skip Linux/SONiC config"
    return 0
  fi

  log "apply ${LINUX_CONFIG}"
  timeout 120 bash "${LINUX_CONFIG}" >/tmp/"${NODE_NAME}"-linux-apply.log 2>&1
  rc=$?

  log "${LINUX_CONFIG} return code: ${rc}"
  cat /tmp/"${NODE_NAME}"-linux-apply.log || true

  if [ "${rc}" -ne 0 ]; then
    log "ERROR: failed to apply ${LINUX_CONFIG}"
    return "${rc}"
  fi
}

set_frr_daemon() {
  local name="$1"
  local value="$2"

  if grep -q "^${name}=" /etc/frr/daemons; then
    sed -i "s/^${name}=.*/${name}=${value}/" /etc/frr/daemons
  else
    echo "${name}=${value}" >>/etc/frr/daemons
  fi
}

configure_frr_daemons() {
  # 必要な daemon だけを有効化し、ラボで不要または邪魔になる daemon を止める。
  if [ ! -f /etc/frr/daemons ]; then
    log "/etc/frr/daemons not found, skip daemon config"
    return 0
  fi

  log "configure FRR daemons"

  for daemon in ${FRR_DAEMONS_ENABLE}; do
    set_frr_daemon "${daemon}" yes
  done

  for daemon in ${FRR_DAEMONS_DISABLE}; do
    set_frr_daemon "${daemon}" no
  done

  grep -E "^(zebra|bgpd|ospfd|mgmtd|staticd)=" /etc/frr/daemons || true
}

restart_frr() {
  # daemon 設定を反映するため FRR を再起動する。
  log "restart FRR"
  service frr restart || /usr/lib/frr/frrinit.sh restart
}

wait_for_vtysh() {
  # FRR 設定投入前に vtysh が応答するまで待つ。
  log "wait for vtysh"

  for i in $(seq 1 "${VTYSH_WAIT_RETRIES}"); do
    if timeout 5 vtysh -c "show version" >/tmp/"${NODE_NAME}"-vtysh.out 2>/tmp/"${NODE_NAME}"-vtysh.err; then
      log "vtysh ready"
      return 0
    fi

    log "waiting vtysh... ${i}"
    cat /tmp/"${NODE_NAME}"-vtysh.err || true
    sleep 5
  done

  log "ERROR: vtysh is not ready"
  ps -ef | grep -E "watchfrr|mgmtd|zebra|bgpd|ospfd|staticd" | grep -v grep || true
  ls -l /var/run/frr || true
  return 1
}

apply_frr_config() {
  # FRR の BGP/EVPN 設定を投入する。
  # write memory は sonic-vs 上で詰まることがあるため、投入時だけ除外する。
  if [ ! -f "${FRR_CONFIG}" ]; then
    log "${FRR_CONFIG} not found, skip FRR config"
    return 0
  fi

  log "apply ${FRR_CONFIG}"
  awk '
    /^[[:space:]]*write memory[[:space:]]*$/ { next }
    { print }
  ' "${FRR_CONFIG}" >/tmp/"${NODE_NAME}"-frr.apply.conf

  timeout 60 vtysh -f /tmp/"${NODE_NAME}"-frr.apply.conf >/tmp/"${NODE_NAME}"-frr-apply.log 2>&1
  rc=$?

  log "vtysh -f return code: ${rc}"
  cat /tmp/"${NODE_NAME}"-frr-apply.log || true

  if [ "${rc}" -ne 0 ]; then
    log "ERROR: failed to apply ${FRR_CONFIG}"
    vtysh -c "show running-config" || true
    return "${rc}"
  fi
}


bgp_neighbor_established() {
  local neighbor="$1"

  vtysh -c "show bgp neighbors ${neighbor}" 2>/dev/null | grep -q "BGP state = Established"
}

wait_for_bgp_sessions() {
  # In sonic-vs, FRR interface neighbors may need a short time for link-local
  # NHT after FRR config is applied. Do not repeatedly clear neighbors here;
  # repeated clears can keep BGP from settling. This waits and reports state only.
  local attempt neighbor all_established

  log "wait for BGP sessions"

  for attempt in $(seq 1 "${BGP_WAIT_RETRIES}"); do
    all_established=1

    for neighbor in ${BGP_UNDERLAY_NEIGHBORS} ${BGP_EVPN_NEIGHBORS}; do
      if ! bgp_neighbor_established "${neighbor}"; then
        all_established=0
        log "waiting BGP ${neighbor}... ${attempt}/${BGP_WAIT_RETRIES}"
      fi
    done

    if [ "${all_established}" -eq 1 ]; then
      log "BGP sessions ready"
      vtysh -c "show bgp ipv4 unicast summary" -c "show bgp l2vpn evpn summary" || true
      return 0
    fi

    sleep "${BGP_WAIT_INTERVAL}"
  done

  log "WARNING: some BGP sessions are not established yet"
  vtysh -c "show bgp ipv4 unicast summary" -c "show bgp l2vpn evpn summary" || true
  return 0
}


save_config_db() {
  # ConfigDB に投入した VLAN/VXLAN 設定を保存する。
  if [ "${SAVE_CONFIG_DB}" = "1" ]; then
    log "save ConfigDB"
    config save -y || true
  fi
}

show_final_state() {
  # 最後にインターフェース状態だけを軽く出して、起動ログで確認しやすくする。
  log "interface summary"
  ip -br link || true
  ip -br addr || true
}

main() {
  log "start"

  install_lab_packages
  setup_admin_user
  start_sshd
  ensure_mgmt_interface
  install_dummy_docker_command

  start_sonic_managers
  wait_for_sonic_managers

  apply_linux_config

  configure_frr_daemons
  restart_frr
  wait_for_vtysh
  apply_frr_config
  wait_for_bgp_sessions

  save_config_db
  ensure_mgmt_interface
  show_final_state

  log "done"
}

main "$@"

leaf3-linux.sh / SONiC Linux setup
leaf3-linux.sh / SONiC Linux setup
#!/usr/bin/env bash
set -u

# ============================================================
# Host-specific values
# ------------------------------------------------------------
# 別 leaf へ流用する場合は、このブロックを最小限変更する。
# NODE_NAME はログ用、VTEP_IP は leaf の Loopback0 / VTEP IP。
# ============================================================

NODE_NAME="leaf3"
UNDERLAY_IFS="Ethernet0 Ethernet4"
ACCESS_IF="Ethernet8"
LOOPBACK_IF="Loopback0"
VTEP_IP="10.255.0.3"
VLAN_ID="100"
VNI_ID="10100"
VTEP_NAME="vtep"
NVO_NAME="nvo"
BRIDGE_IF="Bridge"
VXLAN_IF="vxlan${VNI_ID}"

log() {
  echo "[${NODE_NAME}-linux] $*"
}

run_quiet() {
  # 冪等に再実行するため、既存設定エラーはログへ出さず無視する。
  "$@" >/dev/null 2>&1 || true
}

bring_up_interfaces() {
  # containerlab が接続した underlay / access port を有効化する。
  # UNDERLAY_IFS は spine1/spine2 向けの複数ポートを想定する。
  log "bring up interfaces"
  sleep 1
  for ifname in ${UNDERLAY_IFS}; do
    ip link set "${ifname}" up 2>/dev/null || true
    run_quiet config interface startup "${ifname}"
  done
  ip link set "${ACCESS_IF}" up || true
  run_quiet config interface startup "${ACCESS_IF}"
}


enable_forwarding() {
  # IPv4 unicast を IPv6 link-local underlay で運ぶため、IPv6 forwarding も明示する。
  log "enable IPv4/IPv6 forwarding"
  sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1 || true
  sysctl -w net.ipv6.conf.all.forwarding=1 >/dev/null 2>&1 || true
  sysctl -w net.ipv6.conf.default.forwarding=1 >/dev/null 2>&1 || true
  for ifname in ${UNDERLAY_IFS}; do
    sysctl -w "net.ipv6.conf.${ifname}.forwarding=1" >/dev/null 2>&1 || true
  done
}

configure_loopback() {
  # BGP router-id / VTEP source として使う Loopback0 を用意する。
  log "configure ${LOOPBACK_IF}"
  run_quiet config loopback add "${LOOPBACK_IF}"
  run_quiet config interface ip add "${LOOPBACK_IF}" "${VTEP_IP}/32"

  # sonic-vs で config コマンドが実 Linux IF を作らない場合の補強。
  if ! ip link show "${LOOPBACK_IF}" >/dev/null 2>&1; then
    log "${LOOPBACK_IF} not found, create Linux dummy"
    ip link add "${LOOPBACK_IF}" type dummy || true
  fi

  ip link set "${LOOPBACK_IF}" up || true

  if ! ip addr show dev "${LOOPBACK_IF}" | grep -q "${VTEP_IP}/32"; then
    ip addr add "${VTEP_IP}/32" dev "${LOOPBACK_IF}" || true
  fi
}

configure_vlan_and_vxlan_configdb() {
  # SONiC ConfigDB に VLAN / VTEP / VNI mapping を投入する。
  log "configure VLAN${VLAN_ID} and VNI${VNI_ID}"
  run_quiet config vlan add "${VLAN_ID}"
  run_quiet config vlan member add -u "${VLAN_ID}" "${ACCESS_IF}"

  sleep 1
  run_quiet config vxlan add "${VTEP_NAME}" "${VTEP_IP}"
  sleep 1
  run_quiet config vxlan evpn_nvo add "${NVO_NAME}" "${VTEP_NAME}"
  sleep 1
  run_quiet config vxlan map add "${VTEP_NAME}" "${VLAN_ID}" "${VNI_ID}"
}

wait_for_app_db() {
  # vlanmgrd / vxlanmgrd が ConfigDB を処理した痕跡を少し待つ。
  log "wait VLAN/VXLAN in APP_DB"

  APP_DB_READY=0
  for i in $(seq 1 30); do
    if sonic-db-cli APPL_DB keys 'VLAN*' 2>/dev/null | grep -q . || \
       sonic-db-cli APPL_DB keys 'VXLAN*' 2>/dev/null | grep -q . || \
       sonic-db-cli APPL_DB keys 'TUNNEL*' 2>/dev/null | grep -q .; then
      log "APP_DB updated"
      sonic-db-cli APPL_DB keys 'VLAN*' || true
      sonic-db-cli APPL_DB keys 'VXLAN*' || true
      sonic-db-cli APPL_DB keys 'TUNNEL*' || true
      APP_DB_READY=1
      break
    fi

    log "waiting APP_DB VLAN/VXLAN... ${i}"
    sleep 2
  done

  if [ "${APP_DB_READY}" -ne 1 ]; then
    log "WARNING: APP_DB VLAN/VXLAN entries were not observed"
  fi
}


ensure_bridge() {
  # SONiC manager が Bridge/Vlan100 を作らない場合に備え、Linux 側で補強する。
  log "ensure ${BRIDGE_IF} and Vlan${VLAN_ID}"

  if ! ip link show "${BRIDGE_IF}" >/dev/null 2>&1; then
    ip link add name "${BRIDGE_IF}" type bridge vlan_filtering 1 || true
  fi
  ip link set "${BRIDGE_IF}" up || true

  if ! ip link show "Vlan${VLAN_ID}" >/dev/null 2>&1; then
    ip link add link "${BRIDGE_IF}" name "Vlan${VLAN_ID}" type vlan id "${VLAN_ID}" || true
  fi
  ip link set "Vlan${VLAN_ID}" up || true
  bridge vlan add dev "${BRIDGE_IF}" vid "${VLAN_ID}" self 2>/dev/null || true
}

ensure_vxlan_linux_fallback() {
  # sonic-vs 202605 では vxlanmgrd が ConfigDB を受けても、Linux の VXLAN IF を
  # 作れないことがある。一方で正常時は vtep-100 のような名前で作られるため、
  # 既存 VNI の IF を優先し、無ければ fallback 名で明示作成する。
  log "ensure VNI${VNI_ID} Linux VXLAN interface"

  for i in $(seq 1 30); do
    if ip link show "${BRIDGE_IF}" >/dev/null 2>&1; then
      EXISTING_VXLAN_IF="$(ip -d -o link show type vxlan 2>/dev/null | awk -v needle="id ${VNI_ID} " '$0 ~ needle { name=$2; sub(/:$/, "", name); print name; exit }')"
      if [ -n "${EXISTING_VXLAN_IF}" ]; then
        VXLAN_IF="${EXISTING_VXLAN_IF}"
      elif ! ip link show "${VXLAN_IF}" >/dev/null 2>&1; then
        ip link add "${VXLAN_IF}" type vxlan id "${VNI_ID}" local "${VTEP_IP}" dstport 4789 nolearning || true
      fi

      ip link set "${VXLAN_IF}" master "${BRIDGE_IF}" || true
      bridge vlan del dev "${VXLAN_IF}" vid 1 2>/dev/null || true
      bridge vlan del dev "${VXLAN_IF}" vid "${VLAN_ID}" 2>/dev/null || true
      bridge vlan add dev "${VXLAN_IF}" vid "${VLAN_ID}" pvid untagged || true
      ip link set "${VXLAN_IF}" up || true
      bridge link set dev "${VXLAN_IF}" learning off 2>/dev/null || true
      bridge link set dev "${VXLAN_IF}" neigh_suppress on 2>/dev/null || true
      return 0
    fi

    log "waiting ${BRIDGE_IF} before adding ${VXLAN_IF}... ${i}"
    sleep 2
  done

  log "WARNING: ${BRIDGE_IF} not found, skip VXLAN fallback"
}

ensure_access_port_bridge_vlan() {
  # sonic-vs では ACCESS_IF が Bridge/VLAN に自動収容されないことがあるため補強する。
  log "ensure ${ACCESS_IF} is in ${BRIDGE_IF} VLAN${VLAN_ID}"

  for i in $(seq 1 30); do
    if ip link show "${BRIDGE_IF}" >/dev/null 2>&1; then
      ip link set "${ACCESS_IF}" master "${BRIDGE_IF}" || true
      bridge vlan del dev "${ACCESS_IF}" vid 1 2>/dev/null || true
      bridge vlan add dev "${ACCESS_IF}" vid "${VLAN_ID}" pvid untagged || true
      ip link set "${ACCESS_IF}" up || true
      return 0
    fi

    log "waiting ${BRIDGE_IF} before adding ${ACCESS_IF}... ${i}"
    sleep 2
  done

  log "WARNING: ${BRIDGE_IF} not found, skip ${ACCESS_IF} VLAN membership"
}

show_state() {
  # 起動ログから最低限の状態を追えるようにする。
  log "check interfaces"
  ip -br link || true

  log "check bridge vlan"
  bridge vlan show || true

  log "check routes"
  ip route show "${VTEP_IP}/32" || true
}

main() {
  log "start"
  bring_up_interfaces
  enable_forwarding
  configure_loopback
  configure_vlan_and_vxlan_configdb
  wait_for_app_db
  ensure_bridge
  ensure_vxlan_linux_fallback
  ensure_access_port_bridge_vlan
  show_state
  log "done"
}

main "$@"

leaf3-frr.conf / SONiC FRR
leaf3-frr.conf / SONiC FRR
!
route-map ALLOW_ALL permit 10
exit
!
router bgp 65000
 bgp router-id 10.255.0.3
 no bgp default ipv4-unicast
 neighbor EVPN peer-group
 neighbor EVPN update-source Loopback0
 neighbor SPINE-UNDERLAY peer-group
 neighbor SPINE-UNDERLAY local-as 65003 no-prepend replace-as
 neighbor SPINE-UNDERLAY capability extended-nexthop
 neighbor 10.255.0.101 remote-as 65000
 neighbor 10.255.0.101 peer-group EVPN
 neighbor 10.255.0.102 remote-as 65000
 neighbor 10.255.0.102 peer-group EVPN
 neighbor Ethernet0 interface peer-group SPINE-UNDERLAY
 neighbor Ethernet0 remote-as 65101
 neighbor Ethernet4 interface peer-group SPINE-UNDERLAY
 neighbor Ethernet4 remote-as 65102
 !
 address-family ipv4 unicast
  network 10.255.0.3/32
  neighbor SPINE-UNDERLAY activate
  neighbor SPINE-UNDERLAY route-map ALLOW_ALL in
  neighbor SPINE-UNDERLAY route-map ALLOW_ALL out
  maximum-paths 8
 exit-address-family
 !
 address-family l2vpn evpn
  neighbor EVPN activate
  advertise-all-vni
  vni 10100
   rd 10.255.0.3:10100
   route-target import 10100:10100
   route-target export 10100:10100
  exit-vni
 exit-address-family
exit
!
no ip nht resolve-via-default
!
no ipv6 nht resolve-via-default
!
leaf4.cfg / Juniper cJunosEvolved
leaf4.cfg / Juniper cJunosEvolved
system {
    host-name leaf4;
    root-authentication {
        encrypted-password "$6$GS4pSXiY$GRhQcI8pj3vmM4GwN14CtXS74s1f/L9DX/25AJPn9qVRNgcDqYzQ9AJLLIhD9IiCthCv4IfdUOvEDWC.Mdu.S0"; ## SECRET-DATA
    }
    login {
        user admin {
            uid 500;
            class superuser;
            authentication {
                encrypted-password "$6$9YSzwiCD$ZiMI1N.5fcWCe5fH8hZz/FtISY4K8QKjv9p0w6Hkyct71ke1bn3OQQk0oi7/l5Sn8yP1CClO9CeGSMpNQcFjT/"; ## SECRET-DATA
            }
        }
    }
    services {
        ssh;
    }
}
interfaces {
    et-0/0/0 {
        description "to spine1 Ethernet4";
        unit 0 {
            family inet {
                unnumbered-address lo0.0;
            }
            family inet6;
        }
    }
    et-0/0/1 {
        description "to spine2 Ethernet4";
        unit 0 {
            family inet {
                unnumbered-address lo0.0;
            }
            family inet6;
        }
    }
    et-0/0/2 {
        description "client vlan100";
        unit 0 {
            family ethernet-switching {
                interface-mode access;
                vlan {
                    members VLAN100;
                }
            }
        }
    }
    lo0 {
        unit 0 {
            family inet {
                address 10.255.0.4/32;
            }
        }
    }
    re0:mgmt-0 {
        unit 0 {
            family inet {
                address 172.20.20.104/24;
            }
        }
    }
}
forwarding-options {
    tunnel-termination;
}
policy-options {
    policy-statement LOOPBACK {
        term 10 {
            from {
                route-filter 10.255.0.4/32 exact;
            }
            then accept;
        }
        then reject;
    }
    as-list UNDERLAY-AS members [ 65101 65102 ];
}
routing-instances {
    EVPN100 {
        instance-type mac-vrf;
        protocols {
            evpn {
                encapsulation vxlan;
                extended-vni-list 10100;
                multicast-mode ingress-replication;
            }
        }
        vtep-source-interface lo0.0;
        service-type vlan-based;
        interface et-0/0/2.0;
        route-distinguisher 10.255.0.4:10100;
        vrf-target target:10100:10100;
        vlans {
            VLAN100 {
                vlan-id 100;
                vxlan {
                    vni 10100;
                }
            }
        }
    }
}
routing-options {
    router-id 10.255.0.4;
    autonomous-system 65000;
}
protocols {
    router-advertisement {
        interface et-0/0/0.0;
        interface et-0/0/1.0;
    }
    bgp {
        group UNDERLAY {
            type external;
            family inet {
                unicast {
                    extended-nexthop;
                }
            }
            export LOOPBACK;
            local-as 65004;
            multipath {
                multiple-as;
            }
            dynamic-neighbor FABRIC {
                peer-auto-discovery {
                    family inet6 {
                        ipv6-nd;
                    }
                    interface et-0/0/0.0;
                    interface et-0/0/1.0;
                }
            }
            peer-as-list UNDERLAY-AS;
        }
        group EVPN {
            type internal;
            local-address 10.255.0.4;
            family evpn {
                signaling;
            }
            neighbor 10.255.0.101 {
                peer-as 65000;
            }
            neighbor 10.255.0.102 {
                peer-as 65000;
            }
        }
    }
}

動作確認

起動

Containerlabで起動します。

sudo containerlab deploy -t clab-multivendor-evpn-vxlan-clos.clab.yml

起動すると以下のような表示がされます
(cjunosevolvedはこのあとBGP接続まで5分~10分程度かかりました)

image.png

動作確認

起動済みのcontainerlab上で、各Leafの状態を確認しました。
ここでは、実際に見たコマンドと、確認できたポイントをまとめます。
MAC 学習させるために、事前に client 間で PING 疎通をしています

client間疎通

はじめに、client間でpingを実行しました。

見たコマンドは以下です。

docker exec clab-multivendor-evpn-vxlan-clos-client1 ping -c 2 -W 1 192.168.100.2
docker exec clab-multivendor-evpn-vxlan-clos-client1 ping -c 2 -W 1 192.168.100.3
docker exec clab-multivendor-evpn-vxlan-clos-client1 ping -c 2 -W 1 192.168.100.4

以下の通り、各クライアント間で同一セグメントとしてPing疎通できており、EVPN-VXLANによるL2延伸が正しく動作していることを確認できます。

$ docker exec clab-multivendor-evpn-vxlan-clos-client1 ping -c 2 -W 1 192.168.100.2
PING 192.168.100.2 (192.168.100.2): 56 data bytes
64 bytes from 192.168.100.2: seq=0 ttl=64 time=2.972 ms
64 bytes from 192.168.100.2: seq=1 ttl=64 time=1.771 ms

--- 192.168.100.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 1.771/2.371/2.972 ms
$
$ docker exec clab-multivendor-evpn-vxlan-clos-client1 ping -c 2 -W 1 192.168.100.3
PING 192.168.100.3 (192.168.100.3): 56 data bytes
64 bytes from 192.168.100.3: seq=0 ttl=64 time=0.838 ms
64 bytes from 192.168.100.3: seq=1 ttl=64 time=0.775 ms

--- 192.168.100.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.775/0.806/0.838 ms
$
$ docker exec clab-multivendor-evpn-vxlan-clos-client1 ping -c 2 -W 1 192.168.100.4
PING 192.168.100.4 (192.168.100.4): 56 data bytes
64 bytes from 192.168.100.4: seq=0 ttl=64 time=2.158 ms
64 bytes from 192.168.100.4: seq=1 ttl=64 time=2.199 ms

--- 192.168.100.4 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 2.158/2.178/2.199 ms
$

以降、各Leafの状態を確認していきます。

leaf1 / VyOS

leaf1で、状態を確認していきます
(ログインは、ユーザ名:admin、パスワード:admin)

Underlay BGPはspine1/spine2の両方とEstablishedです。
(VyOSはState/PfxRcdの列に数字が出ていることで Established と判断できます)

admin@leaf1:~$ show bgp ipv4 summary

IPv4 Unicast Summary:
BGP router identifier 10.255.0.1, local AS number 65000 VRF default vrf-id 0
BGP table version 7
RIB entries 11, using 1408 bytes of memory
Peers 2, using 47 KiB of memory
Peer groups 2, using 128 bytes of memory

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc
eth1            4      65101        18        15        7    0    0 00:06:24            5        6 N/A
eth2            4      65102        15        15        7    0    0 00:06:24            5        6 N/A

Total number of neighbors 2
admin@leaf1:~$

EVPN peerもspine1/spine2の両方とEstablishedです。
(VyOSはState/PfxRcdの列に数字が出ていることで Established と判断できます)

admin@leaf1:~$ show bgp l2vpn evpn summary
BGP router identifier 10.255.0.1, local AS number 65000 VRF default vrf-id 0
BGP table version 0
RIB entries 7, using 896 bytes of memory
Peers 2, using 47 KiB of memory
Peer groups 2, using 128 bytes of memory

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc
10.255.0.101    4      65000        15        11        6    0    0 00:06:24            6        2 N/A
10.255.0.102    4      65000        15        11        6    0    0 00:06:25            6        2 N/A

Total number of neighbors 2
admin@leaf1:~$

IPv4のルーティングテーブルを確認すると、他のLeaf/SpineのLoopbackアドレスをBGPで学習しており、BGP UnnumberedによりネクストホップがIPv6リンクローカルアドレスになっていることが分かります。

admin@leaf1:~$ show ip route bgp
Codes: K - kernel route, C - connected, L - local, S - static,
       R - RIP, O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
       f - OpenFabric, t - Table-Direct,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup
       t - trapped, o - offload failure

IPv4 unicast VRF default:
B>* 10.255.0.2/32 [20/0] via fe80::a8c1:abff:fea5:d106, eth1, weight 1, 00:12:16
B>* 10.255.0.3/32 [20/0] via fe80::a8c1:abff:fec6:9c53, eth2, weight 1, 00:12:28
B>* 10.255.0.4/32 [20/0] via fe80::a8c1:abff:fec6:9c53, eth2, weight 1, 00:06:36
B>* 10.255.0.101/32 [20/0] via fe80::a8c1:abff:fea5:d106, eth1, weight 1, 00:12:28
B>* 10.255.0.102/32 [20/0] via fe80::a8c1:abff:fec6:9c53, eth2, weight 1, 00:12:28
admin@leaf1:~$

MACアドレス学習では、local client1のMACはeth3、remote clientのMACは対向の leaf の Loopbask アドレスに見えています。

admin@leaf1:~$ show evpn mac vni all
VNI 10100 #MACs (local and remote) 4

Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy
MAC               Type   Flags Intf/Remote ES/VTEP            VLAN  Seq #'s
aa:c1:ab:5f:79:9e local        eth3                           100   0/0
aa:c1:ab:59:6d:e8 remote       10.255.0.3                           0/0
aa:c1:ab:d9:44:66 remote       10.255.0.4                           0/0
aa:c1:ab:b5:45:41 remote       10.255.0.2                           0/0
admin@leaf1:~$

EVPN route type 2では、各Leaf配下のMACを学習しています。
(長くなるため折りたたみにしています)

show bgp l2vpn evpn route type macip
admin@leaf1:~$ show bgp l2vpn evpn route type macip
BGP table version is 3, local router ID is 10.255.0.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal
Origin codes: i - IGP, e - EGP, ? - incomplete
EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]
EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]
EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]
EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]
EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]

   Network          Next Hop            Metric LocPrf Weight Path
                    Extended Community
Route Distinguisher: 10.255.0.1:2
 *>  [2]:[0]:[48]:[aa:c1:ab:5f:79:9e]
                    10.255.0.1                         32768 i
                    ET:8 RT:10100:10100
Route Distinguisher: 10.255.0.2:10100
 *>i [2]:[0]:[48]:[aa:c1:ab:b5:45:41]
                    10.255.0.2                    100      0 i
                    RT:10100:10100 ET:8
 *=i [2]:[0]:[48]:[aa:c1:ab:b5:45:41]
                    10.255.0.2                    100      0 i
                    RT:10100:10100 ET:8
Route Distinguisher: 10.255.0.3:10100
 *>i [2]:[0]:[48]:[aa:c1:ab:59:6d:e8]
                    10.255.0.3                    100      0 i
                    RT:10100:10100 ET:8
 *=i [2]:[0]:[48]:[aa:c1:ab:59:6d:e8]
                    10.255.0.3                    100      0 i
                    RT:10100:10100 ET:8
 *>i [2]:[0]:[48]:[aa:c1:ab:59:6d:e8]:[128]:[fe80::a8c1:abff:fe59:6de8]
                    10.255.0.3                    100      0 i
                    RT:10100:10100 ET:8
 *=i [2]:[0]:[48]:[aa:c1:ab:59:6d:e8]:[128]:[fe80::a8c1:abff:fe59:6de8]
                    10.255.0.3                    100      0 i
                    RT:10100:10100 ET:8
Route Distinguisher: 10.255.0.4:10100
 *>i [2]:[0]:[48]:[aa:c1:ab:d9:44:66]
                    10.255.0.4                    100      0 i
                    RT:10100:10100 ET:8
 *=i [2]:[0]:[48]:[aa:c1:ab:d9:44:66]
                    10.255.0.4                    100      0 i
                    RT:10100:10100 ET:8
 *>i [2]:[0]:[48]:[aa:c1:ab:d9:44:66]:[32]:[192.168.100.4]
                    10.255.0.4                    100      0 i
                    RT:10100:10100 ET:8
 *=i [2]:[0]:[48]:[aa:c1:ab:d9:44:66]:[32]:[192.168.100.4]
                    10.255.0.4                    100      0 i
                    RT:10100:10100 ET:8

Displayed 6 prefixes (11 paths) (of requested type)
admin@leaf1:~$

leaf2 / Arista cEOS

leaf2で、状態を確認していきます
(ログインは、ユーザ名:admin、パスワード:admin)

Underlay BGPはspine1/spine2の両方とEstablishedです。

leaf2# show bgp ipv4 unicast summary
BGP summary information for VRF default
Router identifier 10.255.0.2, local AS number 65000
Neighbor Status Codes: m - Under maintenance
  Neighbor                      V AS           MsgRcvd   MsgSent  InQ OutQ  Up/Down State   PfxRcd PfxAcc PfxAdv
  fe80::a8c1:abff:fe50:b497%Et1 4 65101             41        40    0    0 00:28:40 Estab   5      5      4
  fe80::a8c1:abff:fec9:f146%Et2 4 65102             43        40    0    0 00:28:40 Estab   5      5      3
leaf2#

EVPN peerもspine1/spine2の両方とEstablishedです。

leaf2# show bgp evpn summary
BGP summary information for VRF default
Router identifier 10.255.0.2, local AS number 65000
Neighbor Status Codes: m - Under maintenance
  Neighbor     V AS           MsgRcvd   MsgSent  InQ OutQ  Up/Down State   PfxRcd PfxAcc PfxAdv
  10.255.0.101 4 65000             46        42    0    0 00:29:26 Estab   5      5      1
  10.255.0.102 4 65000             46        42    0    0 00:29:26 Estab   5      5      1
leaf2#

VNI 10100がVLAN100に対応し、access portのEthernet3とVxlan1に紐づいています。

leaf2# show vxlan vni
VNI to VLAN Mapping for Vxlan1
VNI         VLAN       Source       Interface       802.1Q Tag
----------- ---------- ------------ --------------- ----------
10100       100        static       Ethernet3       untagged
                                    Vxlan1          100
leaf2#

Vxlan1はLoopback0をsource interfaceとしてupしています。

leaf2# show interfaces vxlan 1
Vxlan1 is up, line protocol is up (connected)
  Hardware is Vxlan
  Source interface is Loopback0 and is active with 10.255.0.2
  Listening on UDP port 4789
  Replication/Flood Mode is headend with Flood List Source: EVPN
  Remote MAC learning via EVPN
  VNI mapping to VLANs
  Static VLAN to VNI mapping is
    [100, 10100]
  Note: All Dynamic VLANs used by VCS are internal VLANs.
        Use 'show vxlan vni' for details.
  Static VRF to VNI mapping is not configured
  Headend replication flood vtep list is:
   100 10.255.0.1      10.255.0.3      10.255.0.4
  Shared Router MAC is 0000.0000.0000
leaf2#

EVPN経由で、他Leaf配下のMACをVXLAN address tableに学習しています。

leaf2# show vxlan address-table
          Vxlan Mac Address Table
----------------------------------------------------------------------

VLAN  Mac Address     Type      Prt  VTEP             Moves   Last Move
----  -----------     ----      ---  ----             -----   ---------
 100  aac1.ab59.6de8  EVPN      Vx1  10.255.0.3       1       0:03:18 ago
 100  aac1.ab5f.799e  EVPN      Vx1  10.255.0.1       1       0:01:58 ago
 100  aac1.abd9.4466  EVPN      Vx1  10.255.0.4       1       0:25:41 ago
Total Remote Mac Addresses for this criterion: 3
leaf2#

MAC address tableでは、ローカルclient2のMACはEthernet3、remote clientのMACはVxlan1側に見えています。

leaf2# show mac address-table
          Mac Address Table
------------------------------------------------------------------

Vlan    Mac Address       Type        Ports      Moves   Last Move
----    -----------       ----        -----      -----   ---------
 100    aac1.ab59.6de8    DYNAMIC     Vx1        1       0:02:18 ago
 100    aac1.ab5f.799e    DYNAMIC     Vx1        1       0:00:57 ago
 100    aac1.abb5.4541    DYNAMIC     Et3        1       0:00:57 ago
 100    aac1.abd9.4466    DYNAMIC     Vx1        1       0:24:41 ago
Total Mac Addresses for this criterion: 4

leaf2#

EVPN route type 2では、各Leaf配下のMACを学習しています。
(長くなるため折りたたみにしています)

show bgp evpn route-type mac-ip
leaf2# show bgp evpn route-type mac-ip
BGP routing table information for VRF default
Router identifier 10.255.0.2, local AS number 65000
Route status codes: * - valid, > - active, S - Stale, E - ECMP head, e - ECMP
                    c - Contributing to ECMP, % - Pending best path selection
Origin codes: i - IGP, e - EGP, ? - incomplete
AS Path Attributes: Or-ID - Originator ID, C-LST - Cluster List, LL Nexthop - Link Local Nexthop

          Network                Next Hop              Metric  LocPref Weight  Path
 * >Ec    RD: 10.255.0.3:10100 mac-ip aac1.ab59.6de8
                                 10.255.0.3            -       100     0       i Or-ID: 10.255.0.3 C-LST: 10.255.0.101
 *  ec    RD: 10.255.0.3:10100 mac-ip aac1.ab59.6de8
                                 10.255.0.3            -       100     0       i Or-ID: 10.255.0.3 C-LST: 10.255.0.102
 * >Ec    RD: 10.255.0.3:10100 mac-ip aac1.ab59.6de8 fe80::a8c1:abff:fe59:6de8
                                 10.255.0.3            -       100     0       i Or-ID: 10.255.0.3 C-LST: 10.255.0.101
 *  ec    RD: 10.255.0.3:10100 mac-ip aac1.ab59.6de8 fe80::a8c1:abff:fe59:6de8
                                 10.255.0.3            -       100     0       i Or-ID: 10.255.0.3 C-LST: 10.255.0.102
 * >Ec    RD: 10.255.0.1:2 mac-ip aac1.ab5f.799e
                                 10.255.0.1            -       100     0       i Or-ID: 10.255.0.1 C-LST: 10.255.0.101
 *  ec    RD: 10.255.0.1:2 mac-ip aac1.ab5f.799e
                                 10.255.0.1            -       100     0       i Or-ID: 10.255.0.1 C-LST: 10.255.0.102
 * >      RD: 10.255.0.2:10100 mac-ip aac1.abb5.4541
                                 -                     -       -       0       i
 * >Ec    RD: 10.255.0.4:10100 mac-ip aac1.abd9.4466
                                 10.255.0.4            -       100     0       i Or-ID: 10.255.0.4 C-LST: 10.255.0.101
 *  ec    RD: 10.255.0.4:10100 mac-ip aac1.abd9.4466
                                 10.255.0.4            -       100     0       i Or-ID: 10.255.0.4 C-LST: 10.255.0.102
 * >Ec    RD: 10.255.0.4:10100 mac-ip aac1.abd9.4466 192.168.100.4
                                 10.255.0.4            -       100     0       i Or-ID: 10.255.0.4 C-LST: 10.255.0.101
 *  ec    RD: 10.255.0.4:10100 mac-ip aac1.abd9.4466 192.168.100.4
                                 10.255.0.4            -       100     0       i Or-ID: 10.255.0.4 C-LST: 10.255.0.102
leaf2#

leaf3 / SONiC VS

leaf3で、状態を確認していきます
(ログインは、ユーザ名:admin、パスワード:admin)

Underlay BGPは、Ethernet0/Ethernet4の両方でEstablishedです。
(SONiCはState/PfxRcdの列に数字が出ていることで Established と判断できます)

admin@leaf3:~$ vtysh -c "show bgp ipv4 unicast summary"
BGP router identifier 10.255.0.3, local AS number 65000 VRF default vrf-id 0
BGP table version 6
RIB entries 11, using 1408 bytes of memory
Peers 2, using 47 KiB of memory
Peer groups 2, using 128 bytes of memory

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc
Ethernet0       4      65101        52        47        6    0    0 00:38:40            4        6 N/A
Ethernet4       4      65102        52        47        6    0    0 00:38:40            4        6 N/A

Total number of neighbors 2
admin@leaf3:~$

EVPN peerもspine1/spine2の両方とEstablishedです。
(SONiCはState/PfxRcdの列に数字が出ていることで Established と判断できます)

admin@leaf3:~$ vtysh -c "show bgp l2vpn evpn summary"
BGP router identifier 10.255.0.3, local AS number 65000 VRF default vrf-id 0
BGP table version 0
RIB entries 7, using 896 bytes of memory
Peers 2, using 47 KiB of memory
Peer groups 2, using 128 bytes of memory

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc
10.255.0.101    4      65000        61        50       13    0    0 00:40:21            6        1 N/A
10.255.0.102    4      65000        61        50       13    0    0 00:40:21            6        1 N/A

Total number of neighbors 2
admin@leaf3:~$

BGPで他Leaf/SpineのLoopbackを学習しています。

admin@leaf3:~$ vtysh -c "show ip route bgp"
Codes: K - kernel route, C - connected, L - local, S - static,
       R - RIP, O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
       f - OpenFabric, t - Table-Direct,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup
       t - trapped, o - offload failure

IPv4 unicast VRF default:
B>* 10.255.0.1/32 [20/0] via fe80::a8c1:abff:fe17:9570, Ethernet4, weight 1, 00:42:47
B>* 10.255.0.2/32 [20/0] via fe80::a8c1:abff:fece:2bf2, Ethernet0, weight 1, 00:42:35
B>* 10.255.0.4/32 [20/0] via fe80::a8c1:abff:fe17:9570, Ethernet4, weight 1, 00:36:55
B>* 10.255.0.101/32 [20/0] via fe80::a8c1:abff:fece:2bf2, Ethernet0, weight 1, 00:42:49
B>* 10.255.0.102/32 [20/0] via fe80::a8c1:abff:fe17:9570, Ethernet4, weight 1, 00:42:49
admin@leaf3:~$

EVPN で MACを学習しています。

admin@leaf3:~$ vtysh -c "show evpn mac vni all"

VNI 10100 #MACs (local and remote) 4

Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy
MAC               Type   Flags Intf/Remote ES/VTEP            VLAN  Seq #'s
aa:c1:ab:5f:79:9e remote       10.255.0.1                           1/0
aa:c1:ab:59:6d:e8 local        Ethernet8                      100   0/0
aa:c1:ab:d9:44:66 remote       10.255.0.4                           0/0
aa:c1:ab:b5:45:41 remote       10.255.0.2                           1/0
admin@leaf3:~$

VNI 10100 が VLAN 100 に対応する L2 VNI として動作しており、他LeafのRemote VTEPを学習できていることが確認できます。

admin@leaf3:~$ vtysh -c "show evpn vni detail"
VNI: 10100
 Type: L2
 Vlan: 100
 Bridge: Bridge
 Tenant VRF: default
 VxLAN interface: vtep-100
 VxLAN ifIndex: 36
 SVI interface: Vlan100
 SVI ifIndex: 35
 Local VTEP IP: 10.255.0.3
 Mcast group: 0.0.0.0
 Remote VTEPs for this VNI:
  10.255.0.4 flood: HER
  10.255.0.2 flood: HER
  10.255.0.1 flood: HER
 Number of MACs (local and remote) known for this VNI: 4
 Number of ARPs (IPv4 and IPv6, local and remote) known for this VNI: 5
 Advertise-gw-macip: No
 Advertise-svi-macip: No

admin@leaf3:~$

EVPN route type 2では、各Leaf配下のMACを学習しています。
(長くなるため折りたたみにしています)

vtysh -c "show bgp l2vpn evpn route type macip"
admin@leaf3:~$ vtysh -c "show bgp l2vpn evpn route type macip"
BGP table version is 6, local router ID is 10.255.0.3
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal
Origin codes: i - IGP, e - EGP, ? - incomplete
EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]
EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]
EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]
EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]
EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]

   Network          Next Hop            Metric LocPrf Weight Path
                    Extended Community
Route Distinguisher: 10.255.0.1:2
 *>i [2]:[0]:[48]:[aa:c1:ab:5f:79:9e]
                    10.255.0.1                    100      0 i
                    RT:10100:10100 ET:8
 *=i [2]:[0]:[48]:[aa:c1:ab:5f:79:9e]
                    10.255.0.1                    100      0 i
                    RT:10100:10100 ET:8
Route Distinguisher: 10.255.0.2:10100
 *>i [2]:[0]:[48]:[aa:c1:ab:b5:45:41]
                    10.255.0.2                    100      0 i
                    RT:10100:10100 ET:8
 *=i [2]:[0]:[48]:[aa:c1:ab:b5:45:41]
                    10.255.0.2                    100      0 i
                    RT:10100:10100 ET:8
Route Distinguisher: 10.255.0.3:10100
 *>  [2]:[0]:[48]:[aa:c1:ab:59:6d:e8]
                    10.255.0.3                         32768 i
                    ET:8 RT:10100:10100
 *>  [2]:[0]:[48]:[aa:c1:ab:59:6d:e8]:[128]:[fe80::a8c1:abff:fe59:6de8]
                    10.255.0.3                         32768 i
                    ET:8 RT:10100:10100
Route Distinguisher: 10.255.0.4:10100
 *>i [2]:[0]:[48]:[aa:c1:ab:d9:44:66]
                    10.255.0.4                    100      0 i
                    RT:10100:10100 ET:8
 *=i [2]:[0]:[48]:[aa:c1:ab:d9:44:66]
                    10.255.0.4                    100      0 i
                    RT:10100:10100 ET:8
 *>i [2]:[0]:[48]:[aa:c1:ab:d9:44:66]:[32]:[192.168.100.4]
                    10.255.0.4                    100      0 i
                    RT:10100:10100 ET:8
 *=i [2]:[0]:[48]:[aa:c1:ab:d9:44:66]:[32]:[192.168.100.4]
                    10.255.0.4                    100      0 i
                    RT:10100:10100 ET:8

Displayed 6 prefixes (10 paths) (of requested type)
admin@leaf3:~$

leaf4 / Juniper cJunosEvolved

leaf4で、状態を確認していきます
(ログインは、ユーザ名:admin、パスワード:admin@123)

Underlay/EVPN ともに BGPは、Ethernet0/Ethernet4の両方でEstablishedです。
EVPN peerもspine1/spine2の両方とEstablishedです。

admin@leaf4> show bgp summary

Warning: License key missing; requires 'BGP' license

Threading mode: BGP I/O
Default eBGP mode: advertise - accept, receive - accept
Groups: 2 Peers: 4 Down peers: 0
Auto-discovered peers: 2
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0
                      10          8          0          0          0          0
bgp.evpn.0
                       6          3          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
10.255.0.101          65000        131        106       0       0       46:21 Establ
  bgp.evpn.0: 3/3/3/0
  EVPN100.evpn.0: 3/3/3/0
  __default_evpn__.evpn.0: 0/0/0/0
10.255.0.102          65000        130        105       0       0       46:21 Establ
  bgp.evpn.0: 0/3/3/0
  EVPN100.evpn.0: 0/3/3/0
  __default_evpn__.evpn.0: 0/0/0/0
fe80::a8c1:abff:feb3:16c2%et-0/0/0.0       65101        118        105       0       0       46:46 Establ
  inet.0: 4/5/5/0
fe80::a8c1:abff:fee6:58af%et-0/0/1.0       65102        119        105       0       0       46:46 Establ
  inet.0: 4/5/5/0

admin@leaf4>

EVPNインスタンス EVPN100 が VLAN 100 / VNI 10100 に紐づいた VXLAN として動作しており、leaf4 の VTEP アドレスは 10.255.0.4 であることが確認できます。また、他LeafのVTEPを neighbor として認識し、Remote MAC を学習できていることが分かります。

admin@leaf4> show evpn instance EVPN100 extensive
Instance: EVPN100
  Route Distinguisher: 10.255.0.4:10100
  VLAN ID: 100
  Encapsulation type: VXLAN
  Duplicate MAC detection threshold: 5
  Duplicate MAC detection window: 180
  MAC database status                     Local  Remote
    MAC advertisements:                       1       3
    MAC+IP advertisements:                    1       1
    Default gateway MAC advertisements:       0       0
  Number of local interfaces: 2 (2 up)
    Interface name  ESI                            Mode             Status     AC-Role
    .local..54      00:00:00:00:00:00:00:00:00:00  single-homed     Up         Root
    et-0/0/2.0      00:00:00:00:00:00:00:00:00:00  single-homed     Up         Root
  Number of IRB interfaces: 0 (0 up)
  Number of protect interfaces: 0
  Number of bridge domains: 1
    VLAN  Domain-ID Intfs/up   IRB-intf  Mode            MAC-sync v4-SG-sync v6-SG-sync
    100   10100        1  1              Extended        Enabled  Disabled   Disabled
  Number of neighbors: 3
    Address               MAC    MAC+IP        AD        IM        ES Leaf-label DCI-Peer Flow-label DT2U-SID           DT2M-SID
    10.255.0.1              1         0         0         1         0                           NO
    10.255.0.2              1         0         0         1         0                           NO
    10.255.0.3              1         1         0         1         0                           NO
  Number of ethernet segments: 0
  Router-ID: 10.255.0.4
  Source VTEP interface IP: 10.255.0.4
  SMET Forwarding: Disabled
  RIB Table-ID: 184549384, Kernel Table-ID: 54, Kernel Table-Generation: 0
  EVPN instance flags: 0x80001c000
  RTT Update Timestamp: Jun 27 01:46:59.676 2026
  L2ALD state change Timestamp: Jun 27 01:46:59.727 2026
  Instance Ready Timestamp: NA
  Core-Isolation change TS: Jun 27 01:49:15.185 2026, Core-Isolated: N
  Last Core-Isolation Change Reason: evpn-peer-transition
  Composite Nexthop: Disabled
  Preserve Nexthop Hierarchy: Disabled
  Dynamic List Nexthop: Disabled

admin@leaf4>

leaf4 の MAC テーブルに、ローカルMACと他Leaf配下のリモートMACが登録されており、EVPN-VXLANによるL2延伸が動作していることを確認できます。

admin@leaf4> show mac-vrf forwarding mac-table

MAC flags (S - static MAC, D - dynamic MAC, L - locally learned, P - Persistent static, C - Control MAC
           SE - statistics enabled, NM - non configured MAC, R - remote PE MAC, O - ovsdb MAC,
           B - Blocked MAC)


Ethernet switching table : 4 entries, 4 learned
Routing instance : EVPN100
   Vlan                MAC                 MAC       GBP    Logical                SVLBNH/      Active
   name                address             flags     tag    interface              VENH Index   source
   VLAN100             aa:c1:ab:59:6d:e8   DR               vtep-54.32772                       10.255.0.3
   VLAN100             aa:c1:ab:5f:79:9e   DR               vtep-54.32770                       10.255.0.1
   VLAN100             aa:c1:ab:b5:45:41   DR               vtep-54.32771                       10.255.0.2
   VLAN100             aa:c1:ab:d9:44:66   D                et-0/0/2.0

admin@leaf4>

EVPN route type 2では、各Leaf配下のMACを学習しています。
(長くなるため折りたたみにしています)

show route table EVPN100.evpn.0 match-prefix "2:*"
admin@leaf4> show route table EVPN100.evpn.0 match-prefix "2:*"

EVPN100.evpn.0: 10 destinations, 17 routes (10 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

2:10.255.0.1:2::0::aa:c1:ab:5f:79:9e/304 MAC/IP
                   *[BGP/170] 00:00:06, localpref 100, from 10.255.0.101
                      AS path: I, validation-state: unverified
                       to fe80::a8c1:abff:feb3:16c2 via et-0/0/0.0
                    >  to fe80::a8c1:abff:fee6:58af via et-0/0/1.0
                    [BGP/170] 00:00:06, localpref 100, from 10.255.0.102
                      AS path: I, validation-state: unverified
                       to fe80::a8c1:abff:feb3:16c2 via et-0/0/0.0
                    >  to fe80::a8c1:abff:fee6:58af via et-0/0/1.0
2:10.255.0.2:10100::0::aa:c1:ab:b5:45:41/304 MAC/IP
                   *[BGP/170] 00:00:06, localpref 100, from 10.255.0.101
                      AS path: I, validation-state: unverified
                    >  to fe80::a8c1:abff:feb3:16c2 via et-0/0/0.0
                       to fe80::a8c1:abff:fee6:58af via et-0/0/1.0
                    [BGP/170] 00:00:06, localpref 100, from 10.255.0.102
                      AS path: I, validation-state: unverified
                    >  to fe80::a8c1:abff:feb3:16c2 via et-0/0/0.0
                       to fe80::a8c1:abff:fee6:58af via et-0/0/1.0
2:10.255.0.3:10100::0::aa:c1:ab:59:6d:e8/304 MAC/IP
                   *[BGP/170] 00:00:03, localpref 100, from 10.255.0.101
                      AS path: I, validation-state: unverified
                       to fe80::a8c1:abff:feb3:16c2 via et-0/0/0.0
                    >  to fe80::a8c1:abff:fee6:58af via et-0/0/1.0
                    [BGP/170] 00:00:03, localpref 100, from 10.255.0.102
                      AS path: I, validation-state: unverified
                       to fe80::a8c1:abff:feb3:16c2 via et-0/0/0.0
                    >  to fe80::a8c1:abff:fee6:58af via et-0/0/1.0
2:10.255.0.4:10100::0::aa:c1:ab:d9:44:66/304 MAC/IP
                   *[EVPN/170] 01:01:49
                       Indirect
2:10.255.0.4:10100::0::aa:c1:ab:d9:44:66::192.168.100.4/304 MAC/IP
                   *[EVPN/170] 00:55:49
                       Indirect
2:10.255.0.3:10100::0::aa:c1:ab:59:6d:e8::fe80::a8c1:abff:fe59:6de8/304 MAC/IP
                   *[BGP/170] 00:00:03, localpref 100, from 10.255.0.101
                      AS path: I, validation-state: unverified
                       to fe80::a8c1:abff:feb3:16c2 via et-0/0/0.0
                    >  to fe80::a8c1:abff:fee6:58af via et-0/0/1.0
                    [BGP/170] 00:00:03, localpref 100, from 10.255.0.102
                      AS path: I, validation-state: unverified
                       to fe80::a8c1:abff:feb3:16c2 via et-0/0/0.0
                    >  to fe80::a8c1:abff:fee6:58af via et-0/0/1.0

admin@leaf4>

確認できたこと

今回の構成で、以下を確認できました。

  • 2 Spine / 4 LeafのClosをContainerlabで構築できた
  • Leaf-Spine間をBGP Unnumberedで構築できた
  • EVPN peerをLoopback間で張れた
  • VXLANでVLAN 100 / VNI 10100を延伸できた
  • VyOS / Arista / SONiC / Juniperのマルチベンダー構成でL2延伸できた
  • 各Leafでremote MACをEVPN/VXLAN側に学習していることを確認できた
  • client間で同一L2セグメントとして疎通できた

ハマったところ

ここからは、今回ハマったところを最後にまとめます。

SONiC VSではNHTに注意

SONiC VSでは、Leaf-Spine間のBGP Unnumbered接続において、FRRのNexthop Trackingがmanagement/default route側を参照してしまい、BGP peerが確立しない場合がありました。

今回は、以下の設定でdefault route経由のNexthop Trackingを無効化しました。

no ip nht resolve-via-default
no ipv6 nht resolve-via-default

この設定により、management/default route側で誤って到達性が解決される状態を回避し、UnderlayのBGP Unnumbered接続が改善しました。

Juniperではtunnel terminationを忘れない

Juniper cJunosEvolvedでは、EVPNが張れていてもVXLAN data planeが通らないことがありました。

今回必要だったのは以下です。

set forwarding-options tunnel-termination

この設定がないと、EVPNのcontrol planeは正常に見えても、VXLANを終端できずにclient間疎通が通りませんでした。

EVPN-VXLANでは、BGP EVPNが張れていることと、実際にVXLANパケットを終端できることは別です。
control planeだけを見ると問題なさそうに見えても、data plane側でVXLANを受けられないとclient間のL2疎通は通りません。

まとめ

Containerlabで、BGP Unnumbered + EVPN-VXLANによるマルチベンダーClosを構築しました。

Physical : 2 Spine / 4 Leaf Clos
Underlay : BGP Unnumbered
Overlay  : BGP EVPN
DataPlane: VXLAN
Service  : VLAN 100 / VNI 10100
Vendor   : VyOS / Arista cEOS / SONiC / Juniper cJunosEvolved

BGP Unnumbered は、装置間のリンクアドレスを管理する必要がなくなるので便利。

マルチベンダー構成では、設定コマンドや確認コマンドがベンダーごとに異なりますが、なんとかつながりました。

特にSONiCには手こずりましたが、Codexにcontainerlabで起動したSONiCの状態を直接調べてもらい、改善することができました。Codexめちゃ便利。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?