• Non ci sono risultati.

UniK OLSR e scritto in linguaggio C ed e completamente compatibile con lo standard RFC 3626 [CJ03]

N/A
N/A
Protected

Academic year: 2021

Condividi "UniK OLSR e scritto in linguaggio C ed e completamente compatibile con lo standard RFC 3626 [CJ03]"

Copied!
16
0
0

Testo completo

(1)

Capitolo 6

ARCHITETTURA UniK OLSR

Nell'ambito di questa tesi, per realizzare una possibile soluzione di interazione cross-layer middleware-routing, abbiamo selezionato una particolare implementazione del protocollo proattivo OLSR: UniK OLSR [UNI]. Abbiamo scelto di utilizzare UniK OLSR perche e possibile estendere le sue funzionalita attraverso il collegamento dinamico di opportune librerie.

In particolare (come vedremo in dettaglio nel capitolo Architettura Plugin) e stata sviluppata una libreria a collegamento dinamico (plugin) per realizzare delle interazioni di tipo cross-layer con il protocollo di livello middleware CrossROAD.

UniK OLSR e un'implementazione open source del protocollo di routing OLSR realizzata presso l'Universita di Oslo in Norvegia. La prima versione

e stata sviluppata per sistemi GNU/Linux come parte del lavoro di tesi di uno studente. In seguito ha raccolto l'interesse di un grande numero di sviluppatori e utilizzatori in tutto il mondo ed e oggi disponibile per diverse piattaforme hardware-software (MacOS, FreeBSD, Windows, Linux).

Nell'ambito di questa tesi faremo riferimento alla versione 0.4.8 per sistemi GNU/Linux.

UniK OLSR e scritto in linguaggio C ed e completamente compatibile con lo standard RFC 3626 [CJ03]. E' caratterizzato da un'architettura interna

(2)

6.1 Il modulo Socket Parser

fortemente modulare che lo rende piu facile da mantenere e aggiornare nel tempo. Inoltre funziona in modo trasparente sia su reti IPv4 che su reti IPv6, ovvero e in grado di gestire sia indirizzi IP a 32 bit che indirizzi IP a 128 bit.

Nei prossimi paragra dettaglieremo i singoli componenti dell'architettura software di UniK OLSR, illustrata in gura 6.1.

Figura 6.1: Struttura generale UniK OLSR

6.1 Il modulo Socket Parser

Come illustrato in gura 6.1, tutto il traco OLSR in ingresso al nodo viene innanzitutto gestito dal modulo Socket Parser. Tale modulo, utilizzando la chiamata di sistema select(2), attende l'arrivo di dati in ingresso su uno qualsiasi dei socket che sono stati registrati presso UniK OLSR. Non appena rileva la presenza di dati in ingresso su uno qualsiasi di questi socket, esegue automaticamente la funzione associata al socket interessato (come illustrato in gura 6.2).

(3)

6.1 Il modulo Socket Parser

Figura 6.2: Struttura Socket Parser

I socket e le funzioni associate vengono aggiunti o rimossi a tempo d'esecuzione.

Per aggiungere un nuovo socket possiamo chiamare la funzione:

void a d d o l s r s o c k e t ( int , void (  ) ( int ) ) ;

Il primo argomento e il descrittore del nuovo socket su cui veri care l'arrivo dei dati mentre il secondo argomento e un puntatore alla funzione associata.

Per rimuovere un socket possiamo chiamare la funzione:

void r e m o v e o l s r s o c k e t ( int , void (  ) ( int ) ) ;

Il primo argomento e il descrittore del socket da rimuovere mentre il secondo argomento e un puntatore alla funzione associata.

Il traco di controllo del protocollo OLSR deve essere trasmesso in broadcast attraverso la porta UDP 698. All'avvio UniK OLSR registra presso il Socket Parser un socket per ciascuna interfaccia di rete presente nel nodo

(4)

6.2 Il modulo Packet Parser

locale. In particolare il Socket Parser passera i pacchetti OLSR ricevuti al Packet Parser, descritto nel prossimo paragrafo.

6.2 Il modulo Packet Parser

Il Packet Parser elabora i messaggi che compongono un pacchetto OLSR invocando una funzione appropriata per ciascun tipo di messaggio. In particolare, dopo aver ricevuto un pacchetto OLSR passato dal Socket Parser, veri ca se la dimensione riportata nell'intestazione corrisponde alla quantita di dati e ettivamente ricevuta, scartando il pacchetto in caso contrario. Se il pacchetto risulta valido, viene elaborato passando i singoli messaggi che lo compongono alle funzioni di parsing associate ai tipi corrispondenti e registrate presso il Packet Parser. Osserviamo che il Packet Parser deve disporre di una diversa funzione di parsing per ciascun tipo di messaggio che deve gestire. Se non dispone di una funzione per un dato tipo di messaggio, si limita ad inoltrarlo in accordo al protocollo OLSR, senza elaborarlo ulteriormente.

E' possibile aggiungere dinamicamente delle funzioni di parsing per elaborare nuovi tipi di messaggio, utilizzando la funzione:

void o l s r p a r s e r a d d f u n c t i o n ( void (  ) ( union o l s r m e s s a g e  , struct i n t e r f a c e  , union o l s r i p a d d r  ) , int , int ) ;

Il primo argomento rappresenta la funzione da invocare quando si riceve un messaggio di un dato tipo, speci cato numericamente con il secondo argomento. Il terzo argomento e interpretato come un valore booleano che indica se la funzione associata e ettua autonomamente l'inoltro del messaggio (quando vale 1) o se si deve utilizzare l'algoritmo previsto da OLSR (quando vale 0).

I messaggi, dopo essere stati elaborati dalle funzioni di parsing corrispondenti, vengono inoltrati in accordo alle speci che del protocollo OLSR (a meno che non si implementino speci che politiche di inoltro per determinati tipi di messaggio).

(5)

6.3 Informazioni di stato

L'elaborazione di un messaggio viene svolta tenendo conto delle informazioni presenti nelle strutture dati interne di UniK OLSR, che saranno aggiornate dopo l'elaborazione

6.3 Informazioni di stato

Un protocollo proattivo quale OLSR utilizza una serie di tabelle che memorizzano l'informazione di stato necessaria per la corretta esecuzione dell'attivita di routing. Le funzioni di parsing dei pacchetti basano il processo di elaborazione sul contenuto di queste tabelle e ne determinano l'aggiornamento.

L'informazione contenuta all'interno delle tabelle, se non rinnovata, diventa obsoleta e viene periodicamente eliminata. In particolare si associa ad ogni entrata delle tabelle di stato un'informazione temporale (timestamp) che indica no a quando tale entrata deve essere considerata valida. Quando viene registrata una nuova entrata di una tabella, il campo timestamp viene inizializzato con un valore dato dalla somma dell'istante in cui avviene la registrazione e della validita speci cata per l'informazione. Periodicamente vengono confrontati i vari timestamp nelle entrate delle tabelle con il tempo corrente e vengono cancellate le entrate obsolete. Questa operazione di aggiornamento viene eseguita con una frequenza elevata per garantire che l'informazione di stato sia sempre quanto piu aggiornata possibile.

Ogni volta che una funzione e ettua delle modi che alle tabelle che speci cano la topologia, deve inviare una noti ca ai processi che le utilizzano, inizializzando delle opportune variabili che determinano un nuovo calcolo della tabella di routing.

6.4 Il modulo schedulatore

Lo schedulatore e un componente del sistema che viene attivato periodicamente e deve lanciare eventi distinti ad intervalli ben de niti.

Ad esempio deve avviare la generazione periodica dei pacchetti previsti

(6)

6.5 Funzionamento di base

dal protocollo OLSR e l'aggiornamento periodico delle tabelle di stato.

Normalmente lo schedulatore avvia un proprio ciclo con un periodo pari a 0.1 secondi. Con un periodo cos breve, in pratica, esso risulta sempre attivo e puo quindi lanciare gli eventi registrati rispettando i tempi previsti.

E' possibile aggiungere o rimuovere degli eventi dallo schedulatore a tempo d'esecuzione.

In particolare per aggiungere un evento da eseguire periodicamente possiamo utilizzare la funzione:

void o l s r r e g i s t e r s c h e d u l e r e v e n t ( void (  ) ( ) , float , float , o l s r u 8 t  ) ;

Il primo parametro e un puntatore alla funzione che deve essere eseguita. Il secondo e il periodo (misurato in secondi) con il quale deve essere eseguita. Il terzo parametro indica un eventuale ritardo iniziale con cui lanciare l'evento.

Il quarto parametro e un valore booleano che, se posto ad 1, indica che l'evento deve essere eseguito ad ogni iterazione dello schedulatore, ignorando quindi il periodo.

6.5 Funzionamento di base

All'avvio, UniK OLSR acquisisce dei parametri da un le di con gurazione che generalmente si chiama olsrd.conf e, nei sistemi GNU/Linux, e collocato nella directory /etc/ (e possibile, tuttavia, speci care un diverso le con l'opzione -f da linea di comando). All'interno del le di con gurazione ci sono una serie di direttive che, assegnando valori numerici a determinate parole chiave, permettono, ad esempio, di speci care le interfacce di rete da usare, la versione di protocollo IP, quali librerie dinamiche devono essere caricate e quali periodi di emissione dei pacchetti utilizzare. Osserviamo che i valori dei parametri presenti nel le di con gurazione possono essere ride niti da linea di comando quando viene lanciato il demone di UniK OLSR (olsrd).

Tutti i tipi di dati e le costanti utilizzate nel codice sorgente del protocollo UniK OLSR sono dichiarati in olsr protocol.h. Questo le contiene anche

(7)

6.5 Funzionamento di base

le strutture dati che descrivono i vari pacchetti previsti dal protocollo OLSR e che vengono utilizzate da UniK OLSR durante la trasmissione e ettiva.

Una volta inizializzati i vari parametri di con gurazione, UniK OLSR provvede a con gurare le interfacce di rete presenti, acquisendo le informazioni necessarie direttamente dal kernel del sistema Linux nel nodo locale. Per poter comunicare con il kernel di Linux utilizza due diverse tecniche: la prima prevede l'uso della chiamata di sistema ioctl(2) che, in funzione dei parametri che le vengono passati, puo scrivere o leggere delle informazioni che appartengono allo spazio del kernel. I dati che vengono inviati o acquisiti vengono collocati in apposite strutture dati, organizzate in modo consistente rispetto alla richiesta che viene svolta. In alternativa alla chiamata di sistema ioctl(2), e possibile utilizzare il directory /proc/ che fornisce un interfaccia verso il kernel analoga ad un le system, permettendo di leggere o scrivere dati attraverso normali operazioni di I/O.

UniK OLSR deve acquisire delle informazioni sulle interfacce che andra ad utilizzare a tempo d'esecuzione (speci cate nel le di con gurazione).

In particolare deve ottenere l'indirizzo IP associato a ciascuna interfaccia e il corrispondente indirizzo broadcast da utilizzare per l'invio del traco di controllo. UniK OLSR deve individuare quali interfacce sono di tipo wireless e quali no, ad esempio per poter utilizzare di erenti periodi di emissione dei pacchetti di HELLO (infatti, poiche nelle reti cablate normalmente non si ha mobilita, possiamo ridurre l'overhead dovuto al traco di controllo utilizzando un periodo di emissione dei pacchetti di HELLO piu elevato).

Un altro compito fondamentale che richiede l'interazione con il kernel e la modi ca del contenuto della tabella di routing. Tutte queste operazioni vengono svolte attraverso la chiamata di sistema ioctl sopradetta.

Sempre durante l'avvio di UniK OLSR vengono caricati i plugin indicati all'interno del le di con gurazione. Nel prossimo paragrafo approfondiremo il ruolo dei plugin e come poterli integrare con UniK OLSR.

(8)

6.6 Estendere il protocollo: i plugin

Figura 6.3: Esempio uso OLSR per inoltrare in brodcast messaggi applicativi

6.6 Estendere il protocollo: i plugin

Il protocollo OLSR puo essere utilizzato per trasmettere in broadcast messaggi di tipo generico, anche non legati alle attivita svolte dal routing.

Tutti i nodi di un dominio OLSR, anche se non sanno interpretare correttamente un dato messaggio, lo inoltrano in accordo all'algoritmo ottimizzato basato sui Multipoint Relay. Questo permette di utilizzare i pacchetti OLSR come "veicolo" per trasportare informazioni generiche, magari prodotte dalle applicazioni che operano sui vari nodi (come illustrato in gura 6.3). Osserviamo come all'interno di una rete possono coesistere nodi che sanno interpretare il contenuto dei nuovi tipi di messaggio con nodi che invece si limitano a inoltrarli, senza farne alcuna elaborazione.

In particolare UniK OLSR permette il caricamento a tempo di esecuzione di opportune librerie a collegamento dinamico, dette plugin, che possono essere usate per generare ed elaborare nuovi tipi di messaggio. Una libreria a collegamento dinamico (DLL - Dynamic Linked Library) e una porzione di codice eseguibile contenente dati e funzioni. Una DLL viene collegata con il usso principale del programma che la invoca a tempo d'esecuzione, al

(9)

6.6 Estendere il protocollo: i plugin

contrario di quello che succede con le librerie statiche che vengono collegate nel le eseguibile dal linker, immediatamente dopo la compilazione del codice sorgente.

Le librerie DLL consentono un notevole risparmio di memoria. Infatti una data libreria puo essere utilizzata simultaneamente da molti processi, pur essendovene soltanto una copia caricata in memoria. Le librerie DLL sono, in genere, degli insiemi di funzioni condivise da vari processi. Ad esempio molte librerie per la programmazione di interfacce gra che (GUI - Graphical User Interface) sono sviluppate e rese disponibili come DLL. Le librerie DLL esistono per i piu comuni sistemi operativi: nei sistemi Linux hanno estensione .so mentre nei sistemi Windows .dll.

Nel contesto speci co di UniK OLSR le DLL vengono chiamate plugin e consentono di estendere le funzionalita dell'applicazione originale senza alterarne il funzionamento di base. In particolare l'uso dei plugin permette di estendere le funzionalita del routing senza doverne modi care il codice.

Inoltre i plugin possono essere scritti in qualsiasi linguaggio che puo essere compilato come libreria dinamica.

6.6.1 Caricamento plugin

UniK OLSR, durante la fase di analisi del le di con gurazione, determina quali plugin devono essere caricati e il loro percorso nel le system (normalmente le librerie dinamiche si trovano collocate in /usr/lib/ ). I plugin da caricare vengono inseriti in una lista dinamica costituita da elementi aventi la seguente struttura:

struct p l u g i n e n t r y f

char  name ;

plugin param  params ; p l u g i n e n t r y  next ; g

Il campo name indica il nome del le contenente il plugin mentre il campo params punta ad una lista di parametri, letti dal le di con gurazione, che

(10)

6.6 Estendere il protocollo: i plugin

devono essere passati al plugin. Tale lista puo anche essere vuota.

Durante la fase di inizializzazione di UniK OLSR viene invocata la funzione:

int o l s r l o a d p l u g i n s ( void ) ;

All'interno di tale funzione, per ciascun elemento plugin entry della lista, viene invocata una funzione (olsr load dl(...)) che si occupa di caricare correttamente in memoria il plugin corrispondente, ritornando il numero di plugin correttamente caricati.

Tale funzione utilizza l'interfaccia o erta nel le dlfcn.h per caricare ciascuna libreria dinamica. In particolare dispone delle seguenti funzioni (per maggiori dettagli si rimanda alle pagine corrispondenti del manuale di Linux):

void dlopen ( const char filename , int f l a g ) ; char d l e r r o r ( void ) ;

void dlsym ( void handle , const char symbol ) ; int d l c l o s e ( void handle ) ;

Innanzitutto, utilizzando la funzione dlopen(...), si carica in memoria la libreria speci cata dal parametro lename con eventuali opzioni indicate dal parametro ag. La funzione dlopen(...), in caso di corretto caricamento, restituisce un riferimento (handle) alla libreria caricata. UniK OLSR acquisisce, tramite la funzione dlsym(...), dei puntatori a variabili e funzioni interne ai plugin caricati in memoria, cos da potervi accedere direttamente.

In particolare deve acquisire la versione dell'interfaccia verso UniK OLSR utilizzata dal plugin e veri care che sia correttamente supportata. Inoltre deve ottenere i puntatori alle seguenti funzioni interne al plugin:

void r e g i s t e r o l s r d a t a ( struct o l s r p l u g i n d a t a  ) ; int  p l u g i n i o ( int , void  , s i z e t ) ;

Queste due funzioni devono essere presenti all'interno di tutti i plugin utilizzabili da UniK OLSR. La funzione register olsr data(...), implementata all'interno di ciascun plugin ed eseguita da UniK OLSR al caricamento del

(11)

6.6 Estendere il protocollo: i plugin

plugin stesso, svolge tre compiti fondamentali. Innanzitutto deve inizializzare le funzionalita del plugin invocando la funzione:

int o l s r p l u g i n i n i t ( ) ;

Quindi deve rendere disponibili all'interno del plugin diversi puntatori a variabili e funzioni di UniK OLSR, utilizzando la funzione:

int f e t c h o l s r d d a t a ( ) ;

In ne, deve settare gli eventuali socket per la comunicazione inter-processo (IPC) attraverso la funzione:

int p l u g i n i p c i n i t ( ) ;

Naturalmente il corpo di queste funzioni varia da plugin a plugin, a seconda delle funzionalita che implementano. Una volta che UniK OLSR ha lanciato con successo queste funzioni, il plugin e correttamente caricato in memoria e puo svolgere le funzionalita per cui e stato sviluppato.

Osserviamo che un plugin va scritto e compilato in modo di erente rispetto ad una classica applicazione eseguibile. Vediamo come si puo realizzare una libreria dinamica, facendo riferimento all' ambiente GNU/Linux e compilatore GCC 3.x.x.

Innanzitutto nel codice di un plugin non esiste un punto di ingresso unico, analogo al main() di un generico programma C. Infatti non e detto che un plugin abbia un usso interno analogo a quello di un programma tradizionale. Al contrario e necessario scrivere un costruttore e un distruttore. Il costruttore viene invocato automaticamente dalla chiamata dlopen(...) quando il plugin viene caricato in memoria mentre il distruttore viene invocato quando il plugin viene deallocato dalla memoria.

Vediamo il prototipo del costruttore e del distruttore:

void a t t r i b u t e ( ( c o n s t r u c t o r ) ) my init ( void ) ; void a t t r i b u t e ( ( d e s t r u c t o r ) ) my fin i ( void ) ;

Utilizzando il compilatore GCC dobbiamo compilare i le oggetto con l'opzione -fPIC per produrre codice indipendente dalla posizione in memoria (quindi rilocabile dinamicamente).

(12)

6.6 Estendere il protocollo: i plugin

In particolare dobbiamo usare un comando del tipo:

gcc -fPIC -c -o object.o source.c

dove source.c e il le da compilare e object.o e il nome del le oggetto da creare.

Il collegamento dei vari le oggetto viene svolto in questo modo:

gcc -shared -Wl,-soname, mylibrary.so -o mylibrary.so obj1.0 obj2.o dove -shared indica al compilatore che si sta producendo una libreria condivisa mentre -Wl,-soname, mylibrary.so indica il nome interno della libreria.

6.6.2 L'interfaccia dei plugin

Come abbiamo visto la funzione fetch olsrd data(...) permette di acquisire dei puntatori a variabili e funzioni interne a UniK OLSR. Tramite un plugin, infatti, e possibile accedere alle funzionalita o erte dai vari moduli di UniK OLSR, come illustrato in gura 6.4.

Anche l'interazione tra plugin e UniK OLSR funzioni in modo corretto, occorre stabilire un'interfaccia espandibile che ssi le regole della comunicazione.

Per poter acquisire dal plugin puntatori a variabili e funzioni di UniK OLSR dobbiamo usare la seguente funzione:

int o l s r p l u g i n i o ( int cmd , void data , s i z e t s i z e ) ; Questa funzione fa parte del codice di UniK OLSR e risulta accessibile al plugin in quanto, in fase di caricamento, e stato inizializzato un puntatore alla funzione stessa. Il primo parametro che viene passato alla funzione sopra indicata e un intero che speci ca quale funzione o variabile vogliamo acquisire. Il secondo parametro e un puntatore ad un'area di memoria opportunamente allocata per contenere l'informazione e il terzo parametro indica la dimensione in byte di tale area. La funzione olsr plugin io(...)

e implementata attraverso uno switch che gestisce nei suoi case i possibili

(13)

6.6 Estendere il protocollo: i plugin

Figura 6.4: Interazioni possibili tra un plugin e i vari moduli che costituiscono UniK OLSR

comandi passati. Ad esempio per ottenere un puntatore alla funzione UniK OLSR utilizzata per registrare degli eventi nello schedulatore interno (ovvero la funzione olsr register scheduler event(...)) possiamo passare il comando GETF OLSR REGISTER SCHEDULER EVENT alla funzione olsr plugin io(...) ottenendo cos il puntatore desiderato. Ecco, in particolare, come e fatto il codice che gestisce uno di questi comandi all'interno di olsr plugin io(...):

case (GETF OLSR REGISTER SCHEDULER EVENT ) : ptr = &o l s r r e g i s t e r s c h e d u l e r e v e n t ; memcpy( data ,& ptr , s i z e ) ;

break ;

Tutti i possibili comandi si trovano dichiarati in olsr plugin io.h. Quelli che iniziano con GETF sono comandi che permettono di acquisire dei puntatori a funzioni mentre quelli che iniziano con GETD permettono di ottenere dei

(14)

6.6 Estendere il protocollo: i plugin

puntatori a variabili.

6.6.3 Un esempio di plugin: power-status

Il plugin power-status, distribuito insieme a UniK OLSR come esempio, permette di distribuire in una rete MANET delle informazioni sullo stato dell'alimentazione elettrica dei vari nodi che la costituiscono, appoggiandosi al protocollo OLSR. Inoltre questo tipo di informazione e resa disponibile all'utente e agli altri processi attraverso tecniche di comunicazione inter- processo (IPC) utilizzando delle connessioni TCP. In particolare il plugin determina l'invio periodico in rete di un nuovo tipo di messaggio contenente le seguenti informazioni: tipo di alimentazione del nodo (batteria o rete elettrica), durata stimata della batteria (se presente), percentuale di energia rimasta nella batteria (se presente). Naturalmente occorre registrare presso UniK OLSR una nuova funzione di parsing in grado di analizzare i nuovi tipi di messaggio, aggiornando il contenuto delle strutture dati interne che tengono traccia dello stato energetico dei vari nodi della MANET. Attraverso questo scambio di messaggi, tutti i nodi della MANET che implementano il plugin dispongono di una visione aggiornata dello stato di alimentazione di tutti gli altri. I nodi che non supportano questo plugin si limiteranno ad inoltrare il messaggio power-status in accordo all'algoritmo ottimizzato del protocollo OLSR.

Le informazioni sullo stato energetico del nodo vengono acquisite dallo pseudo le system /proc e incapsulate in un opportuno messaggio OLSR.

Inoltre viene registrata, presso lo schedulatore interno a UniK OLSR, una funzione per la generazione periodica di questo messaggio.

Per poter accedere alle informazioni memorizzate, un'applicazione si puo collegare al plugin aprendo una connessione TCP locale. Infatti all'interno del plugin viene implementato un socket server che rimane in attesa di richieste di connessione da applicazioni locali al nodo. Per maggiori dettagli vedere la documentazione in [UNI].

Nel prossimo capitolo descriveremo in dettaglio il plugin che e stato

(15)

6.6 Estendere il protocollo: i plugin

sviluppato nell'ambito di questa tesi per poter realizzare delle interazioni di tipo cross-layer con il livello middleware e successivamente mostreremo i risultati sperimentali ottenuti in un ambiente MANET reale.

(16)

6.6 Estendere il protocollo: i plugin

Riferimenti

Documenti correlati

Per trasferire un file usando il protocollo ftp occorre avere a disposizione un'applicazione ftp chiamata client ftp (ce ne sono diverse anche di tipo freeware) che viene

Analogamente ogni arco `e incidente ad almeno un nodo di una copertura e quindi nodi del complementare di una copertura non possono essere adiacenti, e allora formano un

% Fornisce in uscita l’azione di controllo a norma minima che porta il sistema. % dallo stato iniziale X0 allo stato finale Xf, in

Le centrali elettriche sono degli stabilimenti nei quali si effettua la CONVERSIONE di energia da una forma non elettrica ad g elettrica.. Esse si differenziano in base al tipo

• Un programma Java puo accedere a files conte- nenti suoni, immagini, testi ed altri programmi Java ovunque situati sulla rete WEB, mediante dei riferimenti basati su indirizzi

Guida all’utilizzo del Plugin MzSTools per la microzonazione sismica.. Schema della Banca dati delle Indagini.

Scrivi tu ora un testo di un problema di RIPARTIZIONE nello spazio che trovi qui sotto..

CISQ – Politecnico di Bari - Corso di formazione per RSPP – Modulo 6: Esempio di un insieme PED (ing. Boenzi).. Bari, 3 febbraio