MPLS LDP
Origine
LDP (Label Distribution Protocol) a été initialement évoqué dans la RFC 3031 décrivant l'architecture MPLS (Multiprotocol Label Switching) avant d'être spécifié dans la RFC 3036 :
The MPLS architecture defines a label distribution protocol
as a set of procedures by which one Label Switched Router (LSR)
informs another of the meaning of labels used to forward traffic
between and through them.
Son rôle est clair, à savoir assurer la distribution des labels entre LSR. Il est par la suite rappelé qu'il n'y a pas forcément qu'un seul protocole pour cela :
The MPLS architecture does not assume a single label distribution
protocol. In fact, a number of different label distribution
protocols are being standardized.
Toutefois, LDP est quasiment l'unique dans la pratique. Plus anciennement, il y avait aussi TDP (Tag Distribution Protocol) qui est, comme souvent, la version propriétaire de Cisco avant la standardisation établie par l'IETF (Internet Engineering Task Force). Est également évoquée l'utilisation de BGP (Border Gateway Protocol) pour la distribution des labels :
If there is a standard, widely deployed routing algorithm which
distributes those routes, it can be argued that label distribution is
best achieved by piggybacking the label distribution on the
distribution of the routes themselves.
For example, BGP distributes such routes, and if a BGP speaker needs
to also distribute labels to its BGP peers, using BGP to do the label
distribution has a number of advantages.
En effet, ce dernier est tentant puisque son rôle primaire est justement la distribution des routes entre pairs. La distribution des labels viendrait s'adjoindre (piggybacking) aux routes distribuées. Ceci a été spécifié dans la RFC 3107. Finalement, BGP (MP-BGP pour être précis) est surtout utilisé dans la distribution des labels dédiés aux VPN (L2 et L3) sur MPLS : LDP distribue le premier niveau de label dédié à l'IGP—comme nous allons le voir ci-dessous—et MP-BGP le deuxième niveau de label dédié aux VPN—comme nous le verrons dans un prochain article. Enfin, noter que des travaux restés au statut de draft ont été menés pour distribuer les labels dans les IGP : draft-gredler-rtgwg-igp-label-advertisement, draft-gredler-isis-label-advertisement et draft-gredler-ospf-label-advertisement. C'est d'ailleurs de cette façon, dans les IGP, que sont distribués les labels dans le Segment Routing (technique de routage à la source qui utilise une stack de labels MPLS).
La maquette utilisée
Nous allons étudier comment sont alloués les labels puis distribués entre LSR à l'aide de la maquette suivante :
10.0.0.2
et auprès de R3 avec l'ID 10.0.0.5
.
Cela n'empêcherait pas le bon fonctionnement (les sessions LDP monteraient bien)
mais point de vue conceptuel cependant, qu'un même LSR se présente avec deux ID différents dans un même AS n'est de toute évidence pas une bonne pratique.
Le lien avec IP
Cette section peut sembler évidente mais rappelons que MPLS est fortement lié au protocole L3 utilisé—bien souvent IP—comme le rappelle sa RFC :
MPLS stands for "Multiprotocol" Label Switching, multiprotocol
because its techniques are applicable to ANY network layer protocol.
In this document, however, we focus on the use of IP as the network
layer protocol.
Autrement dit, cela signifie qu'avant l'allocation des labels, leur distribution et le label switching proprement dit, il y a tout d'abord des réseaux IP—comme illustré dans la maquette précédente avec trois réseaux IP. Et c'est bien normal, les LSR parleront LDP via ces réseaux IP (plan de contrôle) avant de pouvoir parler MPLS sans utiliser IP (plan de données). Comme dans un AS, tous ces réseaux IP doivent être routés entre eux, soit statiquement soit dynamiquement avec un IGP. C'est une fois l'ensemble du routage IP opérationnel qu'il devient cohérent d'activer MPLS (et LDP) sur ce backbone IP alors nommé backbone IP/MPLS. Enfin, retenir que LDP constitue le plan de contrôle de MPLS (plan de données), à l'instar des IGP qui constituent le plan de contrôle d'IP (plan de données).
Étape 1 : l'allocation des labels
Les labels sont alloués localement par chaque LSR. Il y a une unicité locale mais pas globale (un même label peut être utilisé par différents LSR). Les règles sont les suivantes :
- Toute route directement connectée se voit allouer le label particulier
Implicit NULL
soit3
(nous verrons plus bas pourquoi). - Toute autre route se voit allouer un label à partir de
16
(la borne maximale dépend des équipements, par exemple100000
chez certains Cisco). - Les labels de
0
à15
sont en fait des labels particuliers réservés dans la RFC 3032.
Exemple dans notre maquette :
R1 R2 R3 R4
+-------------+------------+-------+ +-------------+------------+-------+ +-------------+------------+-------+ +-------------+------------+-------+
| Route | Type | Label | | Route | Type | Label | | Route | Type | Label | | Route | Type | Label |
+-------------+------------+-------+ +-------------+------------+-------+ +-------------+------------+-------+ +-------------+------------+-------+
| 10.0.0.0/30 | Connected | 3 | | 10.0.0.0/30 | Connected | 3 | | 10.0.0.4/30 | Connected | 3 | | 10.0.0.8/30 | Connected | 3 |
| 10.0.1.1/32 | Connected | 3 | | 10.0.0.4/30 | Connected | 3 | | 10.0.0.8/30 | Connected | 3 | | 10.0.1.4/32 | Connected | 3 |
| 10.0.0.4/30 | Static/IGP | 16 | | 10.0.1.2/32 | Connected | 3 | | 10.0.1.3/32 | Connected | 3 | | 10.0.0.0/30 | Static/IGP | 16 |
| 10.0.0.8/30 | Static/IGP | 17 | | 10.0.0.8/30 | Static/IGP | 16 | | 10.0.0.0/30 | Static/IGP | 19 | | 10.0.0.4/30 | Static/IGP | 17 |
| 10.0.1.2/32 | Static/IGP | 18 | | 10.0.1.1/32 | Static/IGP | 17 | | 10.0.1.1/32 | Static/IGP | 18 | | 10.0.1.1/32 | Static/IGP | 18 |
| 10.0.1.3/32 | Static/IGP | 19 | | 10.0.1.3/32 | Static/IGP | 18 | | 10.0.1.2/32 | Static/IGP | 17 | | 10.0.1.2/32 | Static/IGP | 19 |
| 10.0.1.4/32 | Static/IGP | 20 | | 10.0.1.4/32 | Static/IGP | 19 | | 10.0.1.4/32 | Static/IGP | 16 | | 10.0.1.3/32 | Static/IGP | 20 |
+-------------+------------+-------+ +-------------+------------+-------+ +-------------+------------+-------+ +-------------+------------+-------+
8.8.8.0/24
est joignable via 10.0.1.1
(R1),
le label 18
sera utilisé en cas d'un ping vers 8.8.8.8
.
Les labels sont alloués au fur et à mesure de l'apparition des routes dans les routeurs. Cet ordre d'apparition dépend des annonces de l'IGP ainsi que des changements sur le réseau. Dans cette maquette simple, j'ai utilisé des routes statiques et dans un ordre volontairement inversé pour R3 afin d'avoir des labels différents, ce qui permettra de bien visualiser le label switching dans l'étape 3.
Plus généralement, les labels ne sont pas alloués à des routes mais à des FEC (Forwarding Equivalence Class). Une FEC est un groupe de paquets ayant des points communs. Chaque route est bien une FEC, le point commun des paquets étant le réseau de destination. La RFC de MPLS explique bien ceci :
A label is a short, fixed length, locally significant identifier
which is used to identify a FEC.
Most commonly, a packet is assigned to a FEC based (completely or
partially) on its network layer destination address.
Voici des extraits de R2 et de R3 (les labels ont seulement été alloués localement et non distribués encore) :
R2 | R3 |
---|---|
|
|
Pour les curieux, voici les FIB de R2 et R3 :
R2 | R3 |
---|---|
|
|
Étape 2 : la distribution des labels
Maintenant que chaque LSR a alloué des labels à chaque FEC (chaque route), il leur reste à les distribuer aux voisins :
10.0.1.1/32
car c'est son nexthop pour cette FEC ;
il demanderait à R3 les labels associés à 10.0.0.8/30
, 10.0.1.3/32
et 10.0.1.4/32
car c'est son nexthop pour ces FEC—ce
n'est pas plus compliqué que cela et finalement assez intuitif,
le nexthop étant appelé downstream LSR et le demandeur upstream LSR.
Voyons une capture pour analyser concrètement un message LDP Label Mapping Message
:
Voici les LIB et les LFIB de R2 et R3 après distribution des labels :
R2 | R3 |
---|---|
|
|
Nous retrouvons dans les LIB, pour chaque FEC, les labels distribués par chaque LSR voisin.
Par exemple, pour la FEC 10.0.1.4/32
, R2 a :
- Attribué localement le label
19
—in label (celui envoyé aux voisins et que nous retrouvons donc dans la LIB de R3). - Reçu de R1 le label
20
—out label. - Reçu de R3 le label
16
—out label.
R2 a reçu deux labels pour une même FEC.
Le flag inuse
indique lequel est utilisé dans le plan de données (LFIB).
Le choix est effectué selon ses propres routes : le nexthop de 10.0.1.4/32
étant R3 pour R2,
c'est donc naturellement le label associé qui a été choisi et qui apparaît dans la LFIB.
Apparaît aussi dans cette dernière le label qui sera appliqué en sortie vers R3 :
si R2 reçoit un paquet à destination de 10.0.1.4/32
de la part de R1, ce sera avec le label 19
,
lequel sera changé en label 16
vers R3—c'est
le label switching proprement dit du plan de données.
Remarquer enfin le terme de Pop tag
dans les LFIB de R2 et de R3
qui est évidemment lié au label particulier Implicit NULL
évoqué plus haut.
Nous reviendrons dessus dans l'étape suivante, une illustration permettant plus facilement de comprendre le mécanisme.
Étape 3 : le label switching
Voyons maintenant ce qu'il se passe si R1 ping R4 avec des captures :
Pour les deux premières captures, aucune surprise,
le label switching a bien opéré conformément aux LFIB de R1 et de R2 :
R1 a encapsulé le paquet IP dans MPLS en appliquant le label 19
,
lequel a été changé par R2 en label 16
.
Ce que nous voyons sur ces captures, c'est le fameux LSP (Label Switch Path)
qui en pratique s'étend à plus de deux sauts.
Sur la dernière capture cependant, nous ne voyons plus de MPLS. R3 a enlevé le label avant d'envoyer le paquet à R4 qui est le routeur de destination. En d'autres termes, l'avant-dernier (penultimate) routeur a enlevé le label avant d'envoyer le paquet au dernier (ultimate) routeur du LSP. Ce mécanisme bien connu s'appelle PHP (Penultimate Hop Popping) et a été décrit dans l'architecture MPLS :
Once R[n-1] has decided to send the packet to Rn, the label
no longer has any function, and need no longer be carried.
There is also a practical advantage to doing penultimate hop popping.
If one does not do this, then when the LSP egress receives a packet,
it first looks up the top label, and determines as a result of that
lookup that it is indeed the LSP egress. Then it must pop the stack,
and examine what remains of the packet. If there is another label on
the stack, the egress will look this up and forward the packet based
on this lookup. (In this case, the egress for the packet's level m
LSP is also an intermediate node for its level m-1 LSP.) If there is
no other label on the stack, then the packet is forwarded according
to its network layer destination address. Note that this would
require the egress to do TWO lookups, either two label lookups or a
label lookup followed by an address lookup.
Pour résumer cet extrait, rien n'empêche en réalité de conserver le label et de l'envoyer au dernier routeur—ce
mécanisme existe et s'appelle UHP (Ultimate Hop Popping) par opposition au PHP.
Cependant, cela ne présente aucun intérêt : nous voyons bien que R3 est adjacent à R4,
autant enlever le label pour lui éviter ce travail.
Car en effet, sans cette manipulation préalable, R4 devrait effectuer deux opérations :
enlever le label et interpréter le paquet IP
(ou interpréter le label suivant s'il s'agit d'une stack de labels,
par exemple dans le cas de VPN sur MPLS qui sera abordé dans un prochain article),
ce qui requiert du temps processeur alors que le but de MPLS est justement d'optimiser les réseaux.
R3 sait qu'il faut enlever (to pop) le label
car la route 10.0.1.4/32
lui a été annoncé avec le label Implicit NULL
dont le rôle est finalement de permettre le PHP—voici
donc l'explication de ce label particulier.
Exp
que nous pouvons voir dans les captures.
Ce champ est typiquement utilisé pour de la QoS MPLS (à l'instar des champs 802.1q et DSCP pour, respectivement, de la QoS Ethernet de la QoS IP).
Il peut être ainsi nécessaire de le transmettre au dernier routeur afin qu'il applique le comportement associé à la valeur indiquée.
Dans ce cas, le label Explicit NULL
est appliqué, c'est-à-dire la valeur 0
(RFC 3032).
Certains routeurs plus récents activent le mécanisme UHP par défaut,
les performances des équipements ayant évolué et le gain de l'optimisation PHP étant considéré négligeable.
Voici un exemple du mécanisme UHP :
R4 | R3 |
---|---|
|
|
Nous voyons dans la LIB de R3 que pour joindre les routes directement connectées de R4,
le label Explicit NULL
sera appliqué, ce que nous pouvons vérifier avec le même ping que précédemment
(de R1 à R4) :
Bonus #1 : l'ECMP (Equal-Cost Multi-path Routing)
La résilience des réseaux est souvent assurée par plusieurs routes possibles vers la même destination.
Lorsque ces routes sont à coût égal, le mécanisme d'ECMP est fréquemment appliqué :
du load balancing a alors lieu entre ces routes,
généralement en mode per-flow
par opposition au mode per-packet.
Dans le premier mode, un même flux—défini par le couple L3 (IPsource, IPdestination)
auquel peut s'ajouter le couple L4 (Portsource, Portdestination)
dans le cas TCP ou UDP—emprunte toujours le même chemin,
ce qui garantit l'ordre d'arrivée des paquets (nécessaire pour la VoIP par exemple).
Dans le deuxième mode, un même flux emprunte des chemins différents—ce
qui a souvent pour conséquence des paquets out-of-order à la destination.
Pour illustrer l'ECMP (en mode per-flow mais cela n'a pas d'importance ici), ajoutons un routeur R5 à la maquette :
Affichons les extraits de configuration pertinents de R1 et R3 (rien de particulier sur R5, voir les configurations précédentes) :
R1 | R3 |
---|---|
|
|
Une fois encore, avant même d'aborder MPLS et LDP, nous voyons que l'ECMP est présent point de vue IP : R1 et R3 ont bien chacun deux routes possibles à coût égal vers la même destination, ce qui est visible dans leur RIB et dans leur FIB. Regardons maintenant point de vue LIB et LFIB :
R1 | R3 |
---|---|
|
|
R1 a bien les deux labels actifs en même temps, ce qui est visible dans la LIB avec le flag inuse
doublement présent
et dans la LFIB avec les deux entrées pour la même FEC.
Même constat pour R3 (avec une troisième entrée dans la LIB qui correspond à l'annonce de R4 et qui n'est évidemment pas utilisé).
L'ECMP est donc bien présent également point de vue MPLS.
Le load balancing sera ensuite visible dans le plan de données.
Si R1 ping R4, la requête ICMP sera routée vers R2 ou R5.
Lorsque R4 répondra à R1, la réponse ICMP sera d'abord forcément routée vers R3 (car c'est son seul nexthop), qui,
à son tour, la routera vers R2 ou R5.
Noter donc que du routage asymétrique peut avoir lieu : la requête ICMP peut passer par R2 et la réponse revenir par R5.
Ce n'est pas gênant mais ça a le mérite d'être constaté.
Bonus #2 : la libération de labels
Naturellement, LDP gère à la fois l'allocation et la libération de labels car les topologies réseaux sont amenées à changer.
Imaginons que le lien entre R3 et R4 disparaît (via un shutdown
sur l'interface de R3 vers R4 par exemple).
Voyons une capture pour analyser concrètement un message LDP de libération :