Algoritmi di instradamento - link state e distance vector
In questa pagina 6
In questa pagina 6
Il livello di rete (Livello di rete e indirizzamento IPIl livello di rete (network layer) porta i datagrammi da host a host attraverso i router: incapsula (framing), sceglie il percorso (routing) e sposta il pacchetto da un ingresso a un'uscita del router (forwarding); in Internet lascia ai livelli superiori controllo d'errore, di flusso e di congestione. Un indirizzo IPv4 è di 32 bit, diviso in prefisso (rete, $n$ bit) e suffisso (host, $32-n$ bit). L'indirizzamento a classi (A, B, C, D, E) è obsoleto; oggi si usa quello senza classi (CIDR): data una notazione $a.b.c.d/n$ si ricavano $N=2^{32-n}$ indirizzi, indirizzo di rete (suffisso tutto 0) e di broadcast (suffisso tutto 1), oppure con la netmask: rete $=$ indirizzo AND maschera, broadcast $=$ indirizzo OR (NOT maschera).Livello di rete e indirizzamento IP →) ha due compiti distinti: l'instradamento (routing), cioè calcolare quale strada seguire, e l'inoltro (forwarding), cioè spostare ogni pacchetto verso l'interfaccia di uscita indicata dalla tabella (Instradamento e inoltroL'inoltro (forwarding) mette il pacchetto sulla strada verso la destinazione, un salto alla volta (hop by hop). Se la destinazione è nella stessa rete del mittente l'inoltro è diretto (si usa l'ARP per il MAC del destinatario), altrimenti è indiretto: il pacchetto va al router successivo (next hop) indicato dalla tabella di instradamento, o al default gateway. Con le netmask: l'inoltro è diretto attraverso l'interfaccia $x$ se $\text{IP(dst)}\ \text{AND}\ \text{NM}(x)=\text{IP}(x)\ \text{AND}\ \text{NM}(x)$; altrimenti si scorre la tabella dalla maschera più lunga (longest prefix match) e si usa il primo match. La riga con rete $0.0.0.0$ e maschera $0.0.0.0$ (default route) corrisponde sempre. L'aggregazione di rotte (route aggregation) riduce la tabella, e nell'inoltro con etichette (MPLS) la tabella si consulta per indice.Instradamento e inoltro →). Questa nota tratta il primo: come i router riempiono le loro tabelle. I protocolli veri e propri che usano questi algoritmi (RIP, OSPF, BGP) sono in Protocolli di instradamento - RIP, OSPF e BGPIn Internet l'instradamento non si può fare con un solo protocollo, per scalabilità (tabelle troppo grandi) e per autonomia amministrativa: ogni ISP è un sistema autonomo (AS) con il proprio algoritmo. All'interno di un AS si usano i protocolli IGP: RIP (distance vector, numero di salti, massimo 15, aggiornamenti ogni circa 30 s, su UDP porta 520) e OSPF (link state con Dijkstra, aree collegate all'area 0, cinque tipi di LSA, messaggi direttamente in IP). Tra AS si usa BGP4 (path vector, su TCP porta 179, eBGP tra AS e iBGP dentro l'AS, scelta del percorso per politica: preferenza locale, AS-PATH più corto, origine; i cicli si evitano scartando i cammini che contengono già il proprio AS; quattro messaggi: Open, Keepalive, Notification, Update).Protocolli di instradamento - RIP, OSPF e BGP →.
Il problema: trovare il percorso migliore
Definizione (instradamento). L'insieme delle procedure che permettono di determinare un percorso da un punto a un altro. È possibile solo se ogni router ha una tabella di inoltro per mandare il datagramma al nodo successivo (next hop) sulla strada verso la destinazione.
Perché il percorso conta: instradamento e capacità
In una rete a maglia la quantità di traffico consegnabile dipende da come i flussi sono instradati, non solo dalla capacità dei collegamenti. Si abbiano due flussi e e collegamenti tutti di capacità :
- se i due flussi usano gli stessi collegamenti, condividono la capacità e il traffico massimo consegnato in totale è ;
- se i flussi sono distribuiti su percorsi diversi (nell'esempio delle slide ci sono tre collegamenti utilizzabili in parallelo), il traffico massimo sale a .
Un buon algoritmo di instradamento non cerca soltanto "una strada" ma una strada che usi bene la rete.
La rete come grafo pesato
Per trovare il percorso migliore un insieme di reti interconnesse (internet) si modella come grafo pesato (nodi, archi, cammini e connessione sono definiti in Grafi - definizioni e proprietàGrafo G=(V,E) diretto e non diretto, grafo semplice e pesato; incidenza, adiacenza, grado; cammini, cicli, sottografi, grafi connessi e componenti connesse; alberi liberi, foreste, spanning tree e spanning forest; proprietà con dimostrazioni (somma dei gradi = 2m, m <= n(n-1)/2, alberi m = n-1, connessi m >= n-1, foreste m <= n-1).Grafi - definizioni e proprietà →): ogni router è un nodo, ogni rete tra due router è un arco, e a ogni arco è associato un costo. Se tra due nodi non c'è un arco il costo è . Il significato del costo cambia da protocollo a protocollo.
Definizione (percorso di costo minimo). Dato un grafo connesso e una funzione di costo additiva (il costo di un cammino è la somma dei costi degli archi), il percorso di costo minimo (least-cost route, LCR) da una sorgente a un nodo è la sequenza di nodi connessi, da a , con somma dei costi minima fra tutti i cammini possibili.
Ogni router deve trovare il percorso di costo minimo verso tutti gli altri router: con router sono percorsi per ciascuno, cioè percorsi in tutta la rete. Conviene raccoglierli in un albero di costo minimo (least-cost tree): un albero che ha il router sorgente come radice, tocca tutti gli altri nodi e in cui il cammino dalla radice a ogni nodo è quello minimo. Si ha così un solo albero per sorgente, quindi alberi per tutta la rete.
Quale costo? Le metriche
"Migliore" non ha un'unica risposta: minimo numero di salti, minimo ritardo end-to-end, minima probabilità di perdita, massimo throughput a lungo termine. Per far calcolare a Dijkstra o a Bellman-Ford il percorso desiderato basta scegliere bene il costo di ogni coppia di nodi collegati:
| criterio | costo dell'arco | spiegazione |
|---|---|---|
| minimo numero di salti (hop count) | il costo del cammino è il numero di archi | |
| minimo ritardo end-to-end | tempo di trasmissione del pacchetto più propagazione | |
| minima probabilità di perdita | il prodotto delle probabilità di successo diventa una somma di logaritmi (proprietà in Esponenziale e logaritmoLa funzione esponenziale a^x (base positiva diversa da 1) e la sua inversa, il logaritmo in base a, con grafici e proprietà.Esponenziale e logaritmo →) | |
| massimo throughput | , con intero | vedi sotto |
Esempio (ritardo). Pacchetto di byte bit su un collegamento da Mbit/s con propagazione ms: ms.
Esempio (perdite). Due collegamenti con e : la probabilità di successo sul cammino è . Con i costi logaritmici si ottiene la stessa informazione per somma: . Minimizzare la somma dei costi equivale quindi a massimizzare la probabilità di successo. I passaggi: (1) la probabilità di successo di un cammino è il prodotto (i collegamenti perdono in modo indipendente: Indipendenza di eventiA e B sono indipendenti se P(A ∩ B) = P(A) P(B), cioè se sapere che uno si è verificato non cambia la probabilità dell'altro; l'indipendenza passa ai complementari, non va confusa con l'incompatibilità, e per più eventi va richiesta su ogni sottofamiglia.Indipendenza di eventi →); (2) il logaritmo trasforma il prodotto in somma, ; (3) poiché si ha , e il segno meno rende ogni costo , come richiede Dijkstra; (4) il logaritmo è crescente, quindi massima equivale a massimo, cioè minimo.
Perché per il throughput serve un trucco. Il throughput a lungo termine di un cammino è il minimo dei bitrate lungo il cammino (il collo di bottiglia), non la loro somma: la condizione di additività richiesta da Dijkstra non vale e il massimo throughput non si può riprodurre esattamente. Si può però approssimare con e grande: elevando alla si amplifica il peso del collegamento più lento, così che il cammino più corto sia quasi sempre quello con il collo di bottiglia migliore.
Esempio. Un cammino di 10 collegamenti da 100 Mbit/s (collo di bottiglia 100) e un cammino di due collegamenti da 50 e 100 Mbit/s (collo di bottiglia 50). Con : , : vince , sbagliando. Con : , , ancora . Con : , : vince , correttamente.
Instradamento statico e dinamico
- Statico (reti piccole): le tabelle sono compilate a mano; non reagiscono a guasti o cambi di topologia. Si possono definire più cammini statici tra due nodi per avere un po' di resilienza.
- Dinamico (reti grandi): un protocollo aggiorna da solo le tabelle quando cambiano carico o topologia. Costo: i protocolli generano traffico di controllo, e durante i transitori le tabelle dei nodi possono non essere coerenti (rischio di instabilità).
Le tre famiglie di algoritmi
| link state | distance vector | path vector | |
|---|---|---|---|
| algoritmo | Dijkstra | Bellman-Ford | alberi di copertura (spanning tree) con politica |
| informazione che serve | topologia completa | solo i vicini | solo i vicini |
| cosa si scambia | informazioni locali (i propri collegamenti) con tutti i nodi | informazioni globali (le distanze verso tutti) con i soli vicini | cammini interi con i soli vicini |
| calcolo | centralizzato sul grafo intero | iterativo e distribuito | iterativo e distribuito |
| obiettivo | cammino di costo minimo | cammino di costo minimo | raggiungibilità secondo politiche |
| protocolli | OSPF, IS-IS | RIP, IGRP | BGP |
Link state
Ogni nodo deve prima conoscere i vicini e identificarli (pacchetti HELLO), poi calcolare il costo dei collegamenti diretti, i costi locali (per esempio con pacchetti ECHO per misurare il ritardo). Con queste informazioni crea un pacchetto, il Link State Packet (LSP), e lo diffonde a tutti gli altri router con un flooding (una specie di broadcast multi-salto), da ripetere dopo ogni cambiamento dello stato di un collegamento. Quando un router ha ricevuto l'LSP di ogni nodo, ha l'intero grafo e applica Dijkstra per ottenere il percorso minimo verso ogni altro nodo.
Formato dell'LSP: nome della sorgente seguito da coppie (vicino, costo).
Esempio. Rete con sette router e archi , , , , , , , , .
Grafico interattivo: Rete di esempio con i costi dei collegamenti
Ogni router ha ricevuto questi sette LSP:
| sorgente | vicino e costo |
|---|---|
| A | B 4, F 1 |
| B | A 4, C 2, G 1 |
| C | B 2, D 3, G 4 |
| D | C 3, E 6 |
| E | F 3, D 6 |
| F | A 1, G 1, E 3 |
| G | B 1, C 4, F 1 |
Leggendo la tabella un nodo qualsiasi ricostruisce il grafo della figura (ogni arco compare due volte, una per estremo). Su questo grafo applica Dijkstra.
L'algoritmo di Dijkstra
(L'algoritmo è presentato anche come problema sui grafi in Cammini minimi e algoritmo di DijkstraGrafi pesati, lunghezza di un cammino e distanza; sottocammini di un cammino minimo; problema SSSP; algoritmo di Dijkstra con cloud e priority queue, rilassamento degli archi, esempio svolto; correttezza (due lemmi) e complessità O(min(n^2, (n+m) log n)) con lista non ordinata o heap; pesi non negativi.Cammini minimi e algoritmo di Dijkstra →; qui è letto dal punto di vista del router.) L'obiettivo è trovare il percorso più breve da un nodo di partenza (starting node) a tutti gli altri (one-to-all). L'algoritmo parte con valori iniziali per la distanza da e a ogni passo li migliora, determinando a ogni passo la distanza minima di un nodo.
Definizione (stato di un nodo in Dijkstra). Ogni nodo ha uno stato :
- è la stima corrente della distanza da (il costo accumulato);
- l'etichetta è permanente () se è già la distanza minima da , temporanea () altrimenti.
A ogni passo un nodo è il nodo corrente.
Passi:
- Inizializzazione. Lo stato di è e è il nodo corrente. Ogni altro nodo ha stato .
- Rilassamento. Per ogni vicino del nodo corrente non ancora permanente si calcola ; se il minimo è la seconda quantità, si aggiorna anche il predecessore di (puntatore a ).
- Scelta. Tra i nodi temporanei si sceglie quello con minima: diventa permanente e nodo corrente. Si torna al passo 2 finché non restano nodi temporanei raggiungibili. Perché quel nodo è definitivo: qualunque altra strada verso di lui dovrebbe passare per un altro nodo temporaneo, che ha già una stima almeno uguale, e da lì i costi (non negativi) possono solo aumentare; la dimostrazione precisa è nella sezione sulla correttezza.
- Dai predecessori ai cammini. Per conoscere il cammino da a si segue la catena dei predecessori da a e la si legge al contrario.
Pseudocodice (con dist e prev):
Dijkstra(Graph, source):
per ogni vertice v: dist[v] = INFINITO; prev[v] = NON DEFINITO; v entra in Q
dist[source] = 0
finche' Q non e' vuoto:
u = vertice di Q con dist minima; togli u da Q
per ogni vicino v di u ancora in Q:
alt = dist[u] + length(u, v)
se alt < dist[v]: dist[v] = alt; prev[v] = u
restituisci dist[], prev[]Esempio 1 (grafo a 6 nodi, sorgente 1). Archi: , , , , , , , , .
| passo | nodo corrente (diventa permanente) | stati dei nodi ancora temporanei (distanza, predecessore) |
|---|---|---|
| 1 | 1, con | , , , , |
| 2 | 2, con (il minimo è 7) | resta ; ; ; |
| 3 | 3, con | ; ; |
| 4 | 6, con | ; |
| 5 | 5, con (pari merito con 4: si può scegliere uno qualsiasi dei due) | , invariato |
| 6 | 4, con | nessuno |
Distanze da 1: , , , , . Cammino da 1 a 5: predecessore di 5 è 6, di 6 è 3, di 3 è 1: leggendo al contrario , costo . Cammino da 1 a 4: predecessore di 4 è 3: , costo .
Esempio 2 (il grafo , sorgente ). Ogni riga è lo stato dopo che il nodo indicato è diventato permanente; in ogni cella: distanza e predecessore.
| passo | permanenti | B | C | D | E | F | G |
|---|---|---|---|---|---|---|---|
| 0 | 4-A | 1-A | |||||
| 1 | 4-A | 4-F | 1-A | 2-F | |||
| 2 | 3-G | 6-G | 4-F | 2-F | |||
| 3 | 3-G | 5-B | 4-F | ||||
| 4 | 5-B | 10-E | 4-F | ||||
| 5 | 5-B | 8-C | |||||
| 6 | 8-C |
Spiegazione dei passi cruciali: al passo 1 da si raggiunge con e con ; al passo 2 da si migliora () e si trova (); al passo 3 da si migliora (); al passo 4 (distanza 4, minore di 5) fa raggiungere con ; al passo 5 migliora ().
Albero di costo minimo di (archi in colore): , , , , , .
Grafico interattivo: Albero di costo minimo di A (archi colorati)
(le etichette sugli archi dell'albero sono le distanze da , non i costi degli archi; i tratteggi sono archi che esistono ma non fanno parte dell'albero.)
Dall'albero alla tabella di . Il next hop verso ogni destinazione è il primo nodo del cammino: verso , , , , e si passa tutti da (per : ).
| destinazione | costo | next hop |
|---|---|---|
| B | 3 | F |
| C | 5 | F |
| D | 8 | F |
| E | 4 | F |
| F | 1 | F |
| G | 2 | F |
Ogni router esegue Dijkstra per conto proprio, con sé stesso come sorgente, ottenendo il proprio albero e la propria tabella.
Complessità. Con la scelta del minimo tra i nodi temporanei fatta scorrendo l'elenco si fanno scelte di costo ciascuna, quindi (Notazione asintoticaDefinizioni di O, Omega, Theta e o piccolo con le costanti c ed n0; esempi con costanti esplicite; proprietà (polinomi, esponenziali, logaritmi, somme, implicazioni tra notazioni); sommatorie notevoli; terminologia (logaritmica, lineare, polinomiale, esponenziale).Notazione asintotica →: il numero di operazioni cresce come il quadrato di ); con una coda con prioritàstruttura dati che restituisce l'elemento di chiave minima in tempo logaritmicoCode con priorità → si arriva a , con numero di archi. Conti: ogni nodo diventa permanente una volta ( volte la ricerca del minimo, ciascuna, quindi ), e ogni arco viene rilassato al più una volta per estremo ( rilassamenti); con la coda ogni estrazione o aggiornamento costa .
Distance vector
Qui nessun nodo conosce la topologia. Ogni nodo parte conoscendo solo i vicini (con i pacchetti HELLO e ECHO come sopra) e costruisce un vettore delle distanze (distance vector, DV): per ogni destinazione, la distanza e il next hop del percorso minimo attualmente noto.
Esempio (DV di all'inizio).
| destinazione | distanza | next hop |
|---|---|---|
| A | 0 | - |
| B | 4 | B |
| C | - | |
| D | - | |
| E | - | |
| F | 1 | F |
| G | - |
Questi vettori rudimentali non bastano a inoltrare bene i pacchetti: sono i percorsi minimi con le informazioni limitate che un nodo ha. Per migliorarli i nodi devono aiutarsi: periodicamente (a intervalli casuali tra 25 e 35 s) oppure quando il proprio DV cambia, ogni nodo manda il suo DV ai vicini. Quando un nodo riceve il DV di un vicino, aggiorna il proprio con un algoritmo distribuito (Bellman-Ford). Dopo un transitorio i DV convergono ai veri percorsi minimi. Se una riga non viene aggiornata entro un certo tempo (expiration timer, 180 s) il costo verso quella destinazione diventa infinito; dopo altri 120 s (garbage collection) la riga è cancellata.
Formula (aggiornamento di Bellman-Ford). Il nodo riceve dal vicino il DV con le stime del costo da a ogni destinazione . Per ogni : Se il valore passando per è minore, si mettono nella riga il nuovo costo e next hop .
Qui è il costo immediato del collegamento e è il costo minimo stimato da a (che può passare per più salti).
Esempio. riceve da il primo DV di , che dice , , e per , , . Con : per , (next hop ); per , (next hop ); per , (nessun miglioramento: non conosce ancora ). Poi arriva il DV di (con , ) e calcola, con : per , (next hop ); per , (next hop ).
Convergenza: giro per giro
Se tutti i nodi scambiano i DV in giri sincroni, il vettore di nella rete evolve così (ogni giro tutti i nodi usano i DV del giro precedente):
| giro | B | C | D | E | F | G |
|---|---|---|---|---|---|---|
| 0 (solo vicini) | 4 | 1 | ||||
| 1 | 4 | 6 | 4 | 1 | 2 | |
| 2 | 3 | 6 | 9 | 4 | 1 | 2 |
| 3 | 3 | 5 | 9 | 4 | 1 | 2 |
| 4 | 3 | 5 | 8 | 4 | 1 | 2 |
| 5 | 3 | 5 | 8 | 4 | 1 | 2 |
Il giro 5 non cambia più niente: l'algoritmo è a regime. Il giro ha trovato i cammini minimi con al più archi; il cammino ottimo (, costo 8) ha 5 archi, quindi serve il giro 4 (dimostrazione sotto). I risultati coincidono con Dijkstra (stessa tabella di ). Le tabelle a regime (destinazione, distanza, next hop) per , e sono:
| dest. | : dist. / next hop | : dist. / next hop | : dist. / next hop |
|---|---|---|---|
| A | 0 / - | 3 / G | 5 / B |
| B | 3 / F | 0 / - | 2 / B |
| C | 5 / F | 2 / C | 0 / - |
| D | 8 / F | 5 / C | 3 / D |
| E | 4 / F | 5 / G | 7 / B |
| F | 1 / F | 2 / G | 4 / B |
| G | 2 / F | 1 / G | 3 / B |
Guasto di un collegamento
Se il collegamento si rompe: non riceve più HELLO da ; scaduto il timeout toglie dai vicini e cancella dalla tabella tutte le righe che hanno come next hop, poi manda il nuovo DV ai suoi vicini (e fa lo stesso). L'aggiornamento si propaga e a regime le tabelle sono quelle dell'albero senza : ad esempio raggiunge con costo passando per () e raggiunge con costo passando per . In generale, un nodo che rileva un guasto o una variazione di costo manda subito il proprio DV ai vicini e riavvia il processo distribuito.
Il problema del conteggio all'infinito
Nella rete senza si rompe anche il collegamento . Prima del guasto raggiunge con costo passando per . Succede questo:
- cancella la riga verso ma, prima di mandare il suo DV, riceve il DV di che dice "raggiungo con 5". calcola e aggiorna: a costo 7 con next hop .
- manda il DV a : vede che il percorso verso (già via ) è cambiato e calcola .
- manda il DV a : calcola . E così via.
Costo di visto da e da : : cresce di 2 a ogni messaggio, cioè di 4 a ogni scambio completo ( e ), perché ogni nodo somma il costo del collegamento alla stima del vicino (dopo messaggi la stima vale ). Cresce fino all'infinito, ma lentamente. Nel frattempo i pacchetti per rimbalzano tra e (problema del ciclo a due salti, two-hop loop), perché il percorso verso non esiste più.
Grafico interattivo: Conteggio all'infinito: stima del costo verso D dopo n messaggi
La stima supera la soglia al sesto messaggio (; il quinto dà ): lì il costo viene considerato infinito e il conteggio si ferma.
Soluzioni:
- Infinito limitato (limited infinity): una distanza maggiore di 16 è considerata infinita. Funziona solo in reti con distanza massima tra due nodi inferiore a 16. Nell'esempio il conteggio si ferma quando si arriva a (dopo pochi scambi: ).
- Hold down: quando un router viene informato che una destinazione non è raggiungibile ignora per 60 s ogni aggiornamento per quella destinazione, evitando che informazioni obsolete siano prese per valide (a prezzo di reagire più lentamente ai cambi di topologia).
- Aggiornamento immediato (triggered update): i cambi di topologia sono notificati con priorità, senza aspettare il timer: convergenza più rapida e guasti scoperti prima.
- Split horizon: a ciascun vicino si inviano solo le righe del DV che non hanno come next hop. Nell'esempio non manda a la riga di (perché raggiunge proprio attraverso ): il ciclo non nasce.
- Poison reverse: lo split horizon ha un difetto: se omette la riga di , non sa se è perché applica lo split horizon o perché non conosce davvero . Con il poison reverse il nodo manda tutte le destinazioni ma mette per quelle raggiungibili attraverso il collegamento su cui sta inviando: dice a "per il costo è ": "non usare questo valore, quello che so su questa strada viene da te".
Nota. Split horizon e poison reverse eliminano i cicli a due salti ma non tutti i cicli (con tre o più nodi in cerchio il conteggio all'infinito può ancora presentarsi): per questo sono combinati con l'infinito limitato.
Confronto tra distance vector e link state
Path vector
I costi non permettono a chi invia di imporre politiche sul percorso del pacchetto: con il percorso di costo minimo la strada la decide la metrica. Nel path vector il percorso migliore è scelto dalla sorgente in base alla politica che le interessa, quindi la sorgente può controllare la strada. L'obiettivo non è minimizzare un costo ma la raggiungibilità: far arrivare il pacchetto a destinazione in modo conveniente, senza assegnare costi ai cammini.
L'albero che ne esce è un albero di copertura (spanning tree) ma non è l'albero di costo minimo: è quello determinato dalla politica della sorgente. Una sorgente può applicare più politiche insieme, per esempio "usa il minor numero di nodi" (simile al costo minimo) oppure "evita certi nodi come nodi intermedi". Come il distance vector, l'algoritmo è asincrono e distribuito:
- un nodo all'avvio crea un vettore dei cammini con le informazioni sui vicini immediati (invia messaggi di saluto, HELLO + ECHO, per raccoglierle);
- lo manda a tutti i vicini;
- quando riceve il vettore di un vicino lo combina col proprio con una regola simile a Bellman-Ford, ma applicando la propria politica invece del costo minimo: dove è il cammino ottenuto anteponendo al cammino annunciato da verso .
Rilevamento dei cicli. Ogni annuncio contiene l'intero cammino. Un nodo che riceve un cammino in cui compare già sé stesso lo scarta: i cammini sono privi di cicli e il problema del conteggio all'infinito non esiste (è quanto fa BGP, con i numeri di AS al posto dei router).
Esempio. Rete con archi , , , , e destinazione . riceve da l'annuncio "per : " e da l'annuncio "per : ". Con la politica "non attraversare " sceglie anche se, per costi dei collegamenti, passare da fosse più economico. Se invece riannunciasse a un cammino che contiene , lo scarta.
L'esito di un algoritmo di instradamento è una tabella di instradamento (routing table), con (1) l'indirizzo della rete di destinazione, (2) il router a cui inoltrare il pacchetto (next hop), (3) il costo per raggiungere la destinazione; il formato dei pacchetti scambiati è fissato dal protocollo di instradamento. Come si usa la tabella è in Instradamento e inoltroL'inoltro (forwarding) mette il pacchetto sulla strada verso la destinazione, un salto alla volta (hop by hop). Se la destinazione è nella stessa rete del mittente l'inoltro è diretto (si usa l'ARP per il MAC del destinatario), altrimenti è indiretto: il pacchetto va al router successivo (next hop) indicato dalla tabella di instradamento, o al default gateway. Con le netmask: l'inoltro è diretto attraverso l'interfaccia $x$ se $\text{IP(dst)}\ \text{AND}\ \text{NM}(x)=\text{IP}(x)\ \text{AND}\ \text{NM}(x)$; altrimenti si scorre la tabella dalla maschera più lunga (longest prefix match) e si usa il primo match. La riga con rete $0.0.0.0$ e maschera $0.0.0.0$ (default route) corrisponde sempre. L'aggregazione di rotte (route aggregation) riduce la tabella, e nell'inoltro con etichette (MPLS) la tabella si consulta per indice.Instradamento e inoltro →.
Dimostrazioni di correttezza
Notazione: è il costo minimo (vero) da a ; il costo dell'arco.
Proprietà (sottostruttura ottima). Se è un cammino minimo da a , ogni suo tratto è un cammino minimo da a . Di conseguenza al variare dei vicini di (equazione di Bellman).
Dimostrazione. Se per assurdo il tratto avesse un'alternativa di costo minore, sostituendola si otterrebbe un cammino di costo minore di : assurdo. L'equazione di Bellman segue perché l'ultimo arco di un cammino minimo è per qualche vicino e il tratto è minimo.
Correttezza di Dijkstra (costi non negativi)
Proprietà (invariante di Dijkstra). Quando un nodo diventa permanente, . Inoltre per ogni nodo non permanente è la lunghezza del cammino minimo da a che usa come nodi intermedi soli nodi permanenti.
Dimostrazione per induzione sull'ordine con cui i nodi diventano permanenti.
- Base. Il primo nodo permanente è con (i costi sono , nessun cammino può costare meno).
- Passo. Sia l'insieme dei nodi permanenti e valga l'invariante per tutti i nodi in . Sia il nodo con minima tra i temporanei: l'algoritmo lo rende permanente. Supponiamo per assurdo che esista un cammino da a di costo . Poiché e , esce da : sia il primo arco con , (può essere ). Quando è diventato permanente l'algoritmo ha rilassato , quindi Il primo passaggio è il rilassamento dell'arco ; l'uguaglianza è l'ipotesi induttiva su ; il terzo passaggio dice che il tratto di fino a costa almeno (per definizione di costo minimo); l'ultimo usa : il resto di da a non può avere costo negativo. Ma allora è temporaneo con , contro la scelta di come minimo. Quindi nessun cammino costa meno di e .
- Seconda parte. Rendere permanente e rilassare i suoi archi mantiene l'invariante, perché i nuovi cammini candidati sono quelli che passano per come ultimo nodo permanente.
Dove serve . Con un costo negativo il passaggio "il resto di non costa meno di zero" cade. Controesempio: archi di costo 2, di costo 3, di costo . Dijkstra rende permanente con (minimo tra 2 e 3), ma il cammino costa . In una rete di router i costi sono sempre positivi (ritardi, numeri di salti), quindi Dijkstra si può usare.
Correttezza di Bellman-Ford (e del distance vector)
Sia la stima di per dopo giri sincroni, con se e sono vicini, se , altrimenti. Il giro applica la regola dell'algoritmo:
Proprietà (invariante di Bellman-Ford). è il costo minimo tra i cammini da a con al più archi.
Dimostrazione per induzione su .
- Base (). I cammini con al più un arco sono il cammino vuoto () e i collegamenti diretti: è esattamente .
- Passo. Un cammino da a con al più archi o ha al più archi (e il minimo di questi è per ipotesi), oppure ha esattamente archi: il primo è per un vicino , e il resto è un cammino da a con archi, quindi il minimo è . Il minimo tra tutte queste alternative è .
Conseguenza (convergenza). Se la rete non ha cicli di costo negativo (e con costi non ne ha), un cammino minimo è semplice, cioè non ripete nodi, e ha quindi al più archi. Dopo giri (in pratica ) tutte le stime sono i veri costi minimi e un ulteriore giro non cambia niente: è la condizione di regime vista nella tabella dei giri. Nell'esempio, il cammino minimo ha 5 archi, quindi è il primo valore esatto: lo conferma la tabella dei giri.
Versione asincrona. Nella rete vera i DV non sono scambiati a giri sincroni, ma vale lo stesso: (1) le stime non scendono mai sotto il valore vero, perché ogni stima è il costo di un cammino realmente esistente; (2) per induzione sul numero di archi del cammino minimo, quando riceve i DV già esatti dei vicini la sua stima diventa esatta e resta tale. Dopo al più periodi di aggiornamento senza altri cambiamenti di topologia le stime sono esatte.
Perché allora il conteggio all'infinito? La prima proprietà ("ogni stima è il costo di un cammino realmente esistente") vale solo se la topologia non cambia. Se un collegamento si rompe, alcune stime descrivono cammini che non esistono più: sono più basse del vero costo (che ora è o più alto) e continuano a circolare tra i nodi, come nel ciclo dell'esempio, finché il costo non cresce abbastanza. Per questo servono i rimedi della sezione precedente. Dijkstra, che lavora su una fotografia completa del grafo, non ha questo problema.
Versione ripasso
Il problema
- Instradamento (routing): calcolare la strada; inoltro (forwarding): spostare il pacchetto sull'interfaccia indicata dalla tabella (Instradamento e inoltroL'inoltro (forwarding) mette il pacchetto sulla strada verso la destinazione, un salto alla volta (hop by hop). Se la destinazione è nella stessa rete del mittente l'inoltro è diretto (si usa l'ARP per il MAC del destinatario), altrimenti è indiretto: il pacchetto va al router successivo (next hop) indicato dalla tabella di instradamento, o al default gateway. Con le netmask: l'inoltro è diretto attraverso l'interfaccia $x$ se $\text{IP(dst)}\ \text{AND}\ \text{NM}(x)=\text{IP}(x)\ \text{AND}\ \text{NM}(x)$; altrimenti si scorre la tabella dalla maschera più lunga (longest prefix match) e si usa il primo match. La riga con rete $0.0.0.0$ e maschera $0.0.0.0$ (default route) corrisponde sempre. L'aggregazione di rotte (route aggregation) riduce la tabella, e nell'inoltro con etichette (MPLS) la tabella si consulta per indice.Instradamento e inoltro →, Livello di rete e indirizzamento IPIl livello di rete (network layer) porta i datagrammi da host a host attraverso i router: incapsula (framing), sceglie il percorso (routing) e sposta il pacchetto da un ingresso a un'uscita del router (forwarding); in Internet lascia ai livelli superiori controllo d'errore, di flusso e di congestione. Un indirizzo IPv4 è di 32 bit, diviso in prefisso (rete, $n$ bit) e suffisso (host, $32-n$ bit). L'indirizzamento a classi (A, B, C, D, E) è obsoleto; oggi si usa quello senza classi (CIDR): data una notazione $a.b.c.d/n$ si ricavano $N=2^{32-n}$ indirizzi, indirizzo di rete (suffisso tutto 0) e di broadcast (suffisso tutto 1), oppure con la netmask: rete $=$ indirizzo AND maschera, broadcast $=$ indirizzo OR (NOT maschera).Livello di rete e indirizzamento IP →). I protocolli veri sono in Protocolli di instradamento - RIP, OSPF e BGPIn Internet l'instradamento non si può fare con un solo protocollo, per scalabilità (tabelle troppo grandi) e per autonomia amministrativa: ogni ISP è un sistema autonomo (AS) con il proprio algoritmo. All'interno di un AS si usano i protocolli IGP: RIP (distance vector, numero di salti, massimo 15, aggiornamenti ogni circa 30 s, su UDP porta 520) e OSPF (link state con Dijkstra, aree collegate all'area 0, cinque tipi di LSA, messaggi direttamente in IP). Tra AS si usa BGP4 (path vector, su TCP porta 179, eBGP tra AS e iBGP dentro l'AS, scelta del percorso per politica: preferenza locale, AS-PATH più corto, origine; i cicli si evitano scartando i cammini che contengono già il proprio AS; quattro messaggi: Open, Keepalive, Notification, Update).Protocolli di instradamento - RIP, OSPF e BGP →.
- Il percorso conta per la capacità: due flussi sugli stessi collegamenti consegnano al massimo in totale, su percorsi diversi (tre collegamenti in parallelo) fino a .
- Grafo pesato: router = nodi, reti tra due router = archi con un costo, se non c'è arco. Percorso di costo minimo (LCR): somma minima dei costi (costo additivo) tra tutti i cammini da a .
- Con router servono percorsi; si raccolgono in un albero di costo minimo per sorgente (radice = il router, un solo albero per sorgente, in tutto).
Metriche
| criterio | costo |
|---|---|
| minimo numero di salti | |
| minimo ritardo end-to-end | |
| minima probabilità di perdita | |
| massimo throughput | , intero |
- Ritardo: bit, Mbit/s, ms ms.
- Perdite: e : successo ; (minimizzare la somma = massimizzare il successo).
- Throughput = minimo dei bitrate (collo di bottiglia), non una somma: non è additivo, si approssima con grande. Es. : 10 collegamenti da 100; : 50 e 100. : , (vince , sbagliato); : , (vince , giusto).
- Statico (tabelle a mano, reti piccole, nessuna reazione ai guasti) contro dinamico (il protocollo aggiorna le tabelle; traffico di controllo e tabelle incoerenti nei transitori).
| link state | distance vector | path vector | |
|---|---|---|---|
| algoritmo | Dijkstra | Bellman-Ford | spanning tree con politica |
| informazione | topologia completa | solo vicini | solo vicini |
| si scambia | i propri collegamenti con tutti | distanze verso tutti con i vicini | cammini interi con i vicini |
| obiettivo | costo minimo | costo minimo | raggiungibilità per politica |
| protocolli | OSPF, IS-IS | RIP, IGRP | BGP |
Link state
- HELLO (identifica i vicini), ECHO (misura il costo locale), poi il Link State Packet (sorgente + coppie vicino-costo) diffuso con flooding a tutti, da ripetere a ogni cambio di stato. Con tutti gli LSP ogni router ha il grafo e applica Dijkstra.
- Esempio (archi , , , , , , , , ): LSP di = (B 4, F 1).
Dijkstra (one-to-all)
- Stato di ogni nodo : stima della distanza e etichetta permanente (distanza minima già nota) o temporanea.
- ha ed è il nodo corrente, gli altri .
- Rilassamento per ogni vicino non permanente del corrente : ; se vince il secondo termine si aggiorna il predecessore di .
- Diventa permanente (e corrente) il temporaneo con minima; si ripete finché ci sono nodi temporanei raggiungibili.
- Il cammino si legge seguendo i predecessori da a e invertendo.
- Complessità: scorrendo l'elenco ; con coda con priorità .
- Esempio 1 (sorgente 1; , , , , , , , , ): si fissano 1 (), 2 (), 3 (), 6 (), poi 5 () e 4 (, pari merito con 5). Distanze , , , , . Cammino (costo ) e ().
- Esempio 2 (sorgente ), ordine di fissaggio :
| passo | permanenti | B | C | D | E | F | G |
|---|---|---|---|---|---|---|---|
| 0 | 4-A | 1-A | |||||
| 1 | 4-A | 4-F | 1-A | 2-F | |||
| 2 | 3-G | 6-G | 4-F | 2-F | |||
| 3 | 3-G | 5-B | 4-F | ||||
| 4 | 5-B | 10-E | 4-F | ||||
| 5 | 5-B | 8-C | |||||
| 6 | 8-C |
- Passi chiave: da , ; da , ; da , .
- Albero di : , , , , , . Tabella di (tutto con next hop ): , , , , , . Ogni router esegue Dijkstra da sé, con sé stesso come sorgente.
Distance vector
- Nessuno conosce la topologia: ogni nodo parte dai vicini (HELLO/ECHO) e costruisce il vettore delle distanze (distanza e next hop per ogni destinazione). DV iniziale di : via , via , il resto .
- I DV si mandano ai vicini a intervalli casuali tra 25 e 35 s o quando cambiano. Riga non aggiornata entro 180 s (expiration): costo ; cancellata dopo altri 120 s (garbage collection).
Bellman-Ford: , con costo del collegamento e costo stimato da a ; se vince il secondo termine, next hop .
- Esempio: riceve il DV di (; , ): , , resta ( non lo conosce). Poi da (; , ): , .
- Convergenza a giri sincroni (vettore di ):
| giro | B | C | D | E | F | G |
|---|---|---|---|---|---|---|
| 0 | 4 | 1 | ||||
| 1 | 4 | 6 | 4 | 1 | 2 | |
| 2 | 3 | 6 | 9 | 4 | 1 | 2 |
| 3 | 3 | 5 | 9 | 4 | 1 | 2 |
| 4 | 3 | 5 | 8 | 4 | 1 | 2 |
- Il giro 5 non cambia niente: regime, uguale a Dijkstra. Il giro trova i cammini con al più archi; ottimo (, costo 8) ha 5 archi, quindi serve il giro 4.
- A regime : via , via , via , via , via , via .
Guasti e conteggio all'infinito
- Guasto : non riceve più HELLO, toglie dai vicini, cancella le righe con next hop , manda il nuovo DV. A regime raggiunge con via e raggiunge con via .
- Con rotto anche ( raggiungeva con 5 via ): riceve il DV di (" a 5") e calcola via ; calcola ; calcola ... il costo cresce di 4 a ogni scambio completo () e i pacchetti rimbalzano tra e (ciclo a due salti).
- Rimedi:
- infinito limitato: distanza oltre 16 = infinito (funziona se la distanza massima tra due nodi è inferiore a 16; qui );
- hold down: 60 s in cui si ignorano gli aggiornamenti su una destinazione appena data per irraggiungibile (costo: reazione più lenta ai cambi);
- aggiornamento immediato (triggered update): i cambi di topologia sono notificati subito;
- split horizon: a non si mandano le righe che hanno come next hop ( non manda a la riga di );
- poison reverse: si mandano tutte le righe ma con per quelle raggiungibili attraverso il collegamento su cui si invia (così distingue "non conosco " da "lo raggiungo da te").
- Split horizon e poison reverse tolgono i cicli a due salti ma non tutti (con tre o più nodi il conteggio può tornare): si combinano con l'infinito limitato.
| distance vector | link state |
|---|---|
| RIP, Bellman-Ford | OSPF, Dijkstra |
| manda (una copia di) tutta la tabella | manda solo gli aggiornamenti dei collegamenti |
| non richiede la topologia | richiede la topologia |
| aggiornamenti frequenti, convergenza lenta | aggiornamenti legati agli eventi, convergenza rapida |
Path vector
- Il costo non permette alla sorgente di imporre politiche: nel path vector il cammino lo sceglie la sorgente secondo la sua politica (es. "meno nodi possibile", "evita certi nodi intermedi"). Scopo: raggiungibilità, senza costi; l'albero è di copertura ma non di costo minimo.
- Asincrono e distribuito: vettore iniziale dai vicini (HELLO + ECHO), invio ai vicini, combinazione con , .
- Cicli: l'annuncio contiene l'intero cammino; se compare già il nodo stesso, lo scarta. Niente conteggio all'infinito (BGP, con i numeri di AS).
- Esempio: archi , , , , , destinazione ; riceve "" e ""; con la politica "non attraversare " sceglie .
Correttezza
- Sottostruttura ottima: ogni tratto di un cammino minimo è minimo (se no, sostituendolo si migliorerebbe il totale). Equazione di Bellman: sui vicini di .
- Dijkstra (): quando diventa permanente . Induzione: se esistesse un cammino di costo , esce dai permanenti da un primo arco , e cioè rilassamento, ipotesi induttiva, minimalità di e ; ma allora (temporaneo) avrebbe , contro la scelta di . Con costi negativi cade: , , dà ma costa .
- Bellman-Ford: , e è il minimo sui cammini con al più archi (induzione sul primo arco ). Senza cicli negativi un cammino minimo è semplice, ha al più archi: convergenza dopo giri. Nell'esempio è il primo valore esatto.
- Versione asincrona: le stime non scendono sotto il vero (sono costi di cammini esistenti) e diventano esatte in al più periodi. Dopo un guasto alcune stime descrivono cammini che non esistono più: da qui il conteggio all'infinito, che Dijkstra (grafo completo) non ha.
- Errori tipici: dimenticare il di (giro = archi), scambiare le etichette sugli archi dell'albero (distanze da ) per costi, usare Dijkstra con costi negativi, scambiare split horizon (omette la riga) con poison reverse (la manda a ).