Heute wollen wir wie versprochen über die Konfiguration von ECMP (Equal Cost Multipath) mit JunOS berichten. Nach ein paar Worten zu den Grundlagen holen wir uns zur Demonstration zwei bzw. drei vSRX (aka Firefly Perimeter) ins Labor und schauen uns die Praxis und die entsprechende JunOS-Syntax an.
Grundlagen:
Über den Unterschied zwischen RIB und FIB
Bei Routingtabellen muss man grundsätzlich zwischen RIB (Routing Information Base) und FIB (Forwarding Information Base bzw. Forwarding Table) unterscheiden.
Die RIB wird aus verschiedenen Routingprotokollen generiert (Static, OSPF, IS/IS, BGP) und daraus die FIB berechnet und in die PFE (Packet Forwarding Engine) gepusht, welche dann das eigentliche Routing der Pakete übernimmt.
Welche Routen aus der RIB kommen in die FIB?
Beim Berechnen der FIB muss es eine sinnvolle Entscheidung geben welche Routen aus der RIB in die FIB exportiert werden.
Hierzu gibt es einige Entscheidungskritierien (garantiert unvollständige Liste):
- Das verwendete Routingprotokoll bzw. dessen Priorität (aka Preference). Link für Details bei JunOS.
- Etwaig installierte Export-Filter (z.B. sollen „falsche“ Routen sollten niemals ihren Weg in die FIB finden).
- Erreichbarkeit des Nachbarrouters (aka Next-Hop).
Weiterhin kann es vorkommen dass zm selben Ziel (Prefix) mehrere unterschiedliche Routen existieren, dann wird in der Regel eine der beiden genommen (z.B. die mit dem kleineren Interfaceindex oder Next-Hop IP).
Welche Route in RIB und FIB installiert ist sieht man bei JunOS wie folgt:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
root@A1> show route inet.0: 18 destinations, 18 routes (18 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 192.168.1.0/24 *[Direct/0] 00:32:28 > via ge-0/0/1.0 192.168.1.1/32 *[Local/0] 00:32:29 Local via ge-0/0/1.0 192.168.3.0/24 *[OSPF/10] 00:27:49, metric 110 to 192.168.20.3 via ge-0/0/3.0 > to 192.168.21.4 via ge-0/0/4.0 [...] |
Bei der letzten Route sieht man zwei Next-Hops (192.168.20.3 und 192.168.21.4) für das Ziel 192.168.3.0/24 in der RIB vorhanden sind.
1 2 3 4 5 6 |
root@A1> show route forwarding-table destination 192.168.3.0/24 Routing table: default.inet Internet: Destination Type RtRef Next hop Type Index NhRef Netif 192.168.3.0/24 user 0 192.168.21.4 ucst 572 6 ge-0/0/4.0 [...] |
Die oben durchgeführte Kontrolle in der Forwarding-Table ergibt, daß der mit „>“ marktierte Eintrag aus „show route“ in der FIB installiert wurde.
Wie aktiviere ich ECMP auf JunOS?
Nachdem klar ist wie es ohne ECMP funktioniert, können wir unser JunOS jetzt dazu bringen mehr als eine Route pro Destination in die FIB zu installieren. Hier müssen wir leider ein bischen unterscheiden zwischen den Geräteklassen „EX und SRX“ und „MX, M, T und PTX“.
„EX und SRX“ (Link zur Herstellerdokumentation)
Leider kann diese Geräteklasse nur „per-flow“ ECMP, was in der Praxis jedoch sowieso die sinnvollste Variante ist:
1 2 3 4 5 6 7 8 9 10 11 12 |
routing-options { forwarding-table { export ECMP-per-flow; } } policy-options { policy-statement ECMP-per-flow { then { load-balance per-packet; } } } |
Nein, dieses Snippet hat keinen Fehler, hier steht wirklich „load-balance per-packet“ obwohl eigentlich „load-balance per-flow“ gemeint ist.
Juniper hat hier wohl versucht gleiche Syntax bei kleinerem Featuresset (im Vergleich zu „echten Routern“ (siehe unten) zu etablieren, was auf das erste Lesen ohne Hintergrundwissen ziemlich komisch erscheint.
„MX, M, T und PTX“ (Link1 und Link2 zur Herstellerdokumentation)
Auf den größeren Systemen von Juniper hat man dann neben der Qual der Wahl auch noch ein bischen die Qual der Dokumentationen:
1 2 3 4 5 6 7 8 9 10 11 12 |
routing-options { forwarding-table { export ECMP-per-packet; } } policy-options { policy-statement ECMP-per-packet { then { load-balance per-packet; } } } |
Dieses Config Snippet aktiviert erst mal „per-packet“ Loadbalancing, genau so wie man das auch erwartet.
1 2 3 4 5 6 7 8 |
forwarding-options { load-balance { indexed-load-balance; per-flow { hash-seed; } } } |
Mit diesem zusätzlichen Statement wird dann „per-flow“ Loadbalancing aktiviert. Zumindest interpretiere ich die Dokumentation so.
Vorsicht: Ungetestete Config! Ein Test mit unseren Labor-MXen steht noch aus, die werden gerade von anderen Setups gebunden (Ach, so eine MX-Series als VM wäre doch wirklich was Tolles! *Wunschdenk*).
Wie kontrolliert man ob ECMP aktiviert ist?
Idealerweise kann man sich natürlich die Config anschauen und kontrollieren ob o.g. Einstellungen gesetzt sind.
Alternativ dazu kann man natürlich auch die FIB befragen:
1 2 3 4 5 6 7 |
root@A1> show route forwarding-table destination 192.168.3.0/24 Routing table: default.inet Internet: Destination Type RtRef Next hop Type Index NhRef Netif 192.168.3.0/24 user 0 ulst 262142 3 192.168.20.3 ucst 573 5 ge-0/0/3.0 192.168.21.4 ucst 572 5 ge-0/0/4.0 |
Beispiel 1: „Dr. Trivialo“
Als Grundlagenbeispiel nehmen wir zwei Router A1 und A2 welche nach folgendem Schaubild verbunden sind:
Als Routing Protokoll nutzen wir OSPF mit einer Area 0 und ohne Real World Schnickschnack wie Kosten, Loop-Back-IPs, RouterIDs, MD5 oder gar BFD – bitte nicht im wirklichen Leben nachmachen!
Konfiguration Router A1 (in „set-Notation“, weil kompakter):
1 2 3 4 5 6 7 8 9 10 11 12 |
[...] set interfaces ge-0/0/1 unit 0 family inet address 192.168.1.1/24 set interfaces ge-0/0/2 unit 0 family inet address 10.0.0.1/24 set interfaces ge-0/0/3 unit 0 family inet address 10.0.1.1/24 set routing-options forwarding-table export ECMP-per-flow set protocols ospf area 0.0.0.0 interface ge-0/0/1.0 set protocols ospf area 0.0.0.0 interface ge-0/0/2.0 set protocols ospf area 0.0.0.0 interface ge-0/0/3.0 set policy-options policy-statement ECMP-per-flow then load-balance per-packet set security forwarding-options family inet6 mode packet-based set security forwarding-options family mpls mode packet-based set security forwarding-options family iso mode packet-based |
Konfiguration Router A2 (in „set-Notation“, weil kompakter):
1 2 3 4 5 6 7 8 9 10 11 12 |
[...] set interfaces ge-0/0/1 unit 0 family inet address 192.168.2.1/24 set interfaces ge-0/0/2 unit 0 family inet address 10.0.0.2/24 set interfaces ge-0/0/3 unit 0 family inet address 10.0.1.2/24 set routing-options forwarding-table export ECMP-per-flow set protocols ospf area 0.0.0.0 interface ge-0/0/1.0 set protocols ospf area 0.0.0.0 interface ge-0/0/2.0 set protocols ospf area 0.0.0.0 interface ge-0/0/3.0 set policy-options policy-statement ECMP-per-flow then load-balance per-packet set security forwarding-options family inet6 mode packet-based set security forwarding-options family mpls mode packet-based set security forwarding-options family iso mode packet-based |
Hinweis: mit den „security forwarding-options […]“ wird die vSRX komplett auf den Packet-Mode umgestellt, d.h. Stateful Firewall bzw. Flow-Mode ist deaktiviert und das Ding ist ein reiner Router. 😉
Nach erfolgreichem commit auf beiden Routern schauen RIB und FIB auf A1 so aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
root@A1> show route protocol ospf inet.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 192.168.2.0/24 *[OSPF/10] 00:07:54, metric 2 > to 10.0.0.2 via ge-0/0/2.0 to 10.0.1.2 via ge-0/0/3.0 224.0.0.5/32 *[OSPF/10] 00:20:24, metric 1 MultiRecv root@A1> show route forwarding-table destination 192.168.2.0/24 Routing table: default.inet Internet: Destination Type RtRef Next hop Type Index NhRef Netif 192.168.2.0/24 user 0 ulst 262142 2 10.0.0.2 ucst 581 2 ge-0/0/2.0 10.0.1.2 ucst 582 2 ge-0/0/3.0 |
TaDa!!! Die ECMP-Route ist installiert. Na das war ja einfach. 🙂
Beispiel 2: „Das Magische Dreieck“
Dass das Leben in Wirklichkeit nicht immer ganz so einfach ist zeigt folgendes Beispiel aus der Praxis.
Die hier dargestelle Herausforderung ist, dass die Router B1 und B2 ein Subnetz an „normalen Clients“ über VRRP bereitstellen und gleichzeitig aber die Verbindungen „A1-B1“ und „A1-B2“ per ECMP genutzt werden sollen. B1 wäre in unserem Beispiel der VRRP-Master.
Um das Ziel zu erreichen kann man sich behelfen in dem man die Kosten der Interfaces an den jeweilgen Routern entsprechend so einstellt, dass in Summe immer das selbe Gewicht rauskommt.
Auch hier gibt es keinen Real World Schnick Schnack um das Auge auf dem Wesentlichen zu haben. Auch verzichten wir auf die VRRP-Config. 🙂
Konfiguration Router A1 (in „set-Notation“, weil kompakter):
1 2 3 4 5 6 7 8 9 10 11 12 |
[...] set interfaces ge-0/0/1 unit 0 family inet address 192.168.1.1/24 set interfaces ge-0/0/2 unit 0 family inet address 10.0.0.1/24 set interfaces ge-0/0/3 unit 0 family inet address 10.0.1.1/24 set routing-options forwarding-table export ECMP-per-flow set protocols ospf area 0.0.0.0 interface ge-0/0/1.0 passive set protocols ospf area 0.0.0.0 interface ge-0/0/2.0 metric 100 set protocols ospf area 0.0.0.0 interface ge-0/0/3.0 metric 100 set policy-options policy-statement ECMP-per-flow then load-balance per-packet set security forwarding-options family inet6 mode packet-based set security forwarding-options family mpls mode packet-based set security forwarding-options family iso mode packet-based |
Konfiguration Router B1:
1 2 3 4 5 6 7 8 9 10 11 12 |
[...] set interfaces ge-0/0/1 unit 0 family inet address 192.168.2.1/24 set interfaces ge-0/0/2 unit 0 family inet address 10.0.0.2/24 set interfaces ge-0/0/3 unit 0 family inet address 10.0.2.1/24 set routing-options forwarding-table export ECMP-per-flow set protocols ospf area 0.0.0.0 interface ge-0/0/1.0 passive set protocols ospf area 0.0.0.0 interface ge-0/0/2.0 metric 100 set protocols ospf area 0.0.0.0 interface ge-0/0/3.0 metric 10 set policy-options policy-statement ECMP-per-flow then load-balance per-packet set security forwarding-options family inet6 mode packet-based set security forwarding-options family mpls mode packet-based set security forwarding-options family iso mode packet-based |
Konfigurtion Router B2:
1 2 3 4 5 6 7 8 9 10 11 12 |
[...] set interfaces ge-0/0/1 unit 0 family inet address 192.168.2.2/24 set interfaces ge-0/0/2 unit 0 family inet address 10.0.1.2/24 set interfaces ge-0/0/3 unit 0 family inet address 10.0.2.2/24 set routing-options forwarding-table export ECMP-per-flow set protocols ospf area 0.0.0.0 interface ge-0/0/1.0 passive set protocols ospf area 0.0.0.0 interface ge-0/0/2.0 metric 90 set protocols ospf area 0.0.0.0 interface ge-0/0/3.0 metric 10 set policy-options policy-statement ECMP-per-flow then load-balance per-packet set security forwarding-options family inet6 mode packet-based set security forwarding-options family mpls mode packet-based set security forwarding-options family iso mode packet-based |
Neben den eingestellten Kosten (metric) für die Interfaces wurden noch die User-Interfaces mit „passive“ versehen. Damit erreicht man, dass auf den Interfaces keine OSPF-Pakete versendet werden, um OSPF-Kommunikation der Router über diese Interfaces zu vermeiden.
Die RIBs der Router sind dann so wie gewünscht installiert:
- 192.168.1.0/24 und 192.168.2.0/24 sind auf A1 und B1 gemultipathed.
- Auf B2 sind alle Routen auschliesslich gesinglepathed.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
root@A1> show route protocol ospf inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 10.0.2.0/24 *[OSPF/10] 00:42:30, metric 110 > to 10.0.0.2 via ge-0/0/2.0 to 10.0.1.2 via ge-0/0/3.0 192.168.2.0/24 *[OSPF/10] 00:43:39, metric 101 to 10.0.0.2 via ge-0/0/2.0 > to 10.0.1.2 via ge-0/0/3.0 224.0.0.5/32 *[OSPF/10] 01:44:33, metric 1 MultiRecv |
1 2 3 4 5 6 7 8 9 10 11 12 |
root@B1> show route protocol ospf inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 10.0.1.0/24 *[OSPF/10] 00:43:40, metric 100 > to 10.0.2.2 via ge-0/0/3.0 192.168.1.0/24 *[OSPF/10] 00:43:40, metric 101 > to 10.0.0.1 via ge-0/0/2.0 to 10.0.2.2 via ge-0/0/3.0 224.0.0.5/32 *[OSPF/10] 00:55:45, metric 1 MultiRecv |
1 2 3 4 5 6 7 8 9 10 11 |
root@B2> show route protocol ospf inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 10.0.0.0/24 *[OSPF/10] 00:44:12, metric 110 > to 10.0.2.1 via ge-0/0/3.0 192.168.1.0/24 *[OSPF/10] 00:44:12, metric 91 > to 10.0.1.1 via ge-0/0/2.0 224.0.0.5/32 *[OSPF/10] 00:56:17, metric 1 MultiRecv |
Die Tatsache, dass B2 nur single-path Routen hat ist nicht weiter tragisch, da dieser Router in der Regel der Backup Router ist.
Wäre man theoretisch in der Lage auch auf B2 ECMP-Routen via B1 und A1 installieren zu lassen, werden 50% der Flows wieder von B2 auf B1 zurückreflektiert, was eine lustige Loop zur Folge hätte. Ein Sachverhalt den OSPF zum Glück in der Praxis verhindert.
Wie schon beim letzten Artikel über die vSRX zum Ende noch eine kleine Knobelaufgabe:
Wie könnte man „rein theoretisch“ in unserem Beispiel OSPF dazu bringen auf den Routern B1 und B2 das Netz 192.168.1.0/24 doch „zu multipathen“ und wie verhindert OSPF das in der Praxis?
Die ersten beiden Antworten bekommen wie immer ein kleines Dankeschön von uns.
Zum Thema „virtuelle MX“: Es gibt Gerüchte, dass Juniper genau dies plant. Codename Mx86. Nichts genaues weiss man nicht. Mitbekommen habe ich das auf der letzten JGPC. Toll wäre es ja.