kakkotetsu

vQFX10000 で VXLAN+EVPN (Multihoming 編) (original : 2017/02/28)

この記事は某所で 2017/02/28 に書いたもののコピーです。
そのため 2017/05/13 時点ではやや古い情報も含まれています。

  • 201705GNS3 ver2.0 stable が出たので
    • KVM 間のパケットキャプチャ用に GNS3 のハブを挟む必要がなくなった
    • Docker インスタンスで vlan tag を扱えるようになり、Open vSwitch を Docker で簡単に並べられるようになった

.

最初に

本項でやること

以下をやります。

  • 先日「vQFX10000 で VXLAN+EVPN (L2 over L3 編)」で動かした構成を冗長化する
    • RFC7432(BGP MPLS-Based Ethernet VPN)に書かれた Multihoming を動かして様子を見る
      • 構成図でいう spine 群(VTEP と EVI の役割を担う)の下側
      • これがメイン
    • マルチパスBGPもついでに組んでおく
      • 構成図でいう spine 群(VTEP と EVI の役割を担う)の上側
      • 単にマルチパスなBGP構成にしただけで、サラリと流す
      • ここ数年、あちこちのデータセンタ事業者とかメーカとかが IP CLOS Network として提示しているアレ

個人的には、2014/12 時点で物理スイッチでの VXLAN 実装を確認した時 (VyOS と Arista で VXLAN 相互接続)に、VTEPの冗長化手法が分からなかった(配下のノードで bonding なり VRRP なりで制御せざるを得ないと考えていた)ので、それを標準化技術で実現する手法として期待を持っていたりします。

概要構成図 / 構成簡易解説 / 環境情報

下図のようなものを作っていきます。

f:id:kakkotetsu:20170513140423p:plain

コンポーネントの役割は、前回と変わらず以下の感じ。

  • bb0[12]
    • DataPlane としては VTEP (spine[12]{2})間の VXLAN パケットをフォワードするのみ
    • ControlPlane としては MP-BGP(EVPNシグナリング用) の RouteReflector として、EVPN NLRI経路を reflect するのみ
  • spien[12]{2}
    • DataPlane としては VTEP 動作
    • ControlPlane としては EVPN の PE 動作
  • torSW[12]01a
    • VLAN tag 処理をする単純なL2SW

冗長化の方式としては、構成図の下線で書いた通りで、以下の感じ。

  • bb0[12] - spien[12]{2}
    • Underlay の eBGP では PerPacket の ECMP を動かす
    • Overlay の iBGP では bb0[12] が RouteReflector となる 1 クラスタにする
  • spine[12]{2} - torSW[12]01a
    • spine[12]{2} は 2台1組で torSW[12]01a に対して LAG を組む
      • spine1[12]torSW101a
      • spine2[12]torSW201a
    • spine[12]{2} の EVPN 動作としては
      • その LAG を EthernetSegment(ES) として扱う
      • その LAG に EVPN 世界内で一意になるように EthernetSegmentID(ESI) を付与して識別する
        • 今回の構成例だと、spine1[12]ae0spine2[12]ae0 が重複してはいけない
      • ESI を EVPN NLRI Type4(Ethernet Segment route) で広告しあうことで、相互に誰とLAGを組んでいるかを識別したり・誰が各 ES の Designated Forwarder(DF)になるかの Election をしたりできる
        • だから MLAG や MC-LAG や vPC (何か標準的な用語あるんすかね...?)で用意するような InterLink は不要
          • 実装によっては学習している MAC アドレスを InterLink で同期したりするけれど、EVPN では NLRI Type2(MAC/IP Advertisement route)で経路交換するので不要
      • 各 LAG で DF になっている PE だけが EVPN/VXLAN 側(=図中の上側)から来た BUM トラフィックを VLAN 側(=図中の下側)にフォワードする
    • torSW[12]01a
      • 対向が2台いるとか Multihoming してるとか一切気にする必要なく、単に LACP で LAG 組めば OK

そんなわけで、今までは VLAN Tag の処理だけしていれば良かった torSW[12]01a に新たに「LACP を使えること」という要件が出てきたので、今回は GNS3 の EthernetSwitch ではなく Open vSwitch を使います。

環境情報は最初から変わらずです。
今回新たに登場した torSW[12]01a は(詳細は後述しますが)、 Ubuntu16.04.1-server-amd64 + ovs_version: "2.5.0" です。

参考資料

構築~動作確認

GNS3 でデプロイ

前回の環境を引き続き使っていますが、ポチポチとvQFX のデプロイと、Open vSwitch を動かす Ubuntu のデプロイをしていきます。
以下の感じで。

f:id:kakkotetsu:20170513140925p:plain

例によって、GNS3 のバージョンは 1.5.2 を使っているので、パケットキャプチャ用に EthernetSwitch(図中の cap ではじまるやつら) を挟んでますよ。

余談。
最初、Open vSwitch は手軽に docker で動かしたんですよ。(以下、参考リンク)

そうしたら VLAN trunk port で VLAN tag が取り除かれて出てきたんですよ。つーわけで docker OVS は止め。諦めて各々の OVS 用に Ubuntu 仮想マシンを立てることにしましたとさ。
詳細は以下のリンク先を参照ください。例によって GNS 2.0 では、docker でもちゃんと VLAN tag 取り除かずに動くようになっていました(2017/05 確認済)。

torSW[12]01a (Open vSwitch) 設定

Open vSwitch の導入なんかは、適当に公式ドキュメントを見て進めて頂くとして。(雑) 以下のような設定で。このスイッチは LACP と VLAN が動けばなんでもよいので、適当に各々が使いやすいやつを入れればよいかと。

  • torSW[12]01a 共通
# ovs-vsctl --no-wait init
# ovs-vsctl add-br br0
# ovs-vsctl set bridge br0 datapath_type=netdev

# ovs-vsctl add-bond br0 bond0 ens4 ens5 lacp=active bond_mode=balance-slb other_config:lacp-time=fast
# ovs-vsctl add-port br0 ens6 tag=100
# ovs-vsctl add-port br0 ens7 tag=200
# ip link set dev br0 up
# ip link set dev ens4 up
# ip link set dev ens5 up
# ip link set dev ens6 up
# ip link set dev ens7 up

# ovs-vsctl show
79e38752-1ada-4e44-9da2-f457504b149a
    Bridge "br0"
        Port "ens7"
            tag: 200
            Interface "ens7"
        Port "bond0"
            Interface "ens5"
            Interface "ens4"
        Port "ens6"
            tag: 100
            Interface "ens6"
        Port "br0"
            Interface "br0"
                type: internal
    ovs_version: "2.5.0"

# ovs-vsctl list port bond0
_uuid               : 8e767f1a-6a08-411f-9b86-407922a7565c
bond_active_slave   : "00:37:c4:9e:d1:01"
bond_downdelay      : 0
bond_fake_iface     : false
bond_mode           : balance-slb
bond_updelay        : 0
external_ids        : {}
fake_bridge         : false
interfaces          : [470f05cf-c3db-423d-abd5-4a6c45c9a581, 97fb2fa2-5074-455a-8b58-04ec746ea0a6]
lacp                : active
mac                 : []
name                : "bond0"
other_config        : {lacp-time=fast}
qos                 : []
rstp_statistics     : {}
rstp_status         : {}
statistics          : {}
status              : {}
tag                 : []
trunks              : []
vlan_mode           : []

以下出力は spine1[12] の設定とかも終わった後で LAG が組めている状態のものですが...。

root@torSW101a:~# ovs-appctl bond/show bond0
---- bond0 ----
bond_mode: balance-slb
bond may use recirculation: no, Recirc-ID : -1
bond-hash-basis: 0
updelay: 0 ms
downdelay: 0 ms
next rebalance: 7123 ms
lacp_status: negotiated
active slave mac: 00:37:c4:9e:d1:01(ens4)

slave ens4: enabled
        active slave
        may_enable: true

slave ens5: enabled
        may_enable: true


root@torSW101a:~# ovs-appctl lacp/show bond0
---- bond0 ----
        status: active negotiated
        sys_id: 00:37:c4:9e:d1:01
        sys_priority: 65534
        aggregation key: 1
        lacp_time: fast

slave: ens4: current attached
        port_id: 2
        port_priority: 65535
        may_enable: true

        actor sys_id: 00:37:c4:9e:d1:01
        actor sys_priority: 65534
        actor port_id: 2
        actor port_priority: 65535
        actor key: 1
        actor state: activity timeout aggregation synchronized collecting distributing

        partner sys_id: 00:00:00:01:01:01
        partner sys_priority: 127
        partner port_id: 1
        partner port_priority: 127
        partner key: 1
        partner state: activity timeout aggregation synchronized collecting distributing

slave: ens5: current attached
        port_id: 1
        port_priority: 65535
        may_enable: true

        actor sys_id: 00:37:c4:9e:d1:01
        actor sys_priority: 65534
        actor port_id: 1
        actor port_priority: 65535
        actor key: 1
        actor state: activity timeout aggregation synchronized collecting distributing

        partner sys_id: 00:00:00:01:01:01
        partner sys_priority: 127
        partner port_id: 1
        partner port_priority: 127
        partner key: 1
        partner state: activity timeout aggregation synchronized collecting distributing

疎通確認用 node 設定

今まで通りなのですが、適当に node 群を用意しておきます。疎通確認にしか使わないので、何を使ってもいいです。

  • node11
    • spine1[12] 配下 VLAN 100
kotetsu@node11:~$ ip a show dev ens4
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:37:c4:e2:60:01 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.1/24 brd 192.168.1.255 scope global ens4
       valid_lft forever preferred_lft forever
    inet6 fe80::237:c4ff:fee2:6001/64 scope link
       valid_lft forever preferred_lft forever
  • node21
    • spine2[12] 配下 VLAN 100
kotetsu@node21:~$ ip a show dev ens4
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:37:c4:46:d8:01 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.2/24 brd 192.168.1.255 scope global ens4
       valid_lft forever preferred_lft forever
    inet6 fe80::237:c4ff:fe46:d801/64 scope link
       valid_lft forever preferred_lft forever
  • node12
    • spine1[12] 配下 VLAN 200
kotetsu@node12:~$ ip a show dev ens4
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:37:c4:9c:dd:01 brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.1/24 brd 192.168.2.255 scope global ens4
       valid_lft forever preferred_lft forever
    inet6 fe80::237:c4ff:fe9c:dd01/64 scope link
       valid_lft forever preferred_lft forever
  • node22
    • spine2[12] 配下 VLAN 200
kotetsu@node22:~$ ip a show dev ens4
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:37:c4:3d:e0:01 brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.2/24 brd 192.168.2.255 scope global ens4
       valid_lft forever preferred_lft forever
    inet6 fe80::237:c4ff:fe3d:e001/64 scope link
       valid_lft forever preferred_lft forever

vQFX 設定~確認

まずは Underlay の設定(物理IF~eBGP)を。長くなってしまいますが、下図のような感じで作っていきます。

f:id:kakkotetsu:20170513141043p:plain

Underlay 物理IF設定

vQFX でも RFC3021 Using 31-Bit Prefixes on IPv4 Point-to-Point Links をサポートしているので、使っていくです。

6台分をペタペタ貼っていきますが、まあ物理インターフェース番号やIPアドレスのパラメータが個々に異なるくらい。

  • bb01
set interfaces xe-0/0/0 description "DEV=spine11 IF=xe-0/0/0"
set interfaces xe-0/0/0 mtu 9192
set interfaces xe-0/0/0 unit 0 family inet address 192.0.2.0/31
set interfaces xe-0/0/0 unit 0 family inet mtu 9000

delete interfaces xe-0/0/1 unit 0 family inet dhcp
set interfaces xe-0/0/1 description "DEV=spine12 IF=xe-0/0/0"
set interfaces xe-0/0/1 mtu 9192
set interfaces xe-0/0/1 unit 0 family inet address 192.0.2.2/31
set interfaces xe-0/0/1 unit 0 family inet mtu 9000

delete interfaces xe-0/0/2 unit 0 family inet dhcp
set interfaces xe-0/0/2 description "DEV=spine21 IF=xe-0/0/0"
set interfaces xe-0/0/2 mtu 9192
set interfaces xe-0/0/2 unit 0 family inet address 192.0.2.4/31
set interfaces xe-0/0/2 unit 0 family inet mtu 9000

delete interfaces xe-0/0/3 unit 0 family inet dhcp
set interfaces xe-0/0/3 description "DEV=spine22 IF=xe-0/0/0"
set interfaces xe-0/0/3 mtu 9192
set interfaces xe-0/0/3 unit 0 family inet address 192.0.2.6/31
set interfaces xe-0/0/3 unit 0 family inet mtu 9000

set protocols lldp port-id-subtype interface-name
set protocols lldp interface xe-0/0/0
set protocols lldp interface xe-0/0/1
set protocols lldp interface xe-0/0/2
set protocols lldp interface xe-0/0/3
  • bb02
delete interfaces xe-0/0/0 unit 0 family inet dhcp
set interfaces xe-0/0/0 description "DEV=spine11 IF=xe-0/0/1"
set interfaces xe-0/0/0 mtu 9192
set interfaces xe-0/0/0 unit 0 family inet address 192.0.2.128/31
set interfaces xe-0/0/0 unit 0 family inet mtu 9000

delete interfaces xe-0/0/1 unit 0 family inet dhcp
set interfaces xe-0/0/1 description "DEV=spine12 IF=xe-0/0/1"
set interfaces xe-0/0/1 mtu 9192
set interfaces xe-0/0/1 unit 0 family inet address 192.0.2.130/31
set interfaces xe-0/0/1 unit 0 family inet mtu 9000

delete interfaces xe-0/0/2 unit 0 family inet dhcp
set interfaces xe-0/0/2 description "DEV=spine21 IF=xe-0/0/1"
set interfaces xe-0/0/2 mtu 9192
set interfaces xe-0/0/2 unit 0 family inet address 192.0.2.132/31
set interfaces xe-0/0/2 unit 0 family inet mtu 9000

delete interfaces xe-0/0/3 unit 0 family inet dhcp
set interfaces xe-0/0/3 description "DEV=spine22 IF=xe-0/0/1"
set interfaces xe-0/0/3 mtu 9192
set interfaces xe-0/0/3 unit 0 family inet address 192.0.2.134/31
set interfaces xe-0/0/3 unit 0 family inet mtu 9000

set protocols lldp port-id-subtype interface-name
set protocols lldp interface xe-0/0/0
set protocols lldp interface xe-0/0/1
set protocols lldp interface xe-0/0/2
set protocols lldp interface xe-0/0/3
  • spine11
delete interfaces xe-0/0/0 unit 0 family inet dhcp
set interfaces xe-0/0/0 description "DEV=bb01 IF=xe-0/0/0"
set interfaces xe-0/0/0 mtu 9192
set interfaces xe-0/0/0 unit 0 family inet address 192.0.2.1/31
set interfaces xe-0/0/0 unit 0 family inet mtu 9000

delete interfaces xe-0/0/1 unit 0 family inet dhcp
set interfaces xe-0/0/1 description "DEV=bb02 IF=xe-0/0/0"
set interfaces xe-0/0/1 mtu 9192
set interfaces xe-0/0/1 unit 0 family inet address 192.0.2.129/31
set interfaces xe-0/0/1 unit 0 family inet mtu 9000

delete interfaces xe-0/0/2 unit 0 family inet dhcp
set interfaces xe-0/0/2 description "DEV=torSW101a IF=eth0"

set protocols lldp port-id-subtype interface-name
set protocols lldp interface xe-0/0/0
set protocols lldp interface xe-0/0/1
  • spine12
delete interfaces xe-0/0/0 unit 0 family inet dhcp
set interfaces xe-0/0/0 description "DEV=bb01 IF=xe-0/0/1"
set interfaces xe-0/0/0 mtu 9192
set interfaces xe-0/0/0 unit 0 family inet address 192.0.2.3/31
set interfaces xe-0/0/0 unit 0 family inet mtu 9000

delete interfaces xe-0/0/1 unit 0 family inet dhcp
set interfaces xe-0/0/1 description "DEV=bb02 IF=xe-0/0/1"
set interfaces xe-0/0/1 mtu 9192
set interfaces xe-0/0/1 unit 0 family inet address 192.0.2.131/31
set interfaces xe-0/0/1 unit 0 family inet mtu 9000

delete interfaces xe-0/0/2 unit 0 family inet dhcp
set interfaces xe-0/0/2 description "DEV=torSW101a IF=eth1"

set protocols lldp port-id-subtype interface-name
set protocols lldp interface xe-0/0/0
set protocols lldp interface xe-0/0/1
  • spine21
delete interfaces xe-0/0/0 unit 0 family inet dhcp
set interfaces xe-0/0/0 description "DEV=bb01 IF=xe-0/0/2"
set interfaces xe-0/0/0 mtu 9192
set interfaces xe-0/0/0 unit 0 family inet address 192.0.2.5/31
set interfaces xe-0/0/0 unit 0 family inet mtu 9000

delete interfaces xe-0/0/1 unit 0 family inet dhcp
set interfaces xe-0/0/1 description "DEV=bb02 IF=xe-0/0/2"
set interfaces xe-0/0/1 mtu 9192
set interfaces xe-0/0/1 unit 0 family inet address 192.0.2.133/31
set interfaces xe-0/0/1 unit 0 family inet mtu 9000

delete interfaces xe-0/0/2 unit 0 family inet dhcp
set interfaces xe-0/0/2 description "DEV=torSW201a IF=eth0"

set protocols lldp port-id-subtype interface-name
set protocols lldp interface xe-0/0/0
set protocols lldp interface xe-0/0/1
  • spine22
delete interfaces xe-0/0/0 unit 0 family inet dhcp
set interfaces xe-0/0/0 description "DEV=bb01 IF=xe-0/0/3"
set interfaces xe-0/0/0 mtu 9192
set interfaces xe-0/0/0 unit 0 family inet address 192.0.2.7/31
set interfaces xe-0/0/0 unit 0 family inet mtu 9000

delete interfaces xe-0/0/1 unit 0 family inet dhcp
set interfaces xe-0/0/1 description "DEV=bb02 IF=xe-0/0/3"
set interfaces xe-0/0/1 mtu 9192
set interfaces xe-0/0/1 unit 0 family inet address 192.0.2.135/31
set interfaces xe-0/0/1 unit 0 family inet mtu 9000

delete interfaces xe-0/0/2 unit 0 family inet dhcp
set interfaces xe-0/0/2 description "DEV=torSW201a IF=eth1"

set protocols lldp port-id-subtype interface-name
set protocols lldp interface xe-0/0/0
set protocols lldp interface xe-0/0/1

Underlay eBGP 設定~簡易動作確認

これを設定すれば eBGP で各々の lo0 IPアドレスを相互学習できるようになる筈。

全台共通設定

ここでは6台の vQFX 全台共通の設定を。

ともあれまずは eBGP を動かします。

set protocols bgp group BGP_UNDERLAY type external
set protocols bgp group BGP_UNDERLAY mtu-discovery

広告対象は自身の lo0 のみとします。共通のポリシを全台で流用しました。この辺は今まで通りです。

set policy-options policy-statement POLICY_EXPORT_LO0 from family inet
set policy-options policy-statement POLICY_EXPORT_LO0 from protocol direct
set policy-options policy-statement POLICY_EXPORT_LO0 from route-filter 0.0.0.0/0 prefix-length-range /32-/32
set policy-options policy-statement POLICY_EXPORT_LO0 then accept

set protocols bgp group BGP_UNDERLAY export POLICY_EXPORT_LO0

このあたりは Underlay 設計にもよるのですが...。
今回は IGP を一切使わずに、eBGP のみで組んでいます。(今回のような環境を作るのに、モノの本には IGP が推奨されていたりもしますが。)
また、2台をペアとして同じ AS に所属させています。(6台を各々別 AS に所属させる選択肢もあって、システムの拡張性と利用可能な AS 番号の数、2byte ASN か 4byte ASN か...など考慮して、選択すればよいのでは。)
なので、spine 4 台の lo0 同士でフルメッシュに到達性を持たせるためには、以下を実現する必要があります。

  • AS 65000bb0[12] は、AS 65001spine11 から受信した経路(spine11lo0 IP アドレス)を、AS 65001spine12 に広告する必要がある
    • AS 65002 から来る経路に関しても同様
  • AS 65001spine11 は、AS PATH が 65000 65001 となる spine12 への経路を学習しないといけない

というわけで、以下の設定を入れておきます。

set protocols bgp group BGP_UNDERLAY advertise-peer-as
set protocols bgp group BGP_UNDERLAY family inet unicast loops 2

今回冗長化しますので spine 同士の通信が Per Packet で ECMP されるポリシを適用して、マルチパスを動かします。
VXLANカプセル化したパケットの通信は全て SrcIP も DstIP も spine (の lo0)の通信になるわけで、spine[12]{2} にさえ入れておけば良い設定の筈ですが。

set policy-options policy-statement POLICY_ECMP then load-balance per-packet

set routing-options forwarding-table export POLICY_ECMP
set routing-options forwarding-table ecmp-fast-reroute

set protocols bgp group BGP_UNDERLAY multipath

折角だから BFD も動かしてみようと欲張ったのですが、別に必須ではないし環境が弱いと邪魔になりかねないので、お好みでどうぞ。

set protocols bgp group BGP_UNDERLAY bfd-liveness-detection minimum-interval 350
set protocols bgp group BGP_UNDERLAY bfd-liveness-detection multiplier 3
set protocols bgp group BGP_UNDERLAY bfd-liveness-detection session-mode automatic

ログファイルを /var/log/bgp.log に仕分けたりの細々した設定なのでお好みでどうぞ。

set protocols bgp traceoptions file bgp.log
set protocols bgp traceoptions file size 10k
set protocols bgp traceoptions file files 30
set protocols bgp traceoptions flag normal
set protocols bgp log-updown

仮想環境でどんだけ意味があるかっつーと...ですけど、あーコマンドは入るのねーくらいの感じで投入しただけです。まー今回の箱庭検証では不要でしょう。

set protocols bgp graceful-restart

個別設定

ここから先は個別パラメータの設定です。
lo0IPアドレス、AS番号、neighbor 設定くらいすね。

  • bb01
set interfaces lo0 unit 0 family inet address 172.31.0.1/32

set routing-options router-id 172.31.0.1
set routing-options autonomous-system 65000

set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.1 description spine11
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.1 peer-as 65001
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.3 description spine12
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.3 peer-as 65001
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.5 description spine21
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.5 peer-as 65002
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.7 description spine22
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.7 peer-as 65002
  • bb02
set interfaces lo0 unit 0 family inet address 172.31.0.2/32

set routing-options router-id 172.31.0.2
set routing-options autonomous-system 65000

set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.129 description spine11
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.129 peer-as 65001
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.131 description spine12
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.131 peer-as 65001
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.133 description spine21
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.133 peer-as 65002
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.135 description spine22
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.135 peer-as 65002
  • spine11
set interfaces lo0 unit 0 family inet address 172.16.1.1/32

set routing-options router-id 172.16.1.1
set routing-options autonomous-system 65001

set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.0 description bb01
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.0 peer-as 65000
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.128 description bb02
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.128 peer-as 65000
  • spine12
set interfaces lo0 unit 0 family inet address 172.16.1.2/32

set routing-options router-id 172.16.1.2
set routing-options autonomous-system 65001

set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.2 description bb01
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.2 peer-as 65000
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.130 description bb02
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.130 peer-as 65000
  • spine21
set interfaces lo0 unit 0 family inet address 172.16.2.1/32

set routing-options router-id 172.16.2.1
set routing-options autonomous-system 65002

set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.4 description bb01
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.4 peer-as 65000
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.132 description bb02
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.132 peer-as 65000
  • spine22
set interfaces lo0 unit 0 family inet address 172.16.2.2/32

set routing-options router-id 172.16.2.2
set routing-options autonomous-system 65002

set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.6 description bb01
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.6 peer-as 65000
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.134 description bb02
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.134 peer-as 65000

Underlay eBGP ECMP 動作確認

これで BGP ステータスやテーブルを確認・フルメッシュでの lo0 間疎通ができるようになります。

では ECMP の挙動を軽く確認しておきます。
例えば spine11spine21 は互いに相手の lo0 への経路を 2 パス(bb01 経由と bb02 経由)持っています。

{master:0}
kotetsu@spine11> show route 172.16.2.1

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

172.16.2.1/32      *[BGP/170] 00:20:02, localpref 100
                      AS path: 65000 65002 I, validation-state: unverified
                      to 192.0.2.0 via xe-0/0/0.0
                    > to 192.0.2.128 via xe-0/0/1.0
                    [BGP/170] 00:02:45, localpref 100
                      AS path: 65000 65002 I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
{master:0}
kotetsu@spine21> show route 172.16.1.1

inet.0: 14 destinations, 19 routes (14 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

172.16.1.1/32      *[BGP/170] 00:19:54, localpref 100
                      AS path: 65000 65001 I, validation-state: unverified
                      to 192.0.2.4 via xe-0/0/0.0
                    > to 192.0.2.132 via xe-0/0/1.0
                    [BGP/170] 00:03:23, localpref 100
                      AS path: 65000 65001 I, validation-state: unverified
                    > to 192.0.2.4 via xe-0/0/0.0

ここで spine11 から spine21 に対して(双方 lo0) ping を実行しつつ

{master:0}
kotetsu@spine11> ping source 172.16.1.1 172.16.2.1
PING 172.16.2.1 (172.16.2.1): 56 data bytes
64 bytes from 172.16.2.1: icmp_seq=0 ttl=63 time=28.369 ms
64 bytes from 172.16.2.1: icmp_seq=1 ttl=63 time=37.308 ms

...

--- 172.16.2.1 ping statistics ---
21 packets transmitted, 21 packets received, 0% packet loss
round-trip min/avg/max/stddev = 18.653/29.917/45.982/7.670 ms

spine11spine21 から bb01bb02 へのリンクをパケットキャプチャすると、分散していることが分かります。

あと一応、AS65001 に所属している spine12 へのパスが AS65001 に所属している spine11 で AS-PATH 65000 65001 で学習できていることも確認しておきます。
各 spine の unicast loops 設定と、各 bb の advertise-peer-as 設定が働いて、狙い通り学習できています。

{master:0}
kotetsu@spine11> show route 172.16.1.2

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

172.16.1.2/32      *[BGP/170] 00:29:19, localpref 100
                      AS path: 65000 65001 I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
                    [BGP/170] 00:29:15, localpref 100
                      AS path: 65000 65001 I, validation-state: unverified
                    > to 192.0.2.128 via xe-0/0/1.0

Overlay 設定(MP-BGP)

Underlay eBGP で経路交換した各 lo0 同士で iBGP を組みます。
これで EVPN NLRI をやりとりする MP-BGP が組める筈。
設定は長々となってしまいますが、絵にすると単純で以下のような感じです。

f:id:kakkotetsu:20170513141154p:plain

全台共通設定

前回と同様の設定です。

set protocols bgp group BGP_OVERLAY type internal
set protocols bgp group BGP_OVERLAY family evpn signaling
set protocols bgp group BGP_OVERLAY local-as 64512

個別設定

bb0[12] が共に RouteReflector になる構成をとるので、同じクラスタIDを設定します。
場合によっては RouteReflector 使わずにフルメッシュにするなり、お好きなようにどうぞ。(なんか、今回こればっかり言ってる気がする...。)

  • bb01
set protocols bgp group BGP_OVERLAY local-address 172.31.0.1

set protocols bgp group BGP_OVERLAY cluster 172.31.0.0

set protocols bgp group BGP_OVERLAY neighbor 172.16.1.1 description spine11
set protocols bgp group BGP_OVERLAY neighbor 172.16.1.2 description spine12
set protocols bgp group BGP_OVERLAY neighbor 172.16.2.1 description spine21
set protocols bgp group BGP_OVERLAY neighbor 172.16.2.2 description spine22
  • bb02
set protocols bgp group BGP_OVERLAY local-address 172.31.0.2

set protocols bgp group BGP_OVERLAY cluster 172.31.0.0

set protocols bgp group BGP_OVERLAY neighbor 172.16.1.1 description spine11
set protocols bgp group BGP_OVERLAY neighbor 172.16.1.2 description spine12
set protocols bgp group BGP_OVERLAY neighbor 172.16.2.1 description spine21
set protocols bgp group BGP_OVERLAY neighbor 172.16.2.2 description spine22
  • spine11
set protocols bgp group BGP_OVERLAY local-address 172.16.1.1

set protocols bgp group BGP_OVERLAY neighbor 172.31.0.1 description bb01
set protocols bgp group BGP_OVERLAY neighbor 172.31.0.2 description bb02
  • spine12
set protocols bgp group BGP_OVERLAY local-address 172.16.1.2

set protocols bgp group BGP_OVERLAY neighbor 172.31.0.1 description bb01
set protocols bgp group BGP_OVERLAY neighbor 172.31.0.2 description bb02
  • spine21
set protocols bgp group BGP_OVERLAY local-address 172.16.2.1

set protocols bgp group BGP_OVERLAY neighbor 172.31.0.1 description bb01
set protocols bgp group BGP_OVERLAY neighbor 172.31.0.2 description bb02
  • spine22
set protocols bgp group BGP_OVERLAY local-address 172.16.2.2

set protocols bgp group BGP_OVERLAY neighbor 172.31.0.1 description bb01
set protocols bgp group BGP_OVERLAY neighbor 172.31.0.2 description bb02

Overlay設定~確認(EVPN+VXLAN)

EVPN の設定と、その Dataplane として使う VXLAN 周りの設定をしていきます。前回のシングル構成版と全く一緒です。
bb0[12] はこの辺の挙動に関しては土管に徹しているので登場しません。

spine[12]{2} 4台共通設定

set vlans VLAN0100 vlan-id 100
set vlans VLAN0100 vxlan vni 10100

set vlans VLAN0200 vlan-id 200
set vlans VLAN0200 vxlan vni 10200

set protocols evpn encapsulation vxlan
set protocols evpn extended-vni-list all
set protocols evpn multicast-mode ingress-replication
set protocols evpn vni-options vni 10100 vrf-target export target:1:10100
set protocols evpn vni-options vni 10200 vrf-target export target:1:10200

set policy-options community COM_10100 members target:1:10100
set policy-options community COM_10200 members target:1:10200
set policy-options community COM_LEAF_ESI members target:9999:9999

set policy-options policy-statement POLICY_VRF_IMPORT term T_10100 from community COM_10100
set policy-options policy-statement POLICY_VRF_IMPORT term T_10100 then accept
set policy-options policy-statement POLICY_VRF_IMPORT term T_10200 from community COM_10200
set policy-options policy-statement POLICY_VRF_IMPORT term T_10200 then accept
set policy-options policy-statement POLICY_VRF_IMPORT term T_99900 from community COM_LEAF_ESI
set policy-options policy-statement POLICY_VRF_IMPORT term T_99900 then accept
set policy-options policy-statement POLICY_VRF_IMPORT term T_99999 then reject

set switch-options vtep-source-interface lo0.0
set switch-options vrf-import POLICY_VRF_IMPORT
set switch-options vrf-target target:9999:9999
set switch-options vrf-target auto

個別設定

つっても RD だけですね。

  • spine11
set switch-options route-distinguisher 64512:11
  • spine12
set switch-options route-distinguisher 64512:12
  • spine21
set switch-options route-distinguisher 64512:21
  • spine22
set switch-options route-distinguisher 64512:22

EVPN Multihoming 設定

ようやく本題ですね!(息切れ)

spine1[12]torSW101a に、spine2[12]torSW201a に、それぞれペアで ae0 を提供し、それを EVPN 的には Ethernet Segmeent(ES) として扱い、その識別子として Ethernet Segment Identifier(ESI) を付与します。

spine[12]{2} 4台共通設定

まずは普通の AE 設定です。

  • ethernet device-count を 448 なんて値にしているのは、単に ? で出てきたヘルプに書いてあった最大値を入れただけ。足りないより良かろうガハハ!くらいのノリです。
  • torSW[12]01a 向けの物理インターフェース(4台共に xe-0/0/2)を ae0 に所属させ
  • ae0vlan trunk で(自身の DB にある)全 VLAN 食うようにしておき
  • LACP は
    • default の interval fast (1s間隔)で良いので特に設定せず
    • spine[12]{2} の別筐体にまたがる LAG を torSW[12]01a 側では同じものと見做せる必要があるので、各ペアで同じ system-id を付与
      • それぞれ 3 台(spine 2 台と torSW 1 台)で閉じる部分だし、spine[12]{2} で同じ値を使ってしまっているが、本来は一意になるようにしておいた方が無難かと
    • system-priority 値はデフォルトの 127 のまま
  • EVPN Multihoming Mode としては active-active を使う
set chassis aggregated-devices ethernet device-count 448

set interfaces xe-0/0/2 ether-options 802.3ad ae0
delete interfaces xe-0/0/2 unit 0

set interfaces ae0 unit 0 family ethernet-switching interface-mode trunk
set interfaces ae0 unit 0 family ethernet-switching vlan members all

set interfaces ae0 aggregated-ether-options lacp active
set interfaces ae0 aggregated-ether-options lacp system-id 00:00:00:01:01:01

set interfaces ae0 esi all-active

個別設定

ペア単位で個別な設定を見ていきましょうか。って、ESI だけですが。

2017/02/26 時点で Juniper公式 / Supported EVPN Standardsを見ると

RFC 7432, BGP MPLS-Based Ethernet VPN The following features are not supported: - Automatic derivation of Ethernet segment (ES) values. Only static ES configurations are supported.

となっていますので、巧いこと EVPN の世界で一意になるように手動で付与してやりましょう。

RFC74322 / Ethernet Segment あたりを参照して、1octet 目は ESI Type0x00 とし、あとは適当に。
今回は 9octet 目で spine のペアを、10octet 目で ae 番号を、それぞれ識別できるように付与しました。

  • spine1[12]
set interfaces ae0 esi 00:01:01:01:01:01:01:01:01:00
  • spine2[12]
set interfaces ae0 esi 00:01:01:01:01:01:01:01:02:00

ちなみにですが、自分の環境起因か手順の不備か仕様か分かりませんが、この ESI 値を変更した時、古い ESI が(巧いこと WithDrawn されなかったのかも知れないですが)残ってしまうことがありました。
spine1[12] ae0 用の ESI を変更したら、spine2[12] 側に新旧両方の経路が残ってしまったんですよね。
何でかは追ってません。もし、そんな状況が再現できた & 原因が分かったりしたら & それが公開可能な情報なら、教えてください。

動作確認

node間の疎通確認

node11node21$ sudo ip n flush dev ens4 して node11 から ping 192.168.1.2 で L2 over L3 通信できることを確認できます。

kotetsu@node11:~$ ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=181 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=61.4 ms
64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=35.1 ms
64 bytes from 192.168.1.2: icmp_seq=4 ttl=64 time=42.7 ms
64 bytes from 192.168.1.2: icmp_seq=5 ttl=64 time=53.8 ms
64 bytes from 192.168.1.2: icmp_seq=6 ttl=64 time=78.2 ms
64 bytes from 192.168.1.2: icmp_seq=7 ttl=64 time=33.6 ms
64 bytes from 192.168.1.2: icmp_seq=8 ttl=64 time=35.1 ms
64 bytes from 192.168.1.2: icmp_seq=9 ttl=64 time=33.4 ms
64 bytes from 192.168.1.2: icmp_seq=10 ttl=64 time=61.7 ms
^C
--- 192.168.1.2 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9013ms
rtt min/avg/max/mdev = 33.471/61.687/181.628/42.518 ms

ここで気になったのは EVPN Multihoming の aliasing 動作に沿うならば、Request パケットは spine21 宛と spine22 宛にロードバランスされて、Reply パケットは spine11spine12 にロードバランスされる、って動きになる筈なんですが、そうはならなかった(どちらもその時点での Type2 のみに従って、寄っていた)です。
何らかの環境起因(サポートされないHW or SW)なのか、設定不足なのか...。何かわかったら追記しておきます(2017/02/27)。

vQFX のテーブル確認

EVPN Multihoming の Designated Forwarder 状態

spine1[12] で組んでいる ae0 ESI= 00:01:01:01:01:01:01:01:01:00 においては 172.16.1.1 = spine11 が DF として選出されていることが見えます。
一方で、自身が関与していない spine2[12] で組んでいる ae0 ESI= 00:01:01:01:01:01:01:01:02:00 においては No local attachment to ethernet segment として何も情報出さないようです。

{master:0}
kotetsu@spine11> show evpn instance designated-forwarder
Instance: default-switch
  Number of ethernet segments: 2
    ESI: 00:01:01:01:01:01:01:01:01:00
      Designated forwarder: 172.16.1.1
    ESI: 00:01:01:01:01:01:01:01:02:00
      Designated forwarder: No local attachment to ethernet segment
{master:0}
kotetsu@spine12> show evpn instance designated-forwarder
Instance: default-switch
  Number of ethernet segments: 2
    ESI: 00:01:01:01:01:01:01:01:01:00
      Designated forwarder: 172.16.1.1
    ESI: 00:01:01:01:01:01:01:01:02:00
      Designated forwarder: No local attachment to ethernet segment

spine2[12] で組んでいる ae0 ESI= 00:01:01:01:01:01:01:01:02:00 においては 172.16.2.1 = spine21 が DF として選出されていることが見えます。
一方で、自身が関与していない spine1[12] で組んでいる ae0 ESI= 00:01:01:01:01:01:01:01:01:00 においては No local attachment to ethernet segment として何も情報出さないようです。

{master:0}
kotetsu@spine21> show evpn instance designated-forwarder
Instance: default-switch
  Number of ethernet segments: 2
    ESI: 00:01:01:01:01:01:01:01:01:00
      Designated forwarder: No local attachment to ethernet segment
    ESI: 00:01:01:01:01:01:01:01:02:00
      Designated forwarder: 172.16.2.1
kotetsu@spine22> show evpn instance designated-forwarder
Instance: default-switch
  Number of ethernet segments: 2
    ESI: 00:01:01:01:01:01:01:01:01:00
      Designated forwarder: No local attachment to ethernet segment
    ESI: 00:01:01:01:01:01:01:01:02:00
      Designated forwarder: 172.16.2.1

なお、選出の流れは Juniper公式 / Designated Forwarder Election あたりに書いてあります。
本環境では単純にIPアドレスが小さいやつがそれぞれ DF に選出されたっぽいです。

以下のコマンドで、下の方 Number of ethernet segments でやや詳しい情報が見られるようです。

{master:0}
kotetsu@spine11> show evpn instance extensive
Instance: __default_evpn__
  Route Distinguisher: 172.16.1.1:0
  Number of bridge domains: 0
  Number of neighbors: 1
    172.16.1.2
      Received routes
        Ethernet Segment:                       1

Instance: default-switch
  Route Distinguisher: 64512:11
  Encapsulation type: VXLAN
  MAC database status                     Local  Remote
    MAC advertisements:                       1       1
    MAC+IP advertisements:                    0       0
    Default gateway MAC advertisements:       0       0
  Number of local interfaces: 1 (1 up)
    Interface name  ESI                            Mode             Status
    ae0.0           00:01:01:01:01:01:01:01:01:00  all-active       Up
  Number of IRB interfaces: 0 (0 up)
  Number of bridge domains: 3
    VLAN  VNI    Intfs / up    IRB intf   Mode             MAC sync  IM route label
    100   10100      1   1                Extended         Enabled   10100
    200   10200      1   1                Extended         Enabled   10200
    300   10300      1   1                Extended         Enabled   10300
  Number of neighbors: 3
    172.16.1.2
      Received routes
        MAC address advertisement:              0
        MAC+IP address advertisement:           0
        Inclusive multicast:                    2
        Ethernet auto-discovery:                2
    172.16.2.1
      Received routes
        MAC address advertisement:              0
        MAC+IP address advertisement:           0
        Inclusive multicast:                    2
        Ethernet auto-discovery:                2
    172.16.2.2
      Received routes
        MAC address advertisement:              1
        MAC+IP address advertisement:           0
        Inclusive multicast:                    2
        Ethernet auto-discovery:                2
  Number of ethernet segments: 2
    ESI: 00:01:01:01:01:01:01:01:01:00
      Status: Resolved by IFL ae0.0
      Local interface: ae0.0, Status: Up/Forwarding
      Number of remote PEs connected: 1
        Remote PE        MAC label  Aliasing label  Mode
        172.16.1.2       0          0               all-active
      Designated forwarder: 172.16.1.1
      Backup forwarder: 172.16.1.2
    ESI: 00:01:01:01:01:01:01:01:02:00
      Status: Resolved
      Number of remote PEs connected: 2
        Remote PE        MAC label  Aliasing label  Mode
        172.16.2.1       0          0               all-active
        172.16.2.2       10100      0               all-active
  Router-ID: 172.16.1.1
  Source VTEP interface IP: 172.16.1.1
{master:0}
kotetsu@spine12> show evpn instance extensive
Instance: __default_evpn__
  Route Distinguisher: 172.16.1.2:0
  Number of bridge domains: 0
  Number of neighbors: 1
    172.16.1.1
      Received routes
        Ethernet Segment:                       1

Instance: default-switch
  Route Distinguisher: 64512:12
  Encapsulation type: VXLAN
  MAC database status                     Local  Remote
    MAC advertisements:                       0       2
    MAC+IP advertisements:                    0       0
    Default gateway MAC advertisements:       0       0
  Number of local interfaces: 1 (1 up)
    Interface name  ESI                            Mode             Status
    ae0.0           00:01:01:01:01:01:01:01:01:00  all-active       Up
  Number of IRB interfaces: 0 (0 up)
  Number of bridge domains: 2
    VLAN  VNI    Intfs / up    IRB intf   Mode             MAC sync  IM route label
    100   10100      1   1                Extended         Enabled   10100
    200   10200      1   1                Extended         Enabled   10200
  Number of neighbors: 3
    172.16.1.1
      Received routes
        MAC address advertisement:              1
        MAC+IP address advertisement:           0
        Inclusive multicast:                    2
        Ethernet auto-discovery:                2
    172.16.2.1
      Received routes
        MAC address advertisement:              0
        MAC+IP address advertisement:           0
        Inclusive multicast:                    2
        Ethernet auto-discovery:                2
    172.16.2.2
      Received routes
        MAC address advertisement:              1
        MAC+IP address advertisement:           0
        Inclusive multicast:                    2
        Ethernet auto-discovery:                2
  Number of ethernet segments: 2
    ESI: 00:01:01:01:01:01:01:01:01:00
      Status: Resolved by IFL ae0.0
      Local interface: ae0.0, Status: Up/Forwarding
      Number of remote PEs connected: 1
        Remote PE        MAC label  Aliasing label  Mode
        172.16.1.1       10100      0               all-active
      Designated forwarder: 172.16.1.1
      Backup forwarder: 172.16.1.2
    ESI: 00:01:01:01:01:01:01:01:02:00
      Status: Resolved
      Number of remote PEs connected: 2
        Remote PE        MAC label  Aliasing label  Mode
        172.16.2.2       10100      0               all-active
        172.16.2.1       0          0               all-active
  Router-ID: 172.16.1.2
  Source VTEP interface IP: 172.16.1.2
{master:0}
kotetsu@spine21> show evpn instance extensive
Instance: __default_evpn__
  Route Distinguisher: 172.16.2.1:0
  Number of bridge domains: 0
  Number of neighbors: 1
    172.16.2.2
      Received routes
        Ethernet Segment:                       1

Instance: default-switch
  Route Distinguisher: 64512:21
  Encapsulation type: VXLAN
  MAC database status                     Local  Remote
    MAC advertisements:                       0       2
    MAC+IP advertisements:                    0       0
    Default gateway MAC advertisements:       0       0
  Number of local interfaces: 1 (1 up)
    Interface name  ESI                            Mode             Status
    ae0.0           00:01:01:01:01:01:01:01:02:00  all-active       Up
  Number of IRB interfaces: 0 (0 up)
  Number of bridge domains: 2
    VLAN  VNI    Intfs / up    IRB intf   Mode             MAC sync  IM route label
    100   10100      1   1                Extended         Enabled   10100
    200   10200      1   1                Extended         Enabled   10200
  Number of neighbors: 3
    172.16.1.1
      Received routes
        MAC address advertisement:              1
        MAC+IP address advertisement:           0
        Inclusive multicast:                    2
        Ethernet auto-discovery:                2
    172.16.1.2
      Received routes
        MAC address advertisement:              0
        MAC+IP address advertisement:           0
        Inclusive multicast:                    2
        Ethernet auto-discovery:                2
    172.16.2.2
      Received routes
        MAC address advertisement:              1
        MAC+IP address advertisement:           0
        Inclusive multicast:                    2
        Ethernet auto-discovery:                2
  Number of ethernet segments: 2
    ESI: 00:01:01:01:01:01:01:01:01:00
      Status: Resolved
      Number of remote PEs connected: 2
        Remote PE        MAC label  Aliasing label  Mode
        172.16.1.1       10100      0               all-active
        172.16.1.2       0          0               all-active
    ESI: 00:01:01:01:01:01:01:01:02:00
      Status: Resolved by IFL ae0.0
      Local interface: ae0.0, Status: Up/Forwarding
      Number of remote PEs connected: 1
        Remote PE        MAC label  Aliasing label  Mode
        172.16.2.2       10100      0               all-active
      Designated forwarder: 172.16.2.1
      Backup forwarder: 172.16.2.2
  Router-ID: 172.16.2.1
  Source VTEP interface IP: 172.16.2.1
{master:0}
kotetsu@spine22> show evpn instance extensive
Instance: __default_evpn__
  Route Distinguisher: 172.16.2.2:0
  Number of bridge domains: 0
  Number of neighbors: 1
    172.16.2.1
      Received routes
        Ethernet Segment:                       1

Instance: default-switch
  Route Distinguisher: 64512:22
  Encapsulation type: VXLAN
  MAC database status                     Local  Remote
    MAC advertisements:                       1       1
    MAC+IP advertisements:                    0       0
    Default gateway MAC advertisements:       0       0
  Number of local interfaces: 1 (1 up)
    Interface name  ESI                            Mode             Status
    ae0.0           00:01:01:01:01:01:01:01:02:00  all-active       Up
  Number of IRB interfaces: 0 (0 up)
  Number of bridge domains: 2
    VLAN  VNI    Intfs / up    IRB intf   Mode             MAC sync  IM route label
    100   10100      1   1                Extended         Enabled   10100
    200   10200      1   1                Extended         Enabled   10200
  Number of neighbors: 3
    172.16.1.1
      Received routes
        MAC address advertisement:              1
        MAC+IP address advertisement:           0
        Inclusive multicast:                    2
        Ethernet auto-discovery:                2
    172.16.1.2
      Received routes
        MAC address advertisement:              0
        MAC+IP address advertisement:           0
        Inclusive multicast:                    2
        Ethernet auto-discovery:                2
    172.16.2.1
      Received routes
        MAC address advertisement:              0
        MAC+IP address advertisement:           0
        Inclusive multicast:                    2
        Ethernet auto-discovery:                2
  Number of ethernet segments: 2
    ESI: 00:01:01:01:01:01:01:01:01:00
      Status: Resolved
      Number of remote PEs connected: 2
        Remote PE        MAC label  Aliasing label  Mode
        172.16.1.1       10100      0               all-active
        172.16.1.2       0          0               all-active
    ESI: 00:01:01:01:01:01:01:01:02:00
      Status: Resolved by IFL ae0.0
      Local interface: ae0.0, Status: Up/Forwarding
      Number of remote PEs connected: 1
        Remote PE        MAC label  Aliasing label  Mode
        172.16.2.1       0          0               all-active
      Designated forwarder: 172.16.2.1
      Backup forwarder: 172.16.2.2
  Router-ID: 172.16.2.2
  Source VTEP interface IP: 172.16.2.2

MACアドレステーブル

EVPN Multihoming を設定したことで

  • MAC flags の項目に L - locally learnedR - remote PE MAC が現れた
  • Logical interface の項目は
    • 自身・Multihomingペアで学習したものは local の AE インターフェース名
    • Remote の Multihoming ペアで学習したものは ESI インターフェース名
  • Active source として Remote VTEP の IPアドレスの代わりに ESI が表示されるようになった

例えば spine1[12] の Multihoming ペアを起点として見た時、以下のようになっています。

  • node11MAC アドレス 00:37:c4:e2:60:01spine11 側が学習したので
    • spine11 では L Flag がたった
    • spine12 では R Flag がたった
  • node21MAC アドレス 00:37:c4:46:d8:01spine2[12] が持つ ESI 00:01:01:01:01:01:01:01:02:00 から学習したので
    • spine1[12] 共に R Flag がたった - spine1[12] 共に Active source として spine2[12] で設定した ESI 00:01:01:01:01:01:01:01:02:00 が見える
{master:0}
kotetsu@spine11> show ethernet-switching table

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


Ethernet switching table : 2 entries, 2 learned
Routing instance : default-switch
   Vlan                MAC                 MAC      Logical                Active
   name                address             flags    interface              source
   VLAN0100            00:37:c4:46:d8:01   DR       esi.1739               00:01:01:01:01:01:01:01:02:00
   VLAN0100            00:37:c4:e2:60:01   DL       ae0.0
{master:0}
kotetsu@spine12> show ethernet-switching table

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


Ethernet switching table : 2 entries, 2 learned
Routing instance : default-switch
   Vlan                MAC                 MAC      Logical                Active
   name                address             flags    interface              source
   VLAN0100            00:37:c4:46:d8:01   DR       esi.1736               00:01:01:01:01:01:01:01:02:00
   VLAN0100            00:37:c4:e2:60:01   DR       ae0.0

spine2[12] の Multihoming ペアを起点として見た時も同様。

{master:0}
kotetsu@spine21> show ethernet-switching table

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


Ethernet switching table : 2 entries, 2 learned
Routing instance : default-switch
   Vlan                MAC                 MAC      Logical                Active
   name                address             flags    interface              source
   VLAN0100            00:37:c4:46:d8:01   DR       ae0.0
   VLAN0100            00:37:c4:e2:60:01   DR       esi.1742               00:01:01:01:01:01:01:01:01:00
{master:0}
kotetsu@spine22> show ethernet-switching table

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


Ethernet switching table : 2 entries, 2 learned
Routing instance : default-switch
   Vlan                MAC                 MAC      Logical                Active
   name                address             flags    interface              source
   VLAN0100            00:37:c4:46:d8:01   DL       ae0.0
   VLAN0100            00:37:c4:e2:60:01   DR       esi.1742               00:01:01:01:01:01:01:01:01:00

Multihoming で使われる EVPN NLRI

4台全部のテーブルを並べても見難い & そこまで有意な差もないので、代表として spine11 で見ていきます。
Juniper公式 / EVPN Multihoming Overview - New BGP NLRIs あたりと見比べながらテーブルを眺めるのが良いでしょう。

まずシングル構成の時には登場しなかった Type 1(Ethernet Auto-Discovery (A-D) route) が登場します。
まずは Autodiscovery route per EVPN instance (EVI) を各 PE から学習している状況。こいつはどうも active-active モードでのみ登場するやつ。

{master:0}
kotetsu@spine11> show route table default-switch.evpn.0

default-switch.evpn.0: 18 destinations, 32 routes (18 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

1:64512:11::010101010101010100::0/304
                   *[EVPN/170] 6d 13:23:27
                      Indirect
1:64512:12::010101010101010100::0/304
                   *[BGP/170] 12:29:57, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                      to 192.0.2.0 via xe-0/0/0.0
                    > to 192.0.2.128 via xe-0/0/1.0
                    [BGP/170] 03:36:07, localpref 100, from 172.31.0.2
                      AS path: I, validation-state: unverified
                      to 192.0.2.0 via xe-0/0/0.0
                    > to 192.0.2.128 via xe-0/0/1.0
1:64512:21::010101010101010200::0/304
                   *[BGP/170] 2d 17:29:38, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
                    [BGP/170] 22:46:20, localpref 100, from 172.31.0.2
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
1:64512:22::010101010101010200::0/304
                   *[BGP/170] 05:04:07, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
                    [BGP/170] 1d 00:56:03, localpref 100, from 172.31.0.2
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0

同様に Type 1(Ethernet Auto-Discovery (A-D) route) で今度は Autodiscovery route per Ethernet segment なやつ。

{master:0}
kotetsu@spine11> show route table default-switch.evpn.0

default-switch.evpn.0: 18 destinations, 32 routes (18 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

...

1:172.16.1.2:0::010101010101010100::FFFF:FFFF/304
                   *[BGP/170] 12:29:57, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
                    [BGP/170] 03:36:07, localpref 100, from 172.31.0.2
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
1:172.16.2.1:0::010101010101010200::FFFF:FFFF/304
                   *[BGP/170] 2d 17:29:38, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
                    [BGP/170] 22:46:20, localpref 100, from 172.31.0.2
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
1:172.16.2.2:0::010101010101010200::FFFF:FFFF/304
                   *[BGP/170] 05:04:05, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
                    [BGP/170] 1d 00:56:03, localpref 100, from 172.31.0.2
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0

次、Type 4(Ethernet Segment route) で、こいつを使って同じ ESI を持つ PE を識別するそうですよ。

{master:0}
kotetsu@spine11> show route table __default_evpn__.evpn.0

__default_evpn__.evpn.0: 5 destinations, 8 routes (5 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

1:172.16.1.1:0::010101010101010100::FFFF:FFFF/304
                   *[EVPN/170] 6d 13:58:52
                      Indirect
4:172.16.1.1:0::010101010101010100:172.16.1.1/304
                   *[EVPN/170] 6d 13:58:52
                      Indirect
4:172.16.1.2:0::010101010101010100:172.16.1.2/304
                   *[BGP/170] 13:05:22, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
                    [BGP/170] 04:11:32, localpref 100, from 172.31.0.2
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
4:172.16.2.1:0::010101010101010200:172.16.2.1/304
                   *[BGP/170] 2d 18:05:03, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
                    [BGP/170] 23:21:45, localpref 100, from 172.31.0.2
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
4:172.16.2.2:0::010101010101010200:172.16.2.2/304
                   *[BGP/170] 05:39:30, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0
                    [BGP/170] 1d 01:31:28, localpref 100, from 172.31.0.2
                      AS path: I, validation-state: unverified
                    > to 192.0.2.0 via xe-0/0/0.0
                      to 192.0.2.128 via xe-0/0/1.0

BUM トラフィックフロー確認

Ethernet Segment(ES) で選出された Designated Forwarder(DF) のみが BUM トラフィックを CE 方面に転送する、という動きをパケットキャプチャしてみました。
つって、ここで各リンクのパケットキャプチャを並べてもアレなので、キャプチャから動作を纏めた簡易図のみを...。

f:id:kakkotetsu:20170513141356p:plain

EthernetSegment リンク障害時動作確認(簡易)

仮想環境で真面目に障害試験をやるつもりはサラサラないので、何となく「あー Multihoming を組んでいる単一リンクを落としても経路が切り替わるね」とか「あー、想定通りの経路広告がされるね」くらいの緩いやつです。
今回の環境だと spinetorSW の間に全部パケットキャプチャ用の Ethernet Switch を挟んでいて、対向のリンクダウン検知なんてできず、単に torSW 側では LACP で検知して切り替わっているだけですし...。

node11 から node21ping 撃ちながら spine11xe-0/0/2 (to torSW101a) を disable

{master:0}[edit]
kotetsu@spine11# show | compare
[edit interfaces xe-0/0/2]
+   disable;

切り替わり時間とかは、環境に左右されるので参考にしないでください。あくまで「ホントに切り替わったね」を見ただけですので。

kotetsu@node11:~$ ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=49.3 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=60.0 ms

...

64 bytes from 192.168.1.2: icmp_seq=59 ttl=64 time=58.4 ms
64 bytes from 192.168.1.2: icmp_seq=60 ttl=64 time=75.0 ms
64 bytes from 192.168.1.2: icmp_seq=64 ttl=64 time=64.3 ms
64 bytes from 192.168.1.2: icmp_seq=65 ttl=64 time=70.8 ms
64 bytes from 192.168.1.2: icmp_seq=66 ttl=64 time=44.2 ms

...

--- 192.168.1.2 ping statistics ---
68 packets transmitted, 65 received, 4% packet loss, time 67123ms
rtt min/avg/max/mdev = 27.724/44.214/92.524/13.438 ms

リンク復旧

--- 192.168.1.2 ping statistics ---
60 packets transmitted, 60 received, 0% packet loss, time 59093ms
rtt min/avg/max/mdev = 28.324/45.522/79.932/12.499 ms

この一連の障害で spine11 からの UPDATE/Withdrawn も拾ったので貼っておきます。

まずリンク disabled 時の WithDrawn
Type1~4~3と2が順次 WithDrawn されていく様です。(リンク障害時に Type 2,3 が全部 WithDrawn される前に、まずはザクッと ES 死んだことを別 PE に広告することで、少しでも早く自分宛に送ってこなくなるようにする = 高速な切り替えを促すために Type1 を最初に...という動き)

f:id:kakkotetsu:20170513141454p:plain

f:id:kakkotetsu:20170513141503p:plain

f:id:kakkotetsu:20170513141511p:plain

f:id:kakkotetsu:20170513141518p:plain

次にリンク復旧時の UPDATE
Type1~4~3が順次 UPDATE される様です。

f:id:kakkotetsu:20170513141543p:plain

f:id:kakkotetsu:20170513141552p:plain

f:id:kakkotetsu:20170513141559p:plain

f:id:kakkotetsu:20170513141607p:plain

動作確認(トラフィック バイバイ~ン 問題~~~(ドラ声で))

4台の spineclear ethernet-switching table して、node[12]1 は双方の MAC アドレスが ARP テーブルに載っている状態で

kotetsu@node11:~$ ip n show
10.0.0.254 dev ens3 lladdr 00:a0:de:c0:55:80 REACHABLE
192.168.1.2 dev ens4 lladdr 00:37:c4:46:d8:01 STALE
10.0.0.65 dev ens3 lladdr 52:54:00:07:30:c0 DELAY
kotetsu@node21:~$ ip n show
192.168.1.1 dev ens4 lladdr 00:37:c4:e2:60:01 STALE
10.0.0.254 dev ens3 lladdr 00:a0:de:c0:55:80 STALE
10.0.0.65 dev ens3 lladdr 52:54:00:07:30:c0 DELAY

DUP る。

kotetsu@node11:~$ ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=85.3 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=88.3 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=101 ms (DUP!)
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=103 ms (DUP!)
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=130 ms (DUP!)
64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=78.4 ms
64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=81.7 ms (DUP!)
64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=128 ms (DUP!)
64 bytes from 192.168.1.2: icmp_seq=4 ttl=64 time=43.2 ms
64 bytes from 192.168.1.2: icmp_seq=5 ttl=64 time=51.9 ms
64 bytes from 192.168.1.2: icmp_seq=6 ttl=64 time=46.1 ms
64 bytes from 192.168.1.2: icmp_seq=7 ttl=64 time=37.7 ms
^C
--- 192.168.1.2 ping statistics ---
7 packets transmitted, 7 received, +5 duplicates, 0% packet loss, time 6009ms
rtt min/avg/max/mdev = 37.764/81.372/130.159/30.336 ms

パケットを拾って、一番酷い ICMP Echo (Request|Reply) Sequence No.2 の状況を追ってみると

  • node21
    • Sequence No.2 の ICMP Echo Request を2個受信している
  • node11
    • Sequence No.2 の ICMP Echo Request を1個しか送信していない
    • Sequence No.2 の ICMP Echo Reply を4個受信している
  • torSW101a
    • Sequence No.2 の ICMP Echo Request を spine12 に転送している
  • spine12
    • Sequence No.2 の ICMP Echo Request を Ingress Replication
    • この時点では、まだ node21MAC アドレスがどの VTEP 配下にいるか知らないから Unknown Unicast 扱い
    • Sequence No.2 の ICMP Echo Request を 投げた直後、spine22 から EVPN NLRI Type2node21MAC アドレス advertise を受けて、以降は IngressReplication せずに spine22 だけに送信
  • bb01
    • Sequence No.2 の ICMP Echo Request をそのまま spine11, spine21, spine22 に転送
  • spine21, spine22
    • Sequence No.2 の ICMP Echo Request のカプセルの中身は DstMAC が node21 で、自分の ES 配下にいるやつへの Unicast Traffic なので、そのまま torSw201a に転送(もしかしたら、spine21 はこの時点で node21MACアドレスを学習しておらず、Unknown Unicast として Multihoming の DF 動作を果たした、という可能性も)
    • EVPN Multihoming の挙動としては正しい

という感じでして。
現状の実装だと仕方ない挙動と言わざるをえない...でしょうかね。そもそもあまり起こりえないシナリオですかね。僕はノリで clear ethernet-switching table とかよく叩くんすが(そりゃ検証環境だからだ)。
EVPN Multihoming Mode を active-standby にしても、前述の spine2[12] の挙動は変わらず、Remote VTEP 側(spine12)が DF にのみ送信してくることを期待しているように見えますし...。
なんかこの辺の問題提起やら解決案やらが RFC, draft であったりするんでしょうか。もしくは各メーカの実装で何か回避できているんでしょうか。追っている人がいたら是非教えてください...。

一応、以下は spine12bb01 間のパケットキャプチャですが、Sequence No.2 の ICMP Echo Request を Ingress Replication した直後に spine21 から EVPN NLRI Type2node21MAC アドレス advertise を受けているの図です。

f:id:kakkotetsu:20170513141645p:plain

おしまい

まとめ

  • EVPN Multihoming の触りを試して、最低限の正常動作が確認できました
  • RFC7432(BGP MPLS-Based Ethernet VPN) Multihoming に書かれている内容(で実装されているもの)は、今回試した範囲には収まりきらんので色々やってみましょう

所感

  • VTEP を冗長化する手法として考えると、EVPN Multihoming は各 PE がそれなりに独立して動いてくれるのが嬉しいです。変に独自機構を使うと「その冗長化プロトコルを形成できるバージョンの組み合わせ」でバージョンアップとかが苦しくなりそうなので...。
    • 偏見かも知らんけど L2, L4 の世界はその辺で結構苦しむような...。
    • 例えば、同じ Juniper でいうと MC-LAG とかはどうなんでしょうね。組めるバージョンの組み合わせとか気にして運用するもんでしょうか。
  • vQFX いいすね...100万回言ってますけど、この辺の調査/検証をお家で好きにできると、色々と敷居が下がるので。
    • こうなってくると、本記事の torSW[12]01a にあたるところに、QFX5110 とか QFX5200 とかの仮想版も欲しくなってきますね
  • この辺のニッチな話に興味がある人、冒頭で紹介した oreilly の「Juniper QFX10000 Series」もオススメですよ!
    • 独自プロセッサ開発経緯や特徴・Architecture(HW/SW) の結構詳しい説明・MPLS/VXLAN+EVPNの設計ポイント とか、箱を持っていなくても読んでいて楽しいです
  • Juniper QFX10000 最高!みんな買おうぜ!!(買えない)