giovedì 1 febbraio 2018

MPLS: protezione delle sessioni LDP

Nel mio peregrinare tra ISP e aziende private più o meno grandi, a raccontare le "mirabilie" di MPLS, ho notato che pochi utilizzano un meccanismo molto semplice e non invasivo, come la protezione delle sessioni LDP

Naturalmente, prima di mettere in produzione una qualsiasi nuova funzionalità, un buon networker dovrebbe chiedersi quale problema questa funzionalità consente di risolvere. Bene, allora prima di vedere come funziona la la protezione delle sessioni LDP, vediamo di illustrare cosa avviene in condizioni "nominali" in caso di fuori servizio di un collegamento dove è attiva una sessione LDP (single-Hop).

IL PROBLEMA DA RISOLVERE
Consideriamo, in una rete MPLS, due router direttamente connessi che hanno attiva una sessione LDP e supponiamo che tra i due router sia disponibile un percorso alternativo, come illustrato nella figura seguente. 










Supponiamo che a un certo punto il collegamento RA-RC vada fuori servizio, con conseguente caduta dell'adiacenza del protocollo IGP (tipicamente OSPF o IS-IS) e della sessione LDP.

Come noto, il protocollo LDP, in caso di fuori servizio di un collegamento non ha bisogno di riconvergere. Infatti, nel caso frequente nelle applicazioni pratiche, di utilizzo della modalità "liberale" di mantenimento delle etichette (ad esempio, nei router Cisco e Juniper è di default), la convergenza è immediata in quanto LDP mantiene in memoria tutte le associazioni <FEC, etichetta> dei LDP peers adiacenti. 

Con riferimento alla figura, nel momento in cui il collegamento RA-RC va fuori servizio, il protocollo IGP converge sul nuovo percorso RA-RB-RC (più o meno velocemente in funzione del tipo di protocollo adottato, del tuning dei timer e di eventuali funzionalità di convergenza veloce, come ad esempio LFA). Anche le tabelle FIB e LFIB vengono aggiornate immediatamente, poiché LDP ha già in memoria le associazioni <FEC, etichetta> ricevute (via LDP) dal nuovo IGP Next-Hop RB. Il traffico che aveva Next-Hop RC verrà quindi immediatamente dirottato da RA verso RB, e avendo RA in memoria le associazioni <FEC, etichetta> annunciate da RB, la perdita di traffico è pressoché nulla (e comunque dipende dalla velocità di convergenza del protocollo IGP !).

Una situazione diversa si ha quando il collegamento ritorna in servizio. Infatti, il protocollo IGP riconverge verso il vecchio Next-Hop RC, ma RA non ha più nella propria LIB le associazioni <FEC, etichetta> annunciate da RC, poiché a causa della caduta della sessione LDP tra RA e RC, RA aveva cancellato dalla propria LIB tutte queste associazioni. Fino a che LDP non riconverge, ossia fino a quando la sessione LDP tra RA e RC non ritorna operativa e RC riannuncia a RA le sue associazioni <FEC, etichetta>, vi potrebbe essere perdita di traffico. Infatti RA, non avendo a disposizione etichette MPLS dal Next-Hop RC, invia i pacchetti come semplici pacchetti IP, portando a una interruzione (transitoria) del percorso MPLS che utilizza il collegamento RA-RC. Ora, poiché RC potrebbe non avere nella propria tabella di routing IP le informazioni per raggiungere tutte le reti IP, non tutto il traffico può essere instradato da RC (questo, ad esempio, si verifica (quasi) sempre nelle reti che adottano l’architettura BGP/MPLS, nota anche come architettura BGP core-free).

E' vero, la perdita di traffico è piccola, però vale sempre il ragionamento visto nel post precedente sul Graceful Shutdown delle sessioni BGP, perché perdere traffico quando vi sono funzionalità molto semplici che permettono di evitarlo ?  

Prima di vedere come funziona la protezione delle sessioni LDP un piccolo, Felliniano "Amarcord" sulle sessioni LDP.

AMARCORD ... SESSIONI LDP

Premessa: se siete "ferrati" sulle basi di MPLS potete tranquillamente saltare questa sezione. Anche se "repetita iuvant", magari leggetela comunque, potreste trovare qualche dettaglio che vi era sfuggito.

Due LSR (Label Switching Router, ossia router che supportano le funzionalità MPLS) che utilizzano il protocollo LDP per lo scambio di associazioni <FEC, etichetta> vengono detti LDP Peers e si parla di "sessione LDP" esistente tra i due LSR per lo scambio delle associazioni.

Una singola sessione LDP consente lo scambio delle associazioni <FEC, etichetta> tra i due LSR agli estremi della sessione. La sessione può essere di tipo:
  • Single-hop : i due LDP Peers sono adiacenti l’un l’altro, ossia esiste tra loro un collegamento di Livello 2.
  • Multi-hop : i due LDP Peers sono separati da altri LSR.
Nelle applicazioni pratiche si trovano entrambi questi tipi di sessione. Le sessioni Single-hop sono utilizzate in tutti i più importanti servizi MPLS per realizzare una maglia completa di percorsi MPLS PE-PE, mentre le sessioni Multi-hop trovano applicazione nelle L2VPN punto-punto, e come vedremo in questo post, nella protezione delle sessioni LDP.

La realizzazioni delle sessioni LDP avviene in due fasi, la prima molto simile al classico protocollo di Neighbor Greetings di alcuni protocolli di routing IP (es. OSPF, IS-IS, EIGRP), viene detta meccanismo di discovery, mentre la seconda assomiglia alle sessioni BGP, dove viene realizzata una connessione TCP su una porta well-known. In ultima analisi, una sessione LDP altro non è che una connessione TCP stabilita su una porta well-known (che per le sessioni LDP è la 646).

Il meccanismo di discovery consente ad un LSR di scoprire automaticamente eventuali LDP Peers. Ciò evita la configurazione manuale delle sessioni LDP (come invece avviene ad esempio per le sessioni BGP), rendendo il protocollo estremamente efficiente.
Esistono due varianti del meccanismo di discovery:
  • Meccanismo base: viene utilizzato per scoprire LDP Peers che sono adiacenti (ossia, direttamente connessi a Livello 2). E' il meccanismo utilizzato per la realizzazione di sessioni single-hop.
  • Meccanismo esteso: viene utilizzato per scoprire LDP Peers che non sono adiacenti (ossia, non direttamente connessi a Livello 2). E' il meccanismo utilizzato per la realizzazione di sessioni multi-hop.
In entrambe le varianti, il meccanismo di discovery fa uso dell’invio periodico di particolari messaggi HELLO contenenti varie informazioni utili. I messaggi HELLO sono incapsulati in pacchetti IP con protocollo di trasporto UDP con porta destinazione 646, e contengono sempre un identificativo del LSR che lo invia.
Nella variante base, per scoprire LDP Peers adiacenti un LSR invia periodicamente dei messaggi HELLO (Link Hellos) su tutte le sue interfacce abilitate MPLS (via configurazione), con indirizzo IP destinazione del gruppo multicast "all routers on this subnet" (indirizzo IP multicast 224.0.0.2). 
La variante estesa differisce da quella base su due aspetti:
  • Un LSR invia periodicamente i messaggi HELLO ad uno specifico indirizzo IP unicast (Targeted HELLOs).
  • Il meccanismo è “asimmetrico”, nel senso che il LSR “target” può decidere (su base configurazione) se rispondere ai messaggi HELLO o ignorarli; qualora decidesse di rispondere, lo farebbe inviando periodicamente al LSR mittente messaggi "Targeted HELLOs".
Un LSR adiacente, alla ricezione di un messaggio HELLO risponde creando, se non già presente, una adiacenza Hello, che prevede l’invio periodico di messaggi HELLO all’altro LSR, con frequenza configurabile. A seguito di ciò vengono iniziate le procedure per l’instaurazione di una sessione LDP. 

Una adiacenza Hello viene meno quando uno dei due estremi non riceve alcun messaggio HELLO per un tempo pari al valore (configurabile) di "Hello Holdtime"Nel caso di LDP peers adiacenti, l’adiacenza Hello viene meno quando uno dei due estremi rileva la perdita del collegamento a Livello 2 o a livello fisico.

Quando due LSR sono (direttamente) connessi con più collegamenti fisici, vengono instaurate più adiacenze Hello, una su ciascun collegamento. In questo caso il fuori servizio di una interfaccia provoca la caduta dell’adiacenza Hello sul collegamento, ma non necessariamente la caduta della sessione LDP

Lo scambio di messaggi HELLO tra due LDP Peers fa scattare l’instaurazione di una sessione LDP, che avviene in due fasi successive:
  • Apertura di una connessione TCP tra i due LDP Peers (adiacenti o no).
  • Inizializzazione della sessione LDP.
L’apertura della connessione TCP prevede la determinazione degli estremi della connessione e la determinazione del LSR che gioca il ruolo di LSR «attivo» (ossia il LSR che apre la connessione TCP). Vediamo cosa succede quando si vuole instaurare una connessione TCP tra due LSR, LSR-1 e LSR-2, dal punto di vista di LSR-1. La determinazione degli estremi della connessione richiede la definizione della 4-pla: <IP locale; porta TCP locale; IP remoto; porta TCP remota>.

Il valore di IP locale, di default, coincide con il LSR-ID. Può anche essere determinato manualmente via configurazione. In ogni caso, il valore prescelto viene comunicato al LDP peer remoto attraverso una opzione contenuta nei messaggi HELLO (modulo TLV IPv4 Transport Address). Lo stesso discorso si applica per la determinazione del valore di IP remoto. L’unico aspetto su cui è necessario porre la massima attenzione è che gli indirizzi IP locale e remoto devono (ovviamente) essere connessi a Livello 3. Quindi, le subnet IP che contengono gli indirizzi, devono essere annunciate dal protocollo IGP interno della rete IP/MPLS.

NOTA IMPORTANTE: il LSR-ID è un indirizzo IP parte dell'identificativo LDP (l'altra parte sono due byte posti sempre a 0, a meno non utilizziate interfacce antidiluviane, come ad esempio le interfacce LC-ATM; il valore 0 sta ad indicare uno spazio di etichette MPLS globale, indipendente dalle interfacce). Poiché il LSR-ID viene utilizzato di default come estremo della connessione TCP, deve necessariamente essere un indirizzo routable.

Per quanto riguarda i valori delle porte locale/remota, la prima assume un valore aleatorio mentre la seconda è la well-known port 646 (vedi RFC 5036). La determinazione di chi gioca il ruolo di LSR attivo è basata su un confronto dei valori IP locale e remoto che caratterizzano la connessione TCP. Supponendo di chiamare per semplicità IL il primo e IR il secondo, allora vale la seguente regola:
  • Se IL > IR allora LSR-1 gioca il ruolo di LSR attivo.
  • Se IL < IR allora LSR-1 gioca il ruolo di LSR passivo.
Se LSR-1 risulta attivo, allora questi tenta di aprire la connessione TCP collegandosi alla porta 646 all’indirizzo IP remoto IR. Viceversa, se LSR-1 risulta passivo, attende l’apertura della connessione da parte del LSR-2.
Dopo aver stabilito la connessione TCP, i due LDP Peers si scambiano su questa connessione dei messaggi per inizializzare la sessione LDP. Tramite questi messaggi vengono definite alcune informazioni e negoziati i parametri necessari per il corretto funzionamento della sessione.

Con il ripasso termino qui, anche se vi sarebbero altre cosette da dire, ma non importanti per lo spirito di questo post.

ADIACENZE HELLO E SESSIONI LDP
Una sessione LDP può essere  abbattuta a seguito della caduta dell’adiacenza Hello, causata tipicamente da malfunzionamenti delle interfacce che inviano i messaggi HELLO. 
Quando due LSR sono (direttamente) connessi con più collegamenti fisici, vengono instaurate più adiacenze Hello, una su ciascun collegamento. 

In questo caso, il fuori servizio di una interfaccia provoca la caduta dell’adiacenza Hello sul collegamento, ma non necessariamente la caduta della sessione LDP. Ad esempio, nel caso di due LSR direttamente connessi con un collegamento multi-link vengono stabilite più adiacenze Hello, una per ciascun collegamento. La sessione LDP è però unica e viene chiusa alla caduta dell’ultima adiacenza Hello



Due LSR possono avere adiacenze Hello miste, nel senso che una è un'adiacenza Hello stabilita via Link HELLOs e un'altra stabilita invece attraverso Targeted HELLOs. Anche in questo caso vale quanto detto sopra: la sessione LDP cade quando cadono tutte le adiacenze Hello, siano esse realizzate attraverso Link HELLOs o Targeted HELLOs.

Quest'ultima considerazione è quella su cui si basa il funzionamento della protezione delle sessioni LDP.

PROTEZIONE DELLE SESSIONI LDP: FUNZIONAMENTO
La soluzione del nostro problema è una funzionalità che è una sorta di Uovo di Colombo, nota come protezione delle sessioni LDP.

L'idea di fondo è molto semplice: realizzare una seconda adiacenza Hello (di backup) tra i due LSR estremi della sessione LDP, basata su "Targeted HELLOs", in modo tale che la sessione LDP non cada a fronte della caduta dell’adiacenza Hello diretta (single-hop). Naturalmente questo richiede che esista un percorso alternativo tra i due LSR, che consenta anche in caso di fuori servizio del collegamento diretto, di mantenere la connettività a Livello 3 tra i due LSR-ID. Ma questo è l'ultimo dei problemi in una rete IP/MPLS (un fuori servizio di un collegamento che comporta una partizione della rete, è indice di cattiva progettazione della rete stessa !).

Riassumendo, abilitando (via configurazione) la protezione delle sessioni LDP, tra i due LSR agli estremi di una sessione LDP viene realizzata una seconda adiacenza Hello basata su "Targeted HELLOs", che consente, in caso di fuori servizio del collegamento e conseguente perdita dell'adiacenza Hello diretta (basata su "Link HELLOs"), di mantenere in piedi la sessione LDP. Questo a sua volta comporta che ciascuno dei due LSR mantenga in memoria le associazioni <FEC, Etichetta> ricevute dal LDP peer.

Ad esempio, con riferimento alla figura seguente, nel momento in cui si attiva la protezione delle sessioni LDP, viene realizzata tra i LSR RA e RC una seconda adiacenza Hello di tipo esteso (ossia basata su "Targeted HELLOs"). Si noti che nel funzionamento nominale, presumibilmente i "Targeted HELLOs" vengono scambiati sul collegamento diretto, che (sempre presumibilmente) è il cammino a costo IGP minimo tra i due LSR-ID.



















Solo dopo il fuori servizio del collegamento RA-RC, i "Targeted HELLOs" vengono scambiati sul percorso alternativo RA-RB-RC.

Bene, il meccanismo come potete vedere è molto semplice non invasivo, perché quindi non metterlo in produzione ? Nelle prossime due sezioni illustrerò come le due tecnologie "principe" del networking implementano questa funzionalità.

PROTEZIONE DELLE SESSIONI LDP: CONFIGURAZIONE E TEST IN ROUTER CISCO
Nei router Cisco l'attivazione della protezione delle sessioni LDP avviene con i seguenti comandi:

IOS/IOS XE
router(config)# mpls ldp session protection [for ACL] [duration {infinite | secondi}]

IOS XR
RP/0/RP0/CPU0:router(config)# mpls ldp
RP/0/RP0/CPU0:router(config-ldp)# session protection [for ACL] [duration {infinite |                                                                                                                               secondi}]
dove:
  • Tramite la ACL è possibile specificare per quali LDP peers abilitare la protezione delle sessioni. La ACL specifica i LSR-ID dei LDP peers. Senza l'opzione "for ACL", la protezione viene abilitata su tutte le sessioni LDP. Questa opzione ha senso quando tra due LDP peer non vi sono percorsi alternativi (es. uno dei due LSP è uno stub router) e quindi attivare la protezione sarebbe solo uno spreco di risorse. 
  • Con l’opzione "duration" è possibile definire per quanti secondi la protezione rimane attiva dopo la caduta dell’adiacenza Hello diretta (default = 86.400 sec.).
Vale la pena di chiarire meglio questa seconda opzione. Una volta attivata la protezione, dopo aver rilevato la perdita dell’adiacenza Hello diretta, la protezione della sessione rimane attiva di default per 24 ore (tempo di hold-up). Quello che accade è che il LSR, scaduto il tempo di hold-up, cancella comunque dalla LIB le associazioni <FEC, etichetta> ricevute dal LDP peer. Il valore di hold-up può essere modificato con l’opzione "duration secondi". L’opzione "duration infinite" consente invece di mantenere la protezione della sessione attiva per un tempo indefinito. La ragione della presenza dell'hold-up timer è semplice: se dopo un determinato tempo la sessione LDP diretta non è ritornata up, è inutile sprecare memoria per mantenere le etichette ricevute dal LDP peer.


NOTA IMPORTANTE: il comando va eseguito in entrambi i LSR estremi della sessione da proteggere, altrimenti l'adiacenza Hello di tipo esteso non viene realizzata (la facile dimostrazione è lasciata per esercizio ...).

Qualche informazione sulla protezione può essere ottenuta con il seguente comando di debug:

router# debug mpls ldp session protection

Illustrerò ora un semplice test, realizzato con i router del nostro laboratorio (non sono proprio l'ultimo grido, ma per questo test vanno benissimo). La topologia della rete è descritta nella figura seguente.





















I router P1 e P2 utilizzano l'IOS XR mentre i router PE utilizzano l'IOS semplice. Le configurazioni base sono molto semplici e quindi le ometterò. Su tutti i router ho attivato la protezione delle sessioni LDP con hold-up di 900 secondi. Inoltre, sul router PE1-1 ho attivato il comando "debug mpls ldp session protection".


Nel momento in cui su PE1-1 ho attivato la protezione delle sessioni LDP, il debug ha prodotto i seguenti risultati:


PE1-1(config)#
*Jan 31 18:28:50.059: LDP SP: 192.168.0.12:0: enabling session protection: configuration change
*Jan 31 18:28:50.063: LDP SP: 192.168.0.12:0: state change (None -> Incomplete)
*Jan 31 18:28:50.067: LDP SP: 192.168.1.1:0: enabling session protection: configuration change
*Jan 31 18:28:50.071: LDP SP: 192.168.1.1:0: state change (None -> Incomplete)
*Jan 31 18:28:54.803: LDP SP: 192.168.0.12:0: state change (Incomplete -> Ready)
*Jan 31 18:28:56.143: LDP SP: 192.168.1.1:0: state change (Incomplete -> Ready)

che mettono in evidenza che la protezione è stata attivata. Per una ulteriore verifica si può utilizzare il seguente comando:

PE1-1# show mpls ldp discovery
 Local LDP Identifier:
    192.168.0.11:0
    Discovery Sources:
    Interfaces:
        Ethernet3/0 (ldp): xmit/recv
            LDP Id: 192.168.1.1:0
        Ethernet3/2 (ldp): xmit/recv
            LDP Id: 192.168.0.12:0
    Targeted Hellos:
        192.168.0.11 -> 192.168.0.12 (ldp): active/passive, xmit/recv
            LDP Id: 192.168.0.12:0
        192.168.0.11 -> 192.168.1.1 (ldp): active/passive, xmit/recv
            LDP Id: 192.168.1.1:0

dal quale si evince che PE1-1 ha:
  • Due adiacenze Hello base, con i Link HELLOs ricevuti sulle interfacce Eth3/0 (LDP peer 192.168.1.1) e Eth3/2 (LDP peer 192.168.0.12).
  • Due adiacenze Hello estese, con i Targeted HELLOs che hanno indirizzi IP <sorgente; destinazione> rispettivamente <192.168.0.11; 192.168.0.12> (LDP peer 192.168.0.12) e <192.168.0.11; 192.168.1.1> (LDP peer 192.168.1.1) .
Ora, supponiamo di mettere fuori servizio il collegamento tra PE1-1 e P1 (con un banale shutdown dell'interfaccia Eth3/0). Questo è il risultato del debug:


PE1-1(config-if)#
*Jan 31 19:01:16.599: LDP SP: 192.168.1.1:0: last primary adj lost; starting session protection holdup timer
*Jan 31 19:01:16.599: LDP SP: 192.168.1.1:0: LDP session protection holdup timer started, 900 seconds
*Jan 31 19:01:16.603: LDP SP: 192.168.1.1:0: state change (Ready -> Protecting)

*Jan 31 19:01:16.603: %LDP-5-SP: 192.168.1.1:0: session hold up initiated

Si noti che non è alcuna segnalazione in consolle che la sessione LDP sia andata nello stato down (NOTA: questa segnalazione non è parte del debug). La ragione è molto semplice: la sessione LDP in realtà è rimasta in piedi grazie alla seconda adiacenza Hello (quella basata sui "Targeted HELLOs"). Rieseguendo il comando "show mpls ldp discovery" si ottiene:

PE1-1# show mpls ldp discovery
 Local LDP Identifier:
    192.168.0.11:0
    Discovery Sources:
    Interfaces:
        Ethernet3/2 (ldp): xmit/recv
            LDP Id: 192.168.0.12:0
    Targeted Hellos:
        192.168.0.11 -> 192.168.0.12 (ldp): active/passive, xmit/recv
            LDP Id: 192.168.0.12:0
        192.168.0.11 -> 192.168.1.1 (ldp): active/passive, xmit/recv
            LDP Id: 192.168.1.1:0

dal quale si evince che PE1-1 ha solo due adiacenze Hello di tipo esteso.

Volendo è possibile evidenziare anche il valore di hold-up rimanente:

PE1-1# show mpls ldp neighbor 192.168.1.1 detail | begin LDP Session
        LDP Session Protection enabled, state: Protecting
            duration: 900 seconds
            holdup time remaining: 852 seconds
< output omesso >

Nel momento in cui il collegamento tra PE1-1 e P1 ritorna in servizio, ecco cosa segnala il debug:

PE1-1(config-if)#
*Jan 31 19:05:18.151: LDP SP: 192.168.1.1:0: primary adj restored; stopping session protection holdup timer
*Jan 31 19:05:18.151: LDP SP: 192.168.1.1:0: state change (Protecting -> Ready)
*Jan 31 19:05:18.155: %LDP-5-SP: 192.168.1.1:0: session recovery succeeded

e il timer hold-up ritorna al suo valore di configurazione (900 secondi):

PE1-1# show mpls ldp neighbor 192.168.1.1 detail | begin LDP Session
        LDP Session Protection enabled, state: Ready
            duration: 900 seconds
output omesso >

E qui termina il test, non c'è più niente da dire. L'unica cosa in più che potrei mostrare è che quando l'interfaccia Eth3/0 è fuori servizio, e con un po' di pazienza si fa scadere l'hold-up timer (posto via configurazione a 15 minuti), nella LIB di PE1-1 scompaiono gli annunci <FEC, Etichetta> ricevuti da P1. Ma fidatevi, è proprio così.

PROTEZIONE DELLE SESSIONI LDP: CONFIGURAZIONE NEI ROUTER JUNIPER
Anche le piattaforme Juniper supportano la funzionalità di protezione delle sessioni LDP. Solo che a differenza dei router Cisco, l'abilitazione vale per tutte le sessioni LDP, non è possibile definirla selettivamente.

L'attivazione della protezione avviene attraverso il comando:

[edit protocols ldp]
tt@router# show
session-protection {
   timeout secondi;
}


L'opzione "timeout" ha lo stesso significato dell'opzione "duration" vista per i router Cisco.

Non ho fatto un test di laboratorio con i router Juniper, che comunque non aggiungerebbe nulla a quanto già visto per i router Cisco.

CONCLUSIONI
La funzionalità di protezione delle sessioni LDP è un marchingegno molto semplice, non invasivo, che può essere introdotto in reti in produzione senza alcun problema di interruzione di traffico. Per cui ne consiglio sempre l'utilizzo. 




Nessun commento:

Posta un commento