Teil 3 - Overlay Verifikation - Routen ohne Ende…

Dies ist der dritte Teil meiner Serie “Apstra unter der Haube”, der direkt an den vorherigen zweiten Teil zur Implementierung der Overlay-Services anknüpft und bei dem die Verifikation und Nachvollziehbarkeit der Overlay-Funktionalitäten im Fokus steht.

Dabei soll es vorerst um einen Gesamtüberblick und ein Verständnis der Zusammenhänge gehen, wie Junos die EVPN-Routen im Kontext der übergreifenden EVPN Control Plane verarbeitet, wie man BGP-Peerings analysiert, welche Routingtabellen dabei eine Rolle spielen und mit welchen “show”-Commands man die verschiedenen Zustände und Verarbeitungsstationen einsehen kann. Das Ziel ist es, euch in die Lage zu versetzen, einzelne Erreichbarkeitsinformationen auf ihrem Weg von der EVPN-Route bis zum Eintrag in die relevanten Control Plane Tabellen nachvollziehen zu können - sowohl für Layer-2 als auch für Layer-3 Informationen.

Host-Übersicht

Um die einzelnen Host-Erreichbarkeitsinformationen, wie MAC- und IP-Adressen besser nachvollziehen zu können, verschaffen wir uns zunächst noch einmal einen Überblick über den aktuellen Zustand der Demo-Umgebung:

Apstra Overlay Control Plane
Die Demo-Umgebung simuliert dabei eine virtualisierte Compute-Infrastruktur, d.h. dass sich hinter jedem der drei physischen Hosts mehrere virtuelle Hosts (z.B. VMs) verbergen können. Die einzelnen virtuellen Hosts sind in verschiedenen Virtual Networks angebunden und haben jeweils individuelle IP-Adressen. Virtuelle Hosts, die auf dem gleichen physischen Host laufen, teilen sich die gleiche MAC-Adresse.

Hier eine Gesamtübersicht:

Phys. HostMAC-AdresseAnbindungVirt. Host (IP)Virtual Network
Host1aa:bb:cc:80:12:00Multi-Homed10.1.101.1110101
(Leaf1+2)10.1.102.1110102
ESI 00:02:00:00:00:00:01:00:00:0110.2.201.1120201
10.2.202.1120202
Host2aa:bb:cc:80:18:00Single-Homed10.1.101.1210101
(Leaf3)10.2.201.1220201
Host3aa:bb:cc:80:19:00Single-Homed10.1.102.1310102
(Leaf3)10.2.202.1320202

EVPN-eBGP Peerings

Zu Beginn werfen wir einen Blick auf die eBGP-Sessions, die für die Funktionalität der EVPN Control-Plane erforderlich sind. Dazu nutzen wir sowohl auf den Leaf- als auch auf den Spine-Switches den Befehl show bgp summary.

Im Fokus der Betrachtung stehen hier allerdings nur jene BGP-Session, die zwischen den Loopback-IPs der Switche aufgebaut werden (Adressbereich: 203.0.113.0/24) und die mit der Adressfamilie evpn konfiguriert sind.

Schauen wir uns dazu zunächst exemplarisch den Spine1 an:

aosadmin@spine1> show bgp summary

Threading mode: BGP I/O
Default eBGP mode: advertise - accept, receive - accept
Groups: 2 Peers: 6 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
[...]
bgp.evpn.0
                      60         60          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
[...]
203.0.113.2           64514        152        165       0       0     1:00:13 Establ
  bgp.evpn.0: 21/21/21/0
203.0.113.3           64515        118        133       0       0       44:35 Establ
  bgp.evpn.0: 21/21/21/0
203.0.113.4           64516        117        131       0       0       44:22 Establ
  bgp.evpn.0: 18/18/18/0

Aus Sicht der Spine-Switches kann man ablesen, dass zu jedem Leaf-Loopback jeweils eine eBGP-Session etabliert wurde (Established) und darüber aktiv Pakete und Routen ausgetauscht werden. Es werden die gleichen AS-Nummern verwendet, wie auch für das Underlay-Routing. Sämtliche darüber empfangenen Routen landen in der Routingtabelle bgp.evpn.0.

Als nächstes schauen wir uns das Ganze noch aus Sicht eines Leaf-Switches an:

aosadmin@leaf1> show bgp summary

Threading mode: BGP I/O
Default eBGP mode: advertise - accept, receive - accept
Groups: 2 Peers: 4 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
[...]
bgp.evpn.0
                      78         39          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
[...]
203.0.113.0           64512        157        141       0       0       55:45 Establ
  bgp.evpn.0: 21/39/39/0
  evpn-1.evpn.0: 13/26/26/0
  TenantA.evpn.0: 3/6/6/0
  __default_evpn__.evpn.0: 1/1/1/0
  TenantB.evpn.0: 7/10/10/0
203.0.113.1           64513        128        104       0       0       39:55 Establ
  bgp.evpn.0: 18/39/39/0
  evpn-1.evpn.0: 13/26/26/0
  TenantA.evpn.0: 3/6/6/0
  __default_evpn__.evpn.0: 0/1/1/0
  TenantB.evpn.0: 3/10/10/0

Auch am Beispiel des Leaf1 sieht man, dass zwei eBGP-Sessions, jeweils zu den Loopback-IPs der beiden Spine-Switches mit unterschiedlichen ASNs etabliert wurden.

Interessant ist dabei allerdings im Unterschied zu den Spine-Switches, dass die empfangenen Routen hier nicht nur in einer Routing-Tabelle, sondern gleich in mehreren EVPN Routing-Tabellen landen:

  • bgp.evpn.0
  • evpn-1.evpn.0
  • TenantA.evpn.0
  • TenantB.evpn.0
  • __default_evpn__.evpn.0

Warum die EVPN-Routen hier gleich in mehrere Routing-Tabellen aufgeteilt werden und welchen Zweck diese im Einzelnen erfüllen, schauen wir uns nun näher an.

Überblick

Die folgende Darstellung soll einen Gesamtüberblick über die beteiligten Routing-Tabellen auf Leaf-Switches geben, sowie deren Zusammenhänge und Funktionsweisen veranschaulichen.

Gleichzeitig kann die Zeichnung auch als Hilfsmittel in der gezielten Analyse und Nachverfolgung von einzelnen Routen bzw. Erreichbarkeitsinformationen verwendet werden - von der BGP Protokoll-Ebene über verschiedene Ebenen der Control Plane. Dafür sind die zugehörigen Show-Commands zur Verifizierung der einzelnen Komponenten direkt vermerkt.

Apstra Overlay Leaf-Implementation
Wenn man auf einem bestimmten Leaf-Switch nachvollziehen will, ob einzelne Remote-Ziele erreichbar sind, muss man überprüfen, ob die dafür notwendigen EVPN-Routen empfangen und diese im weiteren Verlauf korrekt über die verschiedenen Routing-Tabellen hinweg verarbeitet werden.

Senden und Empfangen

Noch bevor BGP-Routen in der lokalen Routingtabelle landen, können wir uns für einen spezifischen BGP-Peer zudem noch detailliert anschauen, welche Routen von diesem empfangen, aber auch welche Routen zu diesem gesendet werden.

Dies kann u.a. für die folgenden Fragestellungen relevant sein:

  • Sendet ein Leaf-Switch die erwarteten EVPN-Routen für einen bestimmten Host?
  • Empfängt ein Leaf über beide Spines die identischen Routen oder gibt es eine Diskrepanz?
  • Welche Routen werden von einem Leaf nach der Filterung durch die Export-Policy tatsächlich gesendet?

Dazu werden die folgenden Befehle genutzt:

  • show route advertising-protocol bgp <neighbor>
    • gesendete Routen zum BGP-Peer (nach Filterung durch Export-Policy)
  • show route receive-protocol bgp <neighbor>
    • empfangen Routen vom BGP-Peer (vor Filterung durch Import-Policy)

Am Beispiel des Leaf3 können wir so bspw. mit dem Befehl show route advertising-protocol bgp 203.0.113.0 überprüfen, welche EVPN-Routen er in Richtung des Spine1 sendet:

aosadmin@leaf3> show route advertising-protocol bgp 203.0.113.0
[...]
bgp.evpn.0: 60 destinations, 102 routes (60 active, 0 holddown, 0 hidden)
Restart Complete
  Prefix                  Nexthop              MED     Lclpref    AS path
  2:203.0.113.4:65534::10101::aa:bb:cc:80:18:00/304 MAC/IP
*                         Self                                    I
  2:203.0.113.4:65534::10102::aa:bb:cc:80:19:00/304 MAC/IP
*                         Self                                    I
  2:203.0.113.4:65534::20201::aa:bb:cc:80:18:00/304 MAC/IP
*                         Self                                    I
  2:203.0.113.4:65534::20202::aa:bb:cc:80:19:00/304 MAC/IP
*                         Self                                    I
  2:203.0.113.4:65534::10101::aa:bb:cc:80:18:00::10.1.101.12/304 MAC/IP
*                         Self                                    I
  2:203.0.113.4:65534::10102::aa:bb:cc:80:19:00::10.1.102.13/304 MAC/IP
*                         Self                                    I
  2:203.0.113.4:65534::20201::aa:bb:cc:80:18:00::10.2.201.12/304 MAC/IP
*                         Self                                    I
  2:203.0.113.4:65534::20202::aa:bb:cc:80:19:00::10.2.202.13/304 MAC/IP
*                         Self                                    I
  3:203.0.113.4:65534::10101::203.0.113.4/248 IM
*                         Self                                    I
  3:203.0.113.4:65534::10102::203.0.113.4/248 IM
*                         Self                                    I
  3:203.0.113.4:65534::20201::203.0.113.4/248 IM
*                         Self                                    I
  3:203.0.113.4:65534::20202::203.0.113.4/248 IM
*                         Self                                    I
  5:203.0.113.4:10::0::10.1.101.0::24/248
*                         Self                                    I
  5:203.0.113.4:10::0::10.1.102.0::24/248
*                         Self                                    I
  5:203.0.113.4:10::0::10.1.255.2::32/248
*                         Self                                    I
  5:203.0.113.4:20::0::10.2.201.0::24/248
*                         Self                                    I
  5:203.0.113.4:20::0::10.2.202.0::24/248
*                         Self                                    I
  5:203.0.113.4:20::0::10.2.255.2::32/248
*                         Self                                    I

[...]    <--Output abgeschnitten-->

Und am Beispiel des Leaf1 können wir mit dem Befehl show route receive-protocol bgp 203.0.113.0 sehen, welche EVPN-Routen er vom Spine1 empfängt:

aosadmin@leaf1> show route receive-protocol bgp 203.0.113.0
[...]
bgp.evpn.0: 60 destinations, 99 routes (60 active, 0 holddown, 0 hidden)
Restart Complete
  Prefix                  Nexthop              MED     Lclpref    AS path
  1:203.0.113.3:0::020000000001000001::FFFF:FFFF/192 AD/ESI
*                         203.0.113.3                             64512 64515 I
  1:203.0.113.3:65534::020000000001000001::0/192 AD/EVI
                          203.0.113.3                             64512 64515 I
  2:203.0.113.3:65534::10101::aa:bb:cc:80:12:00/304 MAC/IP
*                         203.0.113.3                             64512 64515 I
  2:203.0.113.3:65534::10102::aa:bb:cc:80:12:00/304 MAC/IP
*                         203.0.113.3                             64512 64515 I
  2:203.0.113.3:65534::20201::aa:bb:cc:80:12:00/304 MAC/IP
*                         203.0.113.3                             64512 64515 I
  2:203.0.113.3:65534::20202::aa:bb:cc:80:12:00/304 MAC/IP
*                         203.0.113.3                             64512 64515 I
  2:203.0.113.4:65534::10101::aa:bb:cc:80:18:00/304 MAC/IP
                          203.0.113.4                             64512 64516 I
  2:203.0.113.4:65534::10102::aa:bb:cc:80:19:00/304 MAC/IP
*                         203.0.113.4                             64512 64516 I
  2:203.0.113.4:65534::20201::aa:bb:cc:80:18:00/304 MAC/IP
*                         203.0.113.4                             64512 64516 I
  2:203.0.113.4:65534::20202::aa:bb:cc:80:19:00/304 MAC/IP
*                         203.0.113.4                             64512 64516 I
  2:203.0.113.3:65534::10101::aa:bb:cc:80:12:00::10.1.101.11/304 MAC/IP
*                         203.0.113.3                             64512 64515 I
  2:203.0.113.3:65534::10102::aa:bb:cc:80:12:00::10.1.102.11/304 MAC/IP
*                         203.0.113.3                             64512 64515 I
  2:203.0.113.3:65534::20201::aa:bb:cc:80:12:00::10.2.201.11/304 MAC/IP
*                         203.0.113.3                             64512 64515 I
  2:203.0.113.3:65534::20202::aa:bb:cc:80:12:00::10.2.202.11/304 MAC/IP
*                         203.0.113.3                             64512 64515 I
  2:203.0.113.4:65534::10101::aa:bb:cc:80:18:00::10.1.101.12/304 MAC/IP
                          203.0.113.4                             64512 64516 I
  2:203.0.113.4:65534::10102::aa:bb:cc:80:19:00::10.1.102.13/304 MAC/IP
*                         203.0.113.4                             64512 64516 I
  2:203.0.113.4:65534::20201::aa:bb:cc:80:18:00::10.2.201.12/304 MAC/IP
*                         203.0.113.4                             64512 64516 I
  2:203.0.113.4:65534::20202::aa:bb:cc:80:19:00::10.2.202.13/304 MAC/IP

[...]    <--Output abgeschnitten-->

Globale EVPN Routing-Tabelle

Kommen wir nun zu den verschiedenen lokalen Routingtabellen auf den Leaf-Switches zurück und beginnen die Betrachtung bei den EVPN-Routen, die jeweils von den EVPN-Peers in Form der Spine-Switches empfangen werden. Sämtliche empfangenen EVPN-Routen der Spines landen primär erst einmal in der globalen EVPN-Routingtabelle mit dem Namen bgp.evpn.0, sofern sie von der entsprechenden Import-Policy akzeptiert werden.

💡 Tipp
Apstra konfiguriert grundsätzlich keine Import-Policies auf den EVPN eBGP-Sessions (Vgl. Blog Post zur Overlay-Implementierung). Von daher greift hier die Default-Policy, die alle eingehenden EVPN-Routen erlaubt. Dies erkennt man auch im o.g. “show bgp summary” Output - sämtliche empfangenen Routen werden auch in die Tabelle bgp.evpn.0 importiert bzw. akzeptiert ("received routes = accepted routes").
Die Tabelle bgp.evpn.0 enthält also alle EVPN-Routen vom Typ 1-5 aus allen VRFs und VNIs inkl. aller Route-Targets. Sie wird darüber hinaus auch in der ausgehenden Richtung als Basis für EVPN-Updates in Richtung der Spine-Switches verwendet. Dabei sind allerdings die Apstra-seitig konfigurierten Export-Policies zu beachten, die bspw. verhindern, dass Routen von einem Spine an den anderen Spine weitergegeben werden.
💡 Tipp
Vergleicht man im vorherigen Abschnitt den Output des “show bgp summary” des Spine1, sieht man daran auch sehr gut, dass dieser ausschließlich die Tabelle bgp.evpn.0 verwendet, um ein- und ausgehende EVPN-Routen zu verarbeiten.

Ausgehend von der globalen EVPN-Tabelle bgp.evpn.0 erfolgt dann auf Basis der jeweils hinterlegten Route-Targets (RTs) eine Weiterverabreitung in den folgenden vier Routing-Tabellen:

  • evpn-1.evpn.0 -> alle MAC-VRF- und VNI-spezifischen Typ 1-3 EVPN-Routen
  • TenantA.evpn.0 -> alle TenantA-spezifischen Typ-5 EVPN-Routen
  • TenantB.evpn.0 -> alle TenantB-spezifischen Typ-2 (MAC/IP) und Typ-5 EVPN-Routen
  • __default_evpn__.evpn.0 -> alle globalen ESI-Multihoming-relevanten Typ-1/4 EVPN-Routen

L2 MAC-VRF Instanz evpn-1

Sämtliche L2-relevanten EVPN-Routen aus der bgp.evpn.0 Tabelle landen in der MAC-VRF Tabelle evpn-1.evpn.0.

Hierzu zählen die folgenden EVPN-Routen:

  • Typ-1: EVI-/Service-bezogene Ethernet-Segment Auto-Discovery (AD/EVI) Routen für Split-Horizon und Aliasing Funktionalität, sowie ESI-bezogene (AD/ESI) Routen für Fast Convergence (Mass Withdrawal)
  • Typ-2: MAC-/IP-Routen als wesentliche Host-Erreichbarkeitsinformationen inkl. VNI-Zugehörigkeit
  • Typ-3: Inclusive Multicast Routen zur Signalisierung der VN-/VLAN-Zugehörigkeit der Leaf-Switches, die für die Erstellung der Flood-List für BUM-Traffic in den einzelnen L2-Segmenten benötigt wird.

Die o.g. Routen werden anhand des MAC-VRF- bzw. der individuellen VNI-sepzifischen Route-Targets in die Tabelle evpn-1.evpn.0 importiert.

Der Inhalt dieser Tabelle kann mit dem Befehl show route table evpn-1.evpn.0 angezeigt werden, wie hier (auszugsweise) am Beispiel des Leaf1:

aosadmin@leaf1> show route table evpn-1.evpn.0
evpn-1.evpn.0: 39 destinations, 65 routes (39 active, 0 holddown, 0 hidden)
Restart Complete
+ = Active Route, - = Last Active, * = Both

1:203.0.113.2:65534::020000000001000001::0/192 AD/EVI
                   *[EVPN/170] 00:31:08
                       Indirect
1:203.0.113.3:0::020000000001000001::FFFF:FFFF/192 AD/ESI
                   *[BGP/170] 00:31:07, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0
                    [BGP/170] 00:31:07, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0
1:203.0.113.3:65534::020000000001000001::0/192 AD/EVI
                   *[BGP/170] 00:31:08, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0
                    [BGP/170] 00:31:08, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0
[...]
2:203.0.113.3:65534::10101::aa:bb:cc:80:12:00/304 MAC/IP
                   *[BGP/170] 00:31:06, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10101
                       to 172.16.0.6 via ge-0/0/1.0, Push 10101
                    [BGP/170] 00:31:06, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10101
                       to 172.16.0.6 via ge-0/0/1.0, Push 10101
2:203.0.113.3:65534::10102::aa:bb:cc:80:12:00/304 MAC/IP
                   *[BGP/170] 00:31:06, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10102
                       to 172.16.0.6 via ge-0/0/1.0, Push 10102
                    [BGP/170] 00:31:06, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10102
                       to 172.16.0.6 via ge-0/0/1.0, Push 10102
2:203.0.113.3:65534::20201::aa:bb:cc:80:12:00/304 MAC/IP
                   *[BGP/170] 00:01:01, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20201
                       to 172.16.0.6 via ge-0/0/1.0, Push 20201
                    [BGP/170] 00:01:01, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20201
                       to 172.16.0.6 via ge-0/0/1.0, Push 20201
2:203.0.113.3:65534::20202::aa:bb:cc:80:12:00/304 MAC/IP
                   *[BGP/170] 00:01:05, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20202
                       to 172.16.0.6 via ge-0/0/1.0, Push 20202
                    [BGP/170] 00:01:05, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20202
                       to 172.16.0.6 via ge-0/0/1.0, Push 20202
[...]
2:203.0.113.3:65534::10101::aa:bb:cc:80:12:00::10.1.101.11/304 MAC/IP
                   *[BGP/170] 00:31:06, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                       to 172.16.0.0 via ge-0/0/0.0, Push 10101
                    >  to 172.16.0.6 via ge-0/0/1.0, Push 10101
                    [BGP/170] 00:31:06, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                       to 172.16.0.0 via ge-0/0/0.0, Push 10101
                    >  to 172.16.0.6 via ge-0/0/1.0, Push 10101
2:203.0.113.3:65534::10102::aa:bb:cc:80:12:00::10.1.102.11/304 MAC/IP
                   *[BGP/170] 00:31:06, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                       to 172.16.0.0 via ge-0/0/0.0, Push 10102
                    >  to 172.16.0.6 via ge-0/0/1.0, Push 10102
                    [BGP/170] 00:31:06, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                       to 172.16.0.0 via ge-0/0/0.0, Push 10102
                    >  to 172.16.0.6 via ge-0/0/1.0, Push 10102
2:203.0.113.3:65534::20201::aa:bb:cc:80:12:00::10.2.201.11/304 MAC/IP
                   *[BGP/170] 00:01:01, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20201
                       to 172.16.0.6 via ge-0/0/1.0, Push 20201
                    [BGP/170] 00:01:01, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20201
                       to 172.16.0.6 via ge-0/0/1.0, Push 20201
2:203.0.113.3:65534::20202::aa:bb:cc:80:12:00::10.2.202.11/304 MAC/IP
                   *[BGP/170] 00:01:05, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20202
                       to 172.16.0.6 via ge-0/0/1.0, Push 20202
                    [BGP/170] 00:01:05, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20202
                       to 172.16.0.6 via ge-0/0/1.0, Push 20202
[...]
3:203.0.113.3:65534::10101::203.0.113.3/248 IM
                   *[BGP/170] 00:40:10, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10101
                       to 172.16.0.6 via ge-0/0/1.0, Push 10101
                    [BGP/170] 00:38:03, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10101
                       to 172.16.0.6 via ge-0/0/1.0, Push 10101
3:203.0.113.3:65534::10102::203.0.113.3/248 IM
                   *[BGP/170] 00:40:10, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10102
                       to 172.16.0.6 via ge-0/0/1.0, Push 10102
                    [BGP/170] 00:38:03, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10102
                       to 172.16.0.6 via ge-0/0/1.0, Push 10102
3:203.0.113.3:65534::20201::203.0.113.3/248 IM
                   *[BGP/170] 00:38:00, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20201
                       to 172.16.0.6 via ge-0/0/1.0, Push 20201
                    [BGP/170] 00:38:00, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20201
                       to 172.16.0.6 via ge-0/0/1.0, Push 20201
3:203.0.113.3:65534::20202::203.0.113.3/248 IM
                   *[BGP/170] 00:37:59, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20202
                       to 172.16.0.6 via ge-0/0/1.0, Push 20202
                    [BGP/170] 00:37:59, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20202
                       to 172.16.0.6 via ge-0/0/1.0, Push 20202

[...]    <--Output abgeschnitten-->
📝 Hinweis
Die relevanten Route-Targets werden in Form von BGP Communities mit den EVPN-Routen übertragen. Sie sind mit dem Zusatz extensive in den jeweiligen Routing-Tabellen einsehbar (z.B. show route table evpn-1.evpn.0 extensive).

EVPN Database

Da die oben gezeigte Routing-Tabelle des MAC-VRFs selbst in dieser überschaubaren Demo-Umgebung bereits sehr viele Einträge enthält, wird das Ganze insbesondere in größeren DC-Netzen schnell sehr unübersichtlich.

Um sich hier einen konsolidierten Überblick über sämtliche Host-Erreichbarkeitsinformationen zu verschaffen, würde ich empfehlen als Einstieg einen Blick in die EVPN Database zu werfen.

Am Beispiel des Leaf1 und des Leaf3 kann man unter Verwendung des show evpn database Commands sehr gut erkennen, wie sämtliche Informationen, insbesondere aus den EVPN Typ2-Routen in einer übersichtlichen Tabellendarstellung zusammengefasst werden:

aosadmin@leaf1> show evpn database
Instance: evpn-1
VLAN  DomainId  MAC address        Active source                  Timestamp        IP address
     10101      00:1c:73:00:00:01  irb.101                        Jun 10 19:31:56  10.1.101.1
     10101      aa:bb:cc:80:12:00  00:02:00:00:00:00:01:00:00:01  Jun 10 19:41:00  10.1.101.11
     10101      aa:bb:cc:80:18:00  203.0.113.4                    Jun 10 20:10:08  10.1.101.12
     10102      00:1c:73:00:00:01  irb.102                        Jun 10 19:31:56  10.1.102.1
     10102      aa:bb:cc:80:12:00  00:02:00:00:00:00:01:00:00:01  Jun 10 19:41:00  10.1.102.11
     10102      aa:bb:cc:80:19:00  203.0.113.4                    Jun 10 20:09:29  10.1.102.13
     20201      00:1c:73:00:00:01  irb.201                        Jun 10 19:34:07  10.2.201.1
     20201      aa:bb:cc:80:12:00  00:02:00:00:00:00:01:00:00:01  Jun 10 20:11:05  10.2.201.11
     20201      aa:bb:cc:80:18:00  203.0.113.4                    Jun 10 20:10:14  10.2.201.12
     20202      00:1c:73:00:00:01  irb.202                        Jun 10 19:34:07  10.2.202.1
     20202      aa:bb:cc:80:12:00  00:02:00:00:00:00:01:00:00:01  Jun 10 20:11:01  10.2.202.11
     20202      aa:bb:cc:80:19:00  203.0.113.4                    Jun 10 20:09:48  10.2.202.13

---------

aosadmin@leaf3> show evpn database
Instance: evpn-1
VLAN  DomainId  MAC address        Active source                  Timestamp        IP address
     10101      00:1c:73:00:00:01  irb.101                        Jun 10 19:31:50  10.1.101.1
     10101      aa:bb:cc:80:12:00  00:02:00:00:00:00:01:00:00:01  Jun 10 19:41:01  10.1.101.11
     10101      aa:bb:cc:80:18:00  ge-0/0/2.0                     Jun 10 20:10:07  10.1.101.12
     10102      00:1c:73:00:00:01  irb.102                        Jun 10 19:31:50  10.1.102.1
     10102      aa:bb:cc:80:12:00  00:02:00:00:00:00:01:00:00:01  Jun 10 19:41:01  10.1.102.11
     10102      aa:bb:cc:80:19:00  ge-0/0/3.0                     Jun 10 20:09:29  10.1.102.13
     20201      00:1c:73:00:00:01  irb.201                        Jun 10 19:34:07  10.2.201.1
     20201      aa:bb:cc:80:12:00  00:02:00:00:00:00:01:00:00:01  Jun 10 20:11:05  10.2.201.11
     20201      aa:bb:cc:80:18:00  ge-0/0/2.0                     Jun 10 20:10:14  10.2.201.12
     20202      00:1c:73:00:00:01  irb.202                        Jun 10 19:34:07  10.2.202.1
     20202      aa:bb:cc:80:12:00  00:02:00:00:00:00:01:00:00:01  Jun 10 20:11:01  10.2.202.11
     20202      aa:bb:cc:80:19:00  ge-0/0/3.0                     Jun 10 20:09:48  10.2.202.13

Für jede MAC-Adresse wird hier neben der VLAN-Zugehörigkeit auch die verwendete IP-Adresse aufgelistet.

💡 Tipp
Diese Informationen werden von den Leaf-Switches u.a. auch für die Umsetzung der Proxy-ARP Funktionalität genutzt.

Was darüber hinaus auffällt, sind die Hinweise zur Active Source, die Aufschluss über den Ursprung der Informationen geben. Hier sind verschiedene Typen von Einträgen zu finden:

TypBeispielBeschreibung
Phys. Interface-Namege-0/0/2.0Die MAC-/IP-Informationen wurden an einem lokalen phys. Interface gelernt. Der zugehörige Host ist also direkt verbunden.
L3 IRB-Interfaceirb.101Die MAC-/IP-Informationen wurden an einem lokalen IRB-Interface gelernt. Hierbei handelt es sich um die Informationen des entsprechenden Anycast-Gateways. Hinweis: Apstra konfiguriert immer die selbe identische MAC-Adresse 00:1c:73:00:00:01 für alle IRB-Interafaces.
IP-Adresse203.0.113.4Die MAC-/IP-Informationen wurden vom Remote-VTEP mit der genannten IP-Adresse gelernt und es handelt sich um eine single-homed Anbindung
Ethernet Segment ID00:02:00:00:00:00:01:00:00:01Es handelt sich um einen multi-homed Host, der über das Ethernet Segment mit der genannten ID angebunden ist, welches von mehreren Leaf-Switches propagiert wird.

Wenn man insbesondere für die Multi-Homed Hosts herausfinden möchte, welche konkreten Leaf-Switches / Remote-VTEPs hinter dem genannten ESI stecken, dann kann dies mit dem Command show evpn database extensive erfolgen:

aosadmin@leaf3> show evpn database extensive
Instance: evpn-1
[...]
VN Identifier: 10101, MAC address: aa:bb:cc:80:12:00
  State: 0x0
  Source: 00:02:00:00:00:00:01:00:00:01, Rank: 1, Status: Active
    Remote origin: 203.0.113.2
    Remote state: <Mac-Only-Adv>
    Remote origin: 203.0.113.3
    Remote state: <Mac-Only-Adv>
    Mobility sequence number: 0 (minimum origin address 203.0.113.2)
    Timestamp: Jun 10 19:41:01.140004 (0x6a29bdcd)
    State: <Remote-To-Local-Adv-Done>
    MAC advertisement route status: Not created (no local state present)
    IP address: 10.1.101.11
      Remote origin: 203.0.113.2
      Remote state: <Sent-to-l2ald>
      Remote origin: 203.0.113.3
      Remote state: <Sent-to-l2ald>
    History db: <No entries>
[...]

Die beiden Remote-Origin Einträge 203.0.113.2 und 203.0.113.3 verweisen auf die entsprechenden VTEPs, die das ESI, sowie den Host anbinden

L3 Tenant-spezifische Routen

Neben den bisher betrachteten Informationen im Kontext des MAC-VRF, wenden wir uns nun der Verarbeitung der reinen Layer-3 Routing-Informationen zu.

Sämtliche L3-relevanten EVPN-Routen für die beiden Tenants / IP-VRFs aus der Tabelle bgp.evpn.0 landen in der den beiden Tenant-spezifischen EVPN-Routingtabellen:

  • TenantA.evpn.0
  • TenantB.evpn.0

Die entsprechenden Routen werden anhand des Tenant-spezifischen Route-Targets in die jeweiligen Tabellen importiert. Der Inhalt dieser Tabellen kann mit dem Befehl show route table TenantA.evpn.0 bzw. show route table TenantB.evpn.0 angezeigt werden.

Das Interessante dabei ist, dass aufgrund der unterschiedlichen Routing-Konfiguration (Asymmetric vs. Symmetric IRB) jeweils verschiedene EVPN-Routinginformationen in den beiden Tabellen vorzufinden sind:

TabelleRoutingInformationen
TenantA.evpn.0Asymmetric IRBausschießlich Typ-5 EVPN-Routen für die Tenant-spezifischen Subnetze und Loopback-IPs
TenantB.evpn.0Symmetric IRBsowohl Typ-2 (MAC/IP) für individuelle Host-Routen als auch Typ-5 EVPN-Routen die Tenant-spezifischen Subnetze und Loopback-IPs
💡 Hintergrund

Inter-VNI-Routing

  • Im TenantA mit Asymmetric IRB sind die Typ-2 EVPN-Routen für die Routing-Entscheidungen nicht erforderlich, da immer am Ingress Leaf direkt in das Ziel-VN geroutet wird und der Ziel-Host von dort über Layer-2 erreichbar ist.
  • Im TenantB mit Symmetric IRB sind die Typ-2 EVPN-Routen hingegen für die Routing-Entscheidungen erforderlich, da der Ingress Leaf direkt den Egress-Leaf identifizieren muss, um im Anschluss über das L3-VN zum konkreten Ziel zu routen.

Hier beide Tabellen auszugsweise gegenübergestellt am Beispiel des Leaf1: TenantA

TenantA.evpn.0: 9 destinations, 15 routes (9 active, 0 holddown, 0 hidden)
Restart Complete
+ = Active Route, - = Last Active, * = Both

[...]
5:203.0.113.3:10::0::10.1.101.0::24/248
                   *[BGP/170] 00:40:11, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10000
                       to 172.16.0.6 via ge-0/0/1.0, Push 10000
                    [BGP/170] 00:40:01, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10000
                       to 172.16.0.6 via ge-0/0/1.0, Push 10000
5:203.0.113.3:10::0::10.1.102.0::24/248
                   *[BGP/170] 00:40:11, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10000
                       to 172.16.0.6 via ge-0/0/1.0, Push 10000
                    [BGP/170] 00:40:01, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10000
                       to 172.16.0.6 via ge-0/0/1.0, Push 10000
5:203.0.113.3:10::0::10.1.255.1::32/248
                   *[BGP/170] 00:40:11, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10000
                       to 172.16.0.6 via ge-0/0/1.0, Push 10000
                    [BGP/170] 00:40:01, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10000
                       to 172.16.0.6 via ge-0/0/1.0, Push 10000
5:203.0.113.4:10::0::10.1.101.0::24/248
                   *[BGP/170] 00:40:00, localpref 100, from 203.0.113.1
                      AS path: 64513 64516 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10000
                       to 172.16.0.6 via ge-0/0/1.0, Push 10000
                    [BGP/170] 00:40:00, localpref 100, from 203.0.113.0
                      AS path: 64512 64516 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10000
                       to 172.16.0.6 via ge-0/0/1.0, Push 10000
5:203.0.113.4:10::0::10.1.102.0::24/248
                   *[BGP/170] 00:40:00, localpref 100, from 203.0.113.1
                      AS path: 64513 64516 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10000
                       to 172.16.0.6 via ge-0/0/1.0, Push 10000
                    [BGP/170] 00:40:00, localpref 100, from 203.0.113.0
                      AS path: 64512 64516 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10000
                       to 172.16.0.6 via ge-0/0/1.0, Push 10000
5:203.0.113.4:10::0::10.1.255.2::32/248
                   *[BGP/170] 00:40:00, localpref 100, from 203.0.113.1
                      AS path: 64513 64516 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10000
                       to 172.16.0.6 via ge-0/0/1.0, Push 10000
                    [BGP/170] 00:40:00, localpref 100, from 203.0.113.0
                      AS path: 64512 64516 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 10000
                       to 172.16.0.6 via ge-0/0/1.0, Push 10000

TenantB

TenantB.evpn.0: 13 destinations, 23 routes (13 active, 0 holddown, 0 hidden)
Restart Complete
+ = Active Route, - = Last Active, * = Both

2:203.0.113.3:65534::20201::aa:bb:cc:80:12:00::10.2.201.11/304 MAC/IP
                   *[BGP/170] 00:01:01, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20201
                       to 172.16.0.6 via ge-0/0/1.0, Push 20201
                    [BGP/170] 00:01:01, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20201
                       to 172.16.0.6 via ge-0/0/1.0, Push 20201
2:203.0.113.3:65534::20202::aa:bb:cc:80:12:00::10.2.202.11/304 MAC/IP
                   *[BGP/170] 00:01:05, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20202
                       to 172.16.0.6 via ge-0/0/1.0, Push 20202
                    [BGP/170] 00:01:05, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20202
                       to 172.16.0.6 via ge-0/0/1.0, Push 20202
2:203.0.113.4:65534::20201::aa:bb:cc:80:18:00::10.2.201.12/304 MAC/IP
                   *[BGP/170] 00:01:52, localpref 100, from 203.0.113.0
                      AS path: 64512 64516 I, validation-state: unverified
                       to 172.16.0.0 via ge-0/0/0.0, Push 20201
                    >  to 172.16.0.6 via ge-0/0/1.0, Push 20201
                    [BGP/170] 00:01:52, localpref 100, from 203.0.113.1
                      AS path: 64513 64516 I, validation-state: unverified
                       to 172.16.0.0 via ge-0/0/0.0, Push 20201
                    >  to 172.16.0.6 via ge-0/0/1.0, Push 20201
2:203.0.113.4:65534::20202::aa:bb:cc:80:19:00::10.2.202.13/304 MAC/IP
                   *[BGP/170] 00:02:18, localpref 100, from 203.0.113.0
                      AS path: 64512 64516 I, validation-state: unverified
                       to 172.16.0.0 via ge-0/0/0.0, Push 20202
                    >  to 172.16.0.6 via ge-0/0/1.0, Push 20202
                    [BGP/170] 00:02:18, localpref 100, from 203.0.113.1
                      AS path: 64513 64516 I, validation-state: unverified
                       to 172.16.0.0 via ge-0/0/0.0, Push 20202
                    >  to 172.16.0.6 via ge-0/0/1.0, Push 20202
[...]
5:203.0.113.3:20::0::10.2.201.0::24/248
                   *[BGP/170] 00:38:00, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20000
                       to 172.16.0.6 via ge-0/0/1.0, Push 20000
                    [BGP/170] 00:38:00, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20000
                       to 172.16.0.6 via ge-0/0/1.0, Push 20000
5:203.0.113.3:20::0::10.2.202.0::24/248
                   *[BGP/170] 00:38:00, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20000
                       to 172.16.0.6 via ge-0/0/1.0, Push 20000
                    [BGP/170] 00:38:00, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20000
                       to 172.16.0.6 via ge-0/0/1.0, Push 20000
5:203.0.113.3:20::0::10.2.255.1::32/248
                   *[BGP/170] 00:38:01, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                       to 172.16.0.0 via ge-0/0/0.0, Push 20000
                    >  to 172.16.0.6 via ge-0/0/1.0, Push 20000
                    [BGP/170] 00:38:01, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                       to 172.16.0.0 via ge-0/0/0.0, Push 20000
                    >  to 172.16.0.6 via ge-0/0/1.0, Push 20000
5:203.0.113.4:20::0::10.2.201.0::24/248
                   *[BGP/170] 00:37:59, localpref 100, from 203.0.113.1
                      AS path: 64513 64516 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20000
                       to 172.16.0.6 via ge-0/0/1.0, Push 20000
                    [BGP/170] 00:37:59, localpref 100, from 203.0.113.0
                      AS path: 64512 64516 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20000
                       to 172.16.0.6 via ge-0/0/1.0, Push 20000
5:203.0.113.4:20::0::10.2.202.0::24/248
                   *[BGP/170] 00:37:59, localpref 100, from 203.0.113.1
                      AS path: 64513 64516 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20000
                       to 172.16.0.6 via ge-0/0/1.0, Push 20000
                    [BGP/170] 00:37:59, localpref 100, from 203.0.113.0
                      AS path: 64512 64516 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0, Push 20000
                       to 172.16.0.6 via ge-0/0/1.0, Push 20000
5:203.0.113.4:20::0::10.2.255.2::32/248
                   *[BGP/170] 00:37:59, localpref 100, from 203.0.113.0
                      AS path: 64512 64516 I, validation-state: unverified
                       to 172.16.0.0 via ge-0/0/0.0, Push 20000
                    >  to 172.16.0.6 via ge-0/0/1.0, Push 20000
                    [BGP/170] 00:37:59, localpref 100, from 203.0.113.1
                      AS path: 64513 64516 I, validation-state: unverified
                       to 172.16.0.0 via ge-0/0/0.0, Push 20000
                    >  to 172.16.0.6 via ge-0/0/1.0, Push 20000

Diese o.g. EVPN-Tabellen dienen im Wesentlichen als Bindeglied zu den jeweiligen IPv4-Routingtabellen für beide VRFs. Die einzelnen EVPN-Routen werden vom Routing-Daemon rpd aufgegriffen, verarbeitet und in die beiden folgenden Routingtabellen übergeben:

  • TenantA.inet.0
  • TenantB.inet.0

Auch diese Tabellen können entsprechend mit dem passenden show route table Befehl angezeigt werden. Wie hier am Beispiel des Leaf1, kann man gut erkenn, wie aus den einzelnen EVPN-Routen die zugehörigen IPv4-Routen abgeleitet werden: TenantA

TenantA.evpn.0: 9 destinations, 15 routes (9 active, 0 holddown, 0 hidden)
Restart Complete
+ = Active Route, - = Last Active, * = Both

[...]
TenantA.inet.0: 9 destinations, 13 routes (9 active, 0 holddown, 0 hidden)
Restart Complete
@ = Routing Use Only, # = Forwarding Use Only
+ = Active Route, - = Last Active, * = Both

10.1.101.0/24      *[Direct/0] 00:40:09
                    >  via irb.101
                    [EVPN/170] 00:40:10
                       to 172.16.0.0 via ge-0/0/0.0
                    >  to 172.16.0.6 via ge-0/0/1.0
                    [EVPN/170] 00:39:59
                       to 172.16.0.0 via ge-0/0/0.0
                    >  to 172.16.0.6 via ge-0/0/1.0
10.1.101.1/32      *[Local/0] 00:40:09
                       Local via irb.101
10.1.101.11/32     *[EVPN/7] 00:31:05
                    >  via irb.101
10.1.102.0/24      *[Direct/0] 00:40:09
                    >  via irb.102
                    [EVPN/170] 00:40:10
                       to 172.16.0.0 via ge-0/0/0.0
                    >  to 172.16.0.6 via ge-0/0/1.0
                    [EVPN/170] 00:39:59
                       to 172.16.0.0 via ge-0/0/0.0
                    >  to 172.16.0.6 via ge-0/0/1.0
10.1.102.1/32      *[Local/0] 00:40:09
                       Local via irb.102
10.1.102.11/32     *[EVPN/7] 00:31:05
                    >  via irb.102
10.1.255.0/32      *[Direct/0] 00:56:10
                    >  via lo0.2
10.1.255.1/32      *[EVPN/170] 00:40:10
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0
10.1.255.2/32      *[EVPN/170] 00:39:59
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0

TenantB

TenantB.inet.0: 11 destinations, 15 routes (11 active, 0 holddown, 0 hidden)
Restart Complete
@ = Routing Use Only, # = Forwarding Use Only
+ = Active Route, - = Last Active, * = Both

10.2.201.0/24      *[Direct/0] 00:37:59
                    >  via irb.201
                    [EVPN/170] 00:37:59
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0
                    [EVPN/170] 00:37:58
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0
10.2.201.1/32      *[Local/0] 00:37:59
                       Local via irb.201
10.2.201.11/32     *[EVPN/7] 00:01:00
                    >  via irb.201
10.2.201.12/32     *[EVPN/7] 00:01:51
                       to 172.16.0.0 via ge-0/0/0.0
                    >  to 172.16.0.6 via ge-0/0/1.0
10.2.202.0/24      *[Direct/0] 00:37:58
                    >  via irb.202
                    [EVPN/170] 00:37:59
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0
                    [EVPN/170] 00:37:58
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0
10.2.202.1/32      *[Local/0] 00:37:58
                       Local via irb.202
10.2.202.11/32     *[EVPN/7] 00:01:04
                    >  via irb.202
10.2.202.13/32     *[EVPN/7] 00:02:17
                       to 172.16.0.0 via ge-0/0/0.0
                    >  to 172.16.0.6 via ge-0/0/1.0
10.2.255.0/32      *[Direct/0] 00:38:02
                    >  via lo0.3
10.2.255.1/32      *[EVPN/170] 00:38:00
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0
10.2.255.2/32      *[EVPN/170] 00:37:58
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0

Wie man in den Outputs erkennen kann, wird für die einzelnen IPv4-Routen auch [EVPN] als Ursprung angegeben - und zwar mit verschiedenen Routepräferenzen:

  • eine Route Preference von 7 für Routen, die von EVPN Typ-2 Routen abgeleitet wurden
  • eine Route Preference von 170 für Routen, die von EVPN Typ-5 Routen abgeleitet wurden.

💡 Besonderheit
Auch im TenantA sind Routen mit Route Preference 7 zu finden. Diese beziehen sich auf lokal angebundene Hosts, für die der lokale Leaf entsprechende Typ-2 (MAC/IP) EVPN-Routen erstellt.
📝 Hinweis
Diese Werte sind Junos-Standardwerte (siehe dazu LINK)

L2-/L3-unabhängige Routen

Wer den Artikel bis hierhin gelesen hat, der hat mitunter bereits vergessen, dass es noch eine weitere EVPN Routing-Tabelle gibt, die neben der L2-bezogenen MAC-VRF Tabelle und den Tenant-spezifischen L3-Tabellen existiert.

Diese Routingtabelle mit dem Namen __default_evpn__.evpn.0 weist mehrere Besonderheiten auf:

  • Einerseits fasst sie alle Fabric-globalen EVPN-Routen vom Typ-1 und Typ-4 zusammen, die im Kontext der ESI-Multihoming Distributed Forwared (DF) Election benötigt werden.
  • Andererseits wird sie aufgrund der Fokussierung auf die DF-Election auch nur auf jenen Leaf-Switches genutzt, die auch tatsächlich Multihomed-Hosts anbinden bzw. ESI-Multihomed Segmente beherbergen.

Dies wird ersichtlich, wenn man den Inhalt der Tabelle __default_evpn__.evpn.0 auf dem Leaf1 (mit multi-homed Hosts) mit dem Inhalt auf dem Leaf3 (nur single-homed Hosts) vergleicht: Leaf1

__default_evpn__.evpn.0: 3 destinations, 4 routes (3 active, 0 holddown, 0 hidden)
Restart Complete
+ = Active Route, - = Last Active, * = Both

1:203.0.113.2:0::020000000001000001::FFFF:FFFF/192 AD/ESI
                   *[EVPN/170] 00:31:07
                       Indirect
4:203.0.113.2:0::020000000001000001:203.0.113.2/296 ES
                   *[EVPN/170] 00:31:08
                       Indirect
4:203.0.113.3:0::020000000001000001:203.0.113.3/296 ES
                   *[BGP/170] 00:31:08, localpref 100, from 203.0.113.0
                      AS path: 64512 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0
                    [BGP/170] 00:31:08, localpref 100, from 203.0.113.1
                      AS path: 64513 64515 I, validation-state: unverified
                    >  to 172.16.0.0 via ge-0/0/0.0
                       to 172.16.0.6 via ge-0/0/1.0

Leaf3

*[leer]*

Die reinen EVPN-Routen in dieser Tabelle zu betrachten ist erst einmal wenig hilfreich, um zu ermitteln welcher Leaf bzw. VTEP das Rennen um den Designated Forwarder für ein bestimmtes Ethernet Segment gemacht hat.

Hierzu kann das Command show evpn instance designated-forwarder verwendet werden - allerdings nur auf den Leaf-Switches, die das entsprechende ESI auch anbinden.

Am Beispiel des Leaf1 sieht man dabei folgenden Output, der darauf schließen lässt, dass der VTEP mit der IP 203.0.113.3 (-> Leaf2) aktuell der Designated Forwarder für das Segment 00:02:00:00:00:00:01:00:00:01 ist.

aosadmin@leaf1> show evpn instance designated-forwarder
Instance: evpn-1
  Number of ethernet segments: 5
    ESI: 00:02:00:00:00:00:01:00:00:01
      Designated forwarder: 203.0.113.3
    ESI: 05:00:00:fc:02:00:00:27:75:00
    ESI: 05:00:00:fc:02:00:00:27:76:00
    ESI: 05:00:00:fc:02:00:00:4e:e9:00
    ESI: 05:00:00:fc:02:00:00:4e:ea:00
💡 Tipp
Details zum DF-Election Prozess in Junos können diesem Hersteller-Artikel entnommen werden.

Fazit

In diesem Artikel habe ich versucht, einen möglichst guten Überblick über die Zusammenhänge und Funktionsweisen im Kontext der EVPN Control Plane zu vermitteln. Ich bin dabei darauf eingegangen wie EVPN-Routen zwischen den Fabric-Switches ausgetauscht werden und wie diese Informationen Junos-intern strukturiert und weiterverarbeitet werden.

Ich gebe zu, dass der Artikel ziemlich umfangreich geworden ist, insbesondere durch die zahlreichen langen Outputs der verschiedenen Routingtabellen. Mir war es aber wichtig, die Erläuterungen im Text mit konkreten Beispielen aus der Demo-Umgebung zu verbinden, um es allen Lesern zu ermöglichen, die Zusammenhänge bestmöglich nachvollziehen zu können.

Wer den Artikel nicht komplett von Anfang bis Ende gelesen hat (was ich sehr gut verstehen kann 😁), kann zumindest anhand der einzelnen Abschnitte gezielt in die Bereiche springen, die von Interesse sind.

Selbst wenn ihr nur eine Information aus dem Artikel mitnehmt, dann ist es wahrscheinlich die Darstellung der Zusammenhänge aus dem Überblick, die man jederzeit als eine Art Troubleshooting-Leitfaden bzw. Checkliste wiederverwenden kann.

Für all jene, für die der Artikel allerdings eher zu oberflächlich war, kann ich schon verraten, dass ich in weiteren Artikeln noch detaillierter auf einzelne Aspekte eingehen werde.