Scarica

Transcript

Scarica
RELAZIONE III Trimestre 2012
Realizzazione TOOL di Collezionamento Dati
Progettazione di Giorgio Sadolfo
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 1
Introduzione
Nel terzo semestre del nostro progetto è stato analizzato e realizzato un collezionatore di
dati per il nostro sistema
In una prima fase è stato preso come sistema di riferimento l’approccio del RouteCollector
usato dal RIPE.
Il mero collezionatore del RIPE non è sufficiente però al nostro scopo di fatti in questi
mesi la prima analisi è stata effettuata verso la tipologia di pacchetti BGP che circolano
nella rete per gli annunci di tipo MPLS-VPN e VPLS.
Analisi dei pacchetti BGP
Le informazioni principali, necessarie per instaurare i collegamenti della rete VPLS,
viaggiano all’interno dei pacchetti BGP. Questi pacchetti sono di quattro tipi:
• Open
• Update
• Notification
• Keepalive
In fase di signaling i router inviano, innanzitutto, pacchetti di tipo Open tramite i quali
annunciano agli altri PE le proprie capacità. Questa fase si chiama Negoziazione delle
Capability : se due PE non hanno capability in comune, il peer tra i due non può essere
instaurato (è un po’ come dire che i due dispositivi non conoscono una lingua comune e
quindi non possono parlare). Nel caso in cui il peer sia correttamente instaurato saranno
inviati periodicamente, in genere in corrispondenza di variazioni, dei pacchetti di tipo
Update. I pacchetti Notification e Keepalive sono invece inviati rispet- tivamente per
notificare errori o problemi di vario genere e per informare regolarmente gli altri PE sullo
stato di vita.
Il pacchetto di Update
I pacchetti di Update vengono inviati per notificare variazioni agli altri PE. Ovviamente,
a seconda della tecnologia con cui la rete è realizzata, questi pacchetti avranno formati
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 2
diversi. In particolare per venire incontro alle esigenze dettate dalle reti MPLS e
VPLS è stata progettata un’estensione
di BGP chiamata Multiprotocol BGP (MP-BGP) che permette ai pacchetti BGP di
trasportare informazioni di routing per molteplici protocolli di livello 3.
Per abilitare BGP alla gestione di un maggior numero di protocolli è stato necessario
aggiungere due funzioni:
• la capacità di associare le informazioni di nexthop al particolare proto- collo.
• la capacità di associare la semantica di NLRI al particolare protocollo.
A questo scopo, nei pacchetti MP-BGP viene usata una combinazione di valori numerici
chiamati Address Family Identifier (AFI) e Subsequent Address Family Identifier
(SAFI) per identificare i diversi protocolli.
La struttura del pacchetto ha subito delle
variazioni in seguito a questa estensione,
ma in tutte le varianti la maggior parte
delle informazioni uti- li si trovano nella
sezione NLRI (Network Layer Reachability
Information ). Come si intuisce dal nome
stesso, questa parte di pacchetto contiene
i da- ti necessari a conoscere le nuove rotte
per la raggiungibilità dei dispositivi, in
senso positivo negli Update di tipo
Announce, oppure in senso negativo
(ovvero
per l’irraggiungibilità) negli
Update di tipo Withdraw.
Vediamo quindi i pacchetti di Update nelle
diverse versioni.
Versione Standard
In figura è mostrata la porzione BGP di un pacchetto standard di Update. Nelle reti IP
classiche le informazioni scambiate tramite gli Update sono relative alle classi di
indirizzi che si rendono raggiungibili o irraggiungibili attraverso un certo router. In
questo tipo di pacchetti quindi la sezione NLRI altro non è che un elenco di prefissi.
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 3
Versione MPLS
Nelle reti MPLS si utilizzano i pacchetti MP-BGP per poter trasporta- re le informazioni
sulle etichette e sulle VPN. In MP-BGP la sezione NL- RI è contenuta in una nuova
porzione del pacchetto che prende il nome di MP_REACH_NLRI e di MP_UNREACH_NLRI,
rispettivamente in ca- so di Announce e di Withdraw; in figura 2.7 è evidenziato un
esempio di MP_REACH_NLRI. L’AFI è impostato a 1, valore che identifica i servizi basati
su IPv4, mentre il SAFI è impostato a 128, valore che identifica i ser- vizi basati su VPN
etichettate: MPLS è infatti un servizio di VPN gestite tramite etichette e basato su IPv4.
Nella parte NLRI sono contenute le in- formazioni sulle etichette e sulle classi di indirizzi
relative ad una certa VPN, identificata da un Route Distinguisher (RD).
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 4
Versione VPLS
Anche
il
pacchetto VPLS
è realizzato con
MP-BGP
e
contiene
le
sezioni
MP_REACH_NLR
I
e
MP_UNREACH_N
LRI. In questo
caso,
mentre
l’AFI, pari a 25,
identifica
genericamente
le VPN di livello
2, il SAFI, pari a
65,
identifica
specificamente
la
tecnologia
VPLS. La sezione
NLRI
contiene
tutte
le
informazioni necessarie ai PE per calcolare gli identificativi. Nella figura è stato
evidenziato anche il Route Target, presente nella sezione EXTENDED_COMMUNITIES
del pacchetto: il Route Target, insieme al Route Distinguisher è usato per identificare le
VPN, e la loro combinazione può essere utilizzata in modi particolari per realizzare reti
VPLS inter-provider.
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 5
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 6
IL COLLEZIONATORE
Grazie all’attenta analisi dei pacchetti si è potuto sviluppare al meglio il collezionatore,
cogliendo fino a fondo quali sono le peculiarità di ogni pacchetto in ogni caso possibile.
Raccolta dei dati
Data la forte analogia con iBGPlay, per la parte di raccolta
sono state ricalcate le stesse scelte architetturali, ovvero:
• Un RC realizzato con Linux.
• Peer instaurati tramite il software di routing Quagga.
• Update memorizzati in formato MRT.
• Dati estratti con la libreria Lib BGP Dump.
• Gestione della sincronizzazione delle operazioni tramite
una serie di Script Shell.
In figura viene mostrato un diagramma di flusso che
rappresenta le diverse fasi necessarie a popolare la base di
dati con le informazioni che saranno utilizzate dal software
di elaborazione e presentazione.
Ovviamente per la fase di raccolta è necessaria una rete VPLS
funzionante alla quale collegare il RC. Una rete di questo
genere è stata effettivamente realizzata nel Laboratorio di
Reti di Calcolatori presso il Dipartimento di Ingegneria
Informatica di Roma Tre.
I COMPONENTI DEL COLLEZIONATORE
Quagga
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 7
Quagga5 è una suite di software di routing che offre implementazioni di OSPFv2, RIP e
BGP-4 per piattaforme Unix, in particolare FreeBSD, Linux, Solaris e NetBSD. Permette
quindi di realizzare macchine in grado di emulare dispositivi di routing simil-Cisco, in
quanto il sistema di Quagga è basato su Cisco IOS6.
Quagga purtroppo però ha un limite: non gestisce il protocollo VPLS ne tantomeno quello
MPLS
La negoziazione delle capabilities
Quando si cerca di instaurare un peer tra due dispositivi questi si comu-nicano a vicenda
le proprie capability. Ognuno dei due dispositivi confeziona un pacchetto BGP di tipo
Open in cui elenca i protocolli che è in grado di gestire e lo invia sulla rete. Quando l’altro
riceve il pacchetto confronta l’e-lenco delle capability presenti nel pacchetto con le
proprie: se ce ne sono di comuni allora il peer viene instaurato, altrimenti il peer viene
rifiutato e un pacchetto di tipo Notification con il messaggio Unsupported Capabilities
viene inviato.
Questo meccanismo impediva l’instaurazione di un peer tra il RC e gli specifici router:
per questo motivo il codice sorgente di Quagga7 è stato opportuna mente esteso.
Lib BGP Dump
Libbgpdump è una libreria scritta in C progettata appositamente per analizzare i file di
dump generati da Quagga in formato MRT. È attualmente alla versione 1.4.9.11 ed è in
grado di analizzare pacchetti BGP di tutti i tipi (Open, Notification, ecc.) e pacchetti MPBGP relativi alla tecnologia MPLS. Anche in questo caso quindi il codice sorgente è
stato esteso per poterlo utilizzare anche con VPLS.
Estensione di Quagga
Quagga è un software libero e open source. La soluzione più semplice quindi, come già
accennato, è stata quella di prendere il codice sorgente, scritto in C, ed estenderlo per
VPLS. La versione utilizzata è stata la 0.99.16.
In realtà l’unica cosa effettivamente necessaria era che il peer venisse instaurato in modo
che i pacchetti di Update inviati dai PE arrivassero an- che al RC; il RC non deve fare nulla
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 8
se non raccogliere questi pacchetti e comportarsi in maniera totalmente trasparente
rispetto alla rete.
Per questo motivo l’estensione di Quagga ha comportato modifiche sola- mente nei punti
in cui viene confezionato il pacchetto di Update da inviare e in quelli in cui viene aperto il
pacchetto di Update ricevuto. Oltre a queste, sono state apportate altre modifiche per
impostare il peer VPLS tramite il terminale.
Per la negoziazione delle capability Quagga utilizza una struttura dati che contiene
informazioni riguardanti il peer, come l’AS number, dei buffer per i pacchetti ricevuti e
inviati, indirizzo e porta dell’altro capo del peer, svariati timer e una serie di flag per la
gestione delle capability. Contiene anche una serie di matrici utilizzate specificatamente
per le procedure di negoziazione:
/* ESTRATTO DAL FILE bgpd.h */
/* BGP neighbor structure. */
struct peer {
/* ... omissis ... */
/* Peer address family configuration. */
u_char afc[AFI_MAX][SAFI_MAX]; u_char
afc_nego[AFI_MAX][SAFI_MAX]; u_char
afc_adv[AFI_MAX][SAFI_MAX]; u_char
afc_recv[AFI_MAX][SAFI_MAX];
/* ... omissis ... */
};
Nel file zebra.h erano definiti tramite macro i codici AFI e SAFI come segue:
1 AFI_IP
1 SAFI_UNICAST
2 AFI_IP6
2 SAFI_MULTICAST
3 AFI_MAX
3 SAFI_UNICAST_MULTICAST
4 SAFI_MPLS_VPN
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 9
5 SAFI_MAX
A questi codici sono stati aggiunti quelli per VPLS e sono stati di conseguenza
incrementati i valori massimi.
1 AFI_IP
1 SAFI_UNICAST
2 AFI_IP6
2 SAFI_MULTICAST
3 AFI_VPLS
3 SAFI_UNICAST_MULTICAST
4 AFI_MAX
4 SAFI_MPLS_VPN
5 SAFI_VPLS
6 SAFI_MAX
Questi codici non sono tutti reali. Le coppie di valori AFI/SAFI per MPLS e VPLS sono
rispettivamente 1/128 e 25/65. Tuttavia era comodo avere i codici definiti in questo
modo per poterne sfruttare la sequenzialità nei blocchi iterativi di codice. Per questo
motivo in opportuni punti sono anche presenti istruzioni di conversione dei valori di
AFI e SAFI (un esempio nel listato che segue).
/* ESTRATTO DAL FILE bgpd.c */
/* Adjust vpls afi code. */
if (mpc.afi == AFI_L2VPN) // AFI_L2VPN = 25
mpc.afi = AFI_VPLS;
// AFI_VPLS = 3
/* Adjust vpls safi code. */
if (mpc.safi == BGP_SAFI_L2VPN) // BGP_SAFI_L2VPN = 65
mpc.safi = SAFI_VPLS;
//
SAFI_VPLS =
5
Questi codici sono stati usati come indici delle matrici viste in precedenza, in modo da
poterle scorrere e verificare quali AFI e SAFI sono stati annun- ciati, ricevuti, negoziati o
impostati. È proprio su questi punti di verifica o di impostazione delle matrici che si sono
concentrate le modifiche al codice.
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 10
Quagga dichiara VPLS
Il metodo int peer_activate(struct peer *peer, afi_t afi, safi_t safi) nel file bgpd.c si occupa
di attivare il peer. Per farlo in un punto del codice invoca il metodo
bgp_capability_send(peer, afi, safi, CAPAB_CODE_MP, CAPAB_ACTION_SET) situato nel
file bgp_packet.c.
/* ESTRATTO DAL FILE bgpd.c */
/* ... omissis ... */
peer->afc_adv[afi][safi] = 1;
bgp_capability_send (peer, afi, safi,
CAPAB_CODE_MP, CAPAB_ACTION_SET);
if (peer->afc_recv[afi][safi]) {
peer->afc_nego[afi][safi] = 1;
/* ... omissis ... */
}
/* ... omissis ... */
1. Viene inserita in afc_adv la capability.
2. Viene inviata tramite pacchetto Open (vedere il prossimo metodo).
3. Se la capability è stata anche ricevuta allora viene inserita in afc_nego.
Nel metodo void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi, int
capability_code, int action) c’è l’effettiva costru- zione del pacchetto da inviare con le
capability dichiarate:
/* ESTRATTO DAL FILE bgp_packet.c */
s = stream_new (BGP_MAX_PACKET_SIZE);
/* ... omissis ... */
/* Encode MP_EXT capability. */
if (capability_code == CAPAB_CODE_MP) {
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 11
stream_putc (s, action); stream_putc
(s, CAPAB_CODE_MP); stream_putc
(s, CAPAB_CODE_MP_LEN); stream_putw
(s, afi);
stream_putc (s, 0);
stream_putc (s, safi);
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 12
/* ... omissis ... */
}
/* ... omissis ... */
In realtà si può notare come in questi punti non ci siano stati interventi di modifica.
Il fatto di aver aggiunto nella lista degli AFI e dei SAFI dispo- nibili quelli per VPLS, ha
automaticamente permesso la dichiarazione di tale capability da parte di Quagga,
essendo i metodi visti totalmente parametrici.
Quagga accetta VPLS
Nel file bgp_packet.c è presente un metodo che si occupa della lettura dei pacchetti
ricevuti: int bgp_read(struct thread *thread). In questo metodo è presente uno
switch-case sulla base del tipo di pacchetto, del quale vediamo in particolare due
casi:
/* ESTRATTO DAL FILE bgp_packet.c */
/* ... omissis ... */
switch (type) {
case BGP_MSG_CAPABILITY: peer>dynamic_cap_in++;
bgp_capability_receive (peer, size);
break;
/* omissis */
case BGP_MSG_OPEN:
peer->open_in++;
bgp_open_receive (peer, size);
break;
}
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 13
/* ... omissis ... */
Il metodo int bgp_capability_receive(struct peer *peer, bgp_size_t size) richiama il parsing
del messaggio:
/* ESTRATTO DAL FILE bgp_packet.c */
/* ... omissis ... */
/* Parse packet. */
return bgp_capability_msg_parse (peer, pnt, size);
Nel parsing del messaggio (nel metodo static int bgp_capability_msg_parse (struct peer *peer,
u_char *pnt, bgp_size_t length)) si impostano le capability ricevute ed eventualmente quelle
negoziate:
/* ESTRATTO DAL FILE bgp_packet.c */
/* ... omissis ... */
if (action == CAPABILITY_ACTION_SET) {
peer->afc_recv[afi][safi] = 1;
if (peer->afc[afi][safi]) {
peer->afc_nego[afi][safi] = 1;
/* omissis */
}
}
/* ... omissis ... */
Il metodo static int bgp_open_receive(struct peer *peer, bgp_size_t size) invoca anch’esso un
parsing:
/* ESTRATTO DAL FILE bgp_packet.c */
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 14
/* Open option part parse. */
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 15
if (optlen != 0) {
ret = bgp_open_option_parse (peer, optlen, &capability);
if (ret < 0)
return ret;
}
In questo metodo di parsing (int bgp_open_option_parse(struct peer *peer, u_char
length, int *capability) nel file bgp_open.c) sono sta- ti necessari degli interventi
espliciti per VPLS, in quanto qui è presente il vero e proprio confronto tra le
capability:
/* ESTRATTO DAL FILE bgp_open.c */
/* ... omissis ... */
/* Check: if there is no common capability
send Unsupported Capability error. */
if (*capability && ! CHECK_FLAG (peer->flags,
PEER_FLAG_OVERRIDE_CAPABILITY)) {
if(! peer->afc_nego[AFI_IP][SAFI_UNICAST]
&&
! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
&&
! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
&&
! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
&&
! peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
&&
/* ESTENSIONE VPLS */
! peer->afc_nego[AFI_VPLS][SAFI_VPLS])
//AFI= 3 SAFI= 5
{
plog_err (peer->log, "%s [Error] No common capability",
peer->host);
/* ... omissis ... */
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 16
bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_UNSUP_CAPBL);
return -1;
}
}
/* ... omissis ... */
In pratica se nella struttura di negoziazione non si trova nessuna delle capability
note allora viene inviato un pacchetto BGP di tipo Notification che informa in merito
all’assenza di capability comuni.
Il terminale di Quagga
Con le modifiche viste finora Quagga è pronto per annunciare e accettare VPLS.
Manca solo un elemento: la possibilità di configurare un peer VPLS dal terminale di
Quagga.
Il funzionamento del terminale di Quagga riflette la struttura ad albero del file
bgpd.conf, che contiene la configurazione di BGP. Quello che segue ne è un estratto.
!
! Zebra configuration saved from vty
!
router bgp 50
bgp router-id 40.0.0.19
neighbor 10.0.0.1 remote-as 50
!
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 17
line vty
!
bgpd# configure terminal
bgpd(config)# router bgp 50
bgpd(config-router)# bgp router-id 40.0.0.19
bgpd(config-router)# neighbor 10.0.0.1 remote-as 50
bgpd(config-router)# exit
bgpd(config)# exit
bgpd#
Si possono notare due livelli di profondità: il config e il config-router. Questi livelli
sono gestiti come nodi definiti tramite macro nel file command.h. La prima
operazione per estendere le configurazioni è stata quindi l’aggiunta di un opportuno
nodo e la specifica della sua posizione all’interno dell’albero:
/* ESTRATTO DAL FILE command.h */
enum node_type {
/* ... omissis ... */
BGP_NODE,
/* BGP node including BGP4+ */
BGP_L2VPN_NODE,
/* NEW: BGP VPLS Node */
VTY_NODE,
/* Vty node. */
};
/* ESTRATTO DAL FILE command.c */
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 18
enum node_type node_parent ( enum node_type node ) {
enum node_type ret;
switch (node) {
case BGP_L2VPN_NODE: /* ESTENSIONE VPLS */
case BGP_VPNV4_NODE:
case BGP_IPV4_NODE:
ret = BGP_NODE;
break;
}
return ret;
}
A questo punto sono state definite le funzioni necessarie per effettuare
configurazioni sotto l’address family L2VPN3. Il codice di Quagga prevede un
meccanismo automatico e parametrico molto interessante che permette la
definizione di nuove funzioni all’interno del vty specificandone le singole parti della
segnatura:
/* ESTRATTO DAL FILE command.h */
#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
DEFUN_CMD_FUNC_DECL(funcname) \
/* ... omissis ... */
#define DEFUN_CMD_FUNC_DECL(funcname) \
static int funcname (struct cmd_element *,
struct vty *, int,
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 19
const char *[]);
Questo sistema è stato usato per definire quindi l’ingresso nel nodo definito in
precedenza e l’uscita da esso:
/* ESTRATTO DAL FILE bgp_vty.c */
DEFUN (address_family_l2vpn,
address_family_l2vpn_cmd,
"address-family l2vpn",
"Enter Address Family command mode\n"
"Address family\n") {
vty->node = BGP_L2VPN_NODE;
return CMD_SUCCESS;
}
/* ESTRATTO DAL FILE bgp_vty.c */
DEFUN (exit_address_family,
exit_address_family_cmd,
"exit-address-family",
"Exit from Address Family configuration mode\n") {
if (vty->node == BGP_L2VPN_NODE)
vty->node = BGP_NODE;
return CMD_SUCCESS;
}
Infine deve essere definita la stringa che verrà visualizzata come prompt dei
comandi:
/* ESTRATTO DAL FILE bgp_vty.c */
static struct cmd_node bgp_l2vpn_node =
{ BGP_L2VPN_NODE, "%s(config-router-af-l2vpn)# " };
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 20
Una volta implementate le nuove funzioni queste devono essere installate nel vty,
insieme a quelle già definite che devono essere funzionanti anche con il nodo L2VPN,
come ad esempio l’attivazione e la disattivazione dei neighbor:
void bgp_vty_init (void) {
install_node (&bgp_l2vpn_node, NULL);
install_default (BGP_L2VPN_NODE);
install_element (BGP_L2VPN_NODE, &neighbor_activate_cmd);
install_element (BGP_L2VPN_NODE, &no_neighbor_activate_cmd);
install_element (BGP_NODE, &address_family_l2vpn_cmd);
install_element (BGP_L2VPN_NODE, &exit_address_family_cmd);
}
A questo punto Quagga può essere configurato per VPLS tramite vty. Aseguire un
esempio di configurazione e di file bgpd.conf generato:
bgpd# configure terminal
bgpd(config)# router bgp 50
bgpd(config-router)# bgp router-id 40.0.0.19
bgpd(config-router)# neighbor 10.0.0.1 remote-as 50
bgpd(config-router)# address-family l2vpn
bgpd(config-router-af-l2vpn)# neighbor 10.0.0.1 activate
bgpd(config-router-af-l2vpn)# exit
bgpd(config-router)# exit
bgpd(config)# exit
bgpd#
!
! Zebra configuration saved from vty
!
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 21
router bgp 50
bgp router-id 40.0.0.19 neighbor
10.0.0.1 remote-as 50
!
address-family vpnv4 unicast
neighbor 10.0.0.1 activate exitaddress-family
!
line vty
!
In altri punti del codice sono presenti le istruzioni per la compilazione automatica del file
bgpd.conf e anche in questi punti si è dovuto intervenire, in maniera molto simile a
quanto già visto per le modifiche al terminale, affinché il file venisse opportunamente
compilato come appena mostrato.
Estensione di Lib BGP Dump
Libbgpdump funziona in modo semplice ma a un livello molto basso:
1. Carica il file che gli viene passato in input e lo trasforma in uno stream di byte.
2. Legge byte per byte lo stream ed estrae i campi del pacchetto di Update.
3. Inserisce i campi in una struttura dati che ricalca il pacchetto.
4. Stampa questi campi in tre modi:
• Una descrizione dettagliata.
• Due diverse descrizioni compatte.
Le modifiche quindi hanno interessato tre punti: la definizione delle strutture adatte,
il parsing del file MRT, la stampa dei campi.
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 22
Il parsing del file MRT
La lettura dello stream è comune a quella per gli Update di tipo MPLS fino al punto in cui
viene letto l’AFI. A questo punto è presente un blocco switch-case sul valore dell’AFI in
cui è stato inserito il caso di AFI pari a 25 (ovvero VPLS).
/* ESTRATTO DAL FILE bgpdump_lib.c */
switch(afi) {
case AFI_L2VPN:
mstream_getc(s, &vpls_info->nexthop_len); // 1 byte
mstream_get_ipv4(s, &vpls_info->nexthop); // 4 byte
mstream_getc(s, &vpls_info->subnet_points_attach); // 1 byte
mstream_getw(s, &vpls_info->lenght); // 2 byte
mstream_getw(s, &vpls_info->rd_type); // 2 byte
switch(vpls_info->rd_type){
case (0):
mstream_getw(s, &vpls_info->rd_admin_subfield_2);
mstream_get_ipv4(s, &vpls_info->rd_number_subfield_4);
break;
case (1):
mstream_get_ipv4(s, &vpls_info->rd_admin_subfield_4);
mstream_getw(s, &vpls_info->rd_number_subfield_2);
break;
case (2):
mstream_getl(s, &vpls_info->rd_admin_subfield_4);
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 23
mstream_getw(s, &vpls_info->rd_number_subfield_2);
break;
} // 6 byte
mstream_getw(s,&vpls_info->ce_id); // 2 byte mstream_getw(s,
&vpls_info->label_block_offset); // 2 byte mstream_getw(s,
&vpls_info->label_block_size); // 2 byte u_int8_t one_byte;
mstream_get(s, &vpls_info->label_base, (3*sizeof(one_byte)));
vpls_info->label_base = ntohl(vpls_info->label_base); vpls_info>label_base = vpls_info->label_base >> 12;
// 20 bit
break;
/* omissis */
}
Per il route distinguisher è stato inserito un ulteriore blocco switch-case perché questo valore
può essere definito in tre modi diversi, ciascuno identi- ficato dal type field (i primi due byte)
:
• Type = 0: Administrator subfield (un AS number di 2 byte) + Assigned Number
subfield (un numero scelto dal provider di 4 byte)
• Type = 1: Administrator subfield (un IP di 4 byte) + Assigned Number subfield
(un numero scelto dal provider di 2 byte)
• Type = 2: Administrator subfield (un AS number di 4 byte) + Assigned Number
subfield (un numero scelto dal provider di 2 byte)
La lettura del campo label base è stata piuttosto complessa: i metodi offerti dalla libreria
libbgpdump (ma anche da C stesso) permettono di leggere a blocchi di byte e non sono
quindi adatti per leggere i 20 bit (due byte e mezzo ) della label base. L’artificio utilizzato è
stato quello di:
1. Leggere esattamente 3 byte.
2. Convertirli da formato network a formato host (necessario in ogni ca- so per
problemi di rappresentazione) considerando un’unità di 4 byte: questo ha provocato
il riempimento del byte mancante con degli zeri.
3. Effetuare uno shift opportuno di quanto ottenuto per eliminare i bit in eccesso.
I dati presenti nella struttura possono essere infine stampati. Nella figura
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 24
sono mostrati i tre tipi di output quando l’operazione è invocata senza parametri, con il
parametro -m o con il parametro -M.
Popolamento della base di dati
A questo punto è possibile utilizzare questi pezzi per mettere insieme il
RC: la composizione è effettuata tramite una serie di script shell.
Lo script di installazione si occupa di:
1. Copiare negli opportuni percorsi il file eseguibile del demone Quagga.
2. Instaurare il peer secondo quanto specificato in un file di configurazione
precompilato.
3. Attivare dei cronjob che eseguono la lettura e il dumping degli update tramite un
ulteriore script chiamato retriever_ibgp.sh.
Lo script retriever_ibgp.sh esegue una pipeline di comandi:
1. cat del file MRT dell’update.
2. bgpdump -m sull’output del cat, generando una serie di campi separati
dal carattere |.
3. awk con il carattere | come separatore.
4. Inserimento degli elementi di output di awk in un array.
5. Creazione di una tabella sul database MySql che ha come nome il nome del file mrt
letto.
6. Inserimento degli elementi dell’array nella tabella appena creata.
#! ESTRATTO DAL FILE retriever_ibgp.sh
#!/bin/sh
cat "$i" | $BGPDUMP_PATH/bgpdump -m ->
$HUMAN_READABLE_FILE_PATH/‘basepath $i‘
mysql -u $DB_USER -h $DB_HOST $DB_NAME --password=$DB_PASSWORD -e
"CREATE
TABLE IF NOT EXISTS $tablename (
type_packet VARCHAR(40) NOT NULL,
#! omissis
label_base INT UNSIGNED default NULL;"
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 25
A questo punto il database ha iniziato a riempirsi di dati estratti dai file di update che
circolavano sulla rete in esercizio.
RELAZIONE III° TRIMESTRE: GIORGIO SADOLFO
Pag. 26