Guida al simulatore di rete ns-3. Capitolo 5

Guida al simulatore di rete ns-3. Capitolo 5
capitoli 1, 2
capitolo 3
capitolo 4

5 Configurazione
5.1 Utilizzo del modulo di registrazione
5.1.1 Panoramica della registrazione
5.1.2 Abilitazione della registrazione
5.1.3 Aggiunta della registrazione al tuo codice
5.2 Utilizzo degli argomenti della riga di comando
5.2.1 Sovrascrittura dei valori degli attributi predefiniti
5.2.2 Catturare i tuoi comandi
5.3 Utilizzo del sistema di tracciamento
5.3.1 Tracciamento ASCII
Parsing del tracciamento ASCII
5.3.2 Tracciamento PCAP

Capitolo 5

Impostazione

5.1 Utilizzo del modulo di registrazione

Abbiamo già esaminato brevemente il modulo di registrazione ns-3, rivedendo lo script first.cc. In questo capitolo, ci concentreremo più attentamente sulle potenziali applicazioni del sottosistema di registrazione.

5.1.1 Panoramica della registrazione

Molti grandi sistemi supportano qualche mezzo di registrazione dei messaggi e ns-3 non fa eccezione. In alcuni casi, nella «console operatore» (che di solito è stderr nei sistemi basati su Unix) vengono registrati solo i messaggi di errore. In altri sistemi, possono essere visualizzati messaggi di avviso e anche informazioni più dettagliate. In alcuni casi, i mezzi di registrazione vengono utilizzati per visualizzare messaggi di debug, che possono rapidamente «anestetizzare» l'output.

Il logging utilizzato in ns-3 presume che tutti questi livelli di informatività siano utili, e forniamo un approccio selettivo e multilivello alla registrazione dei messaggi. Il logging può essere completamente disattivato, attivato per singoli componenti o a livello globale. Questo è reso possibile da livelli di informatività configurabili. Il modulo di logging di ns-3 fornisce un modo relativamente semplice per ottenere informazioni utili dalla tua simulazione.

È importante comprendere che forniamo un meccanismo di uso generale — la tracciatura — per estrarre dati dai tuoi modelli, che dovrebbe essere la modalità preferita per l'output durante la modellazione (per ulteriori dettagli sul nostro sistema di tracciatura, vedere la sezione 5.3 del tutorial). Il logging dovrebbe essere il metodo preferito per ottenere informazioni di debug, avvisi, messaggi di errore o per un rapido output di messaggi dai tuoi script o modelli in qualsiasi momento.

Attualmente il sistema definisce sette livelli (tipi) di messaggi di log in ordine crescente di informatività.

  • LOG_ERROR — registrazione dei messaggi di errore (macro correlata: NS_LOG_ERROR);
  • LOG_WARN — registrazione dei messaggi di avviso (macro correlata: NS_LOG_WARN);
  • LOG_DEBUG — registrazione di messaggi di debug relativamente rari (macro correlata: NS_LOG_DEBUG);
  • LOG_INFO — registrazione di messaggi informativi sull'andamento del programma (macro correlata: NS_LOG_INFO);
  • LOG_FUNCTION — registrazione dei messaggi che descrivono ogni funzione chiamata (due macro correlate: NS_LOG_FUNCTION, utilizzata per le funzioni membro, e NS_LOG_FUNCTION_NOARGS, utilizzata per le funzioni statiche);
  • LOG_LOGIC — registrazione dei messaggi che descrivono il flusso logico all'interno della funzione (macro correlata: NS_LOG_LOGIC);
  • LOG_ALL — registrazione di tutto quanto sopra menzionato (nessuna macro correlata).
    Per ogni tipo (LOG_TYPE) esiste anche un tipo LOG_LEVEL_TYPE che, se utilizzato, consente di registrare, oltre al proprio livello, tutti i livelli superiori. (Di conseguenza, LOG_ERROR e LOG_LEVEL_ERROR, così come LOG_ALL e LOG_LEVEL_ALL sono funzionalmente equivalenti.) Ad esempio, attivare LOG_INFO permetterà solo messaggi forniti dal macro NS_LOG_INFO; attivando LOG_LEVEL_INFO verranno inclusi anche i messaggi forniti dai macro NS_LOG_DEBUG, NS_LOG_WARN e NS_LOG_ERROR.

Offriamo anche un macro di registrazione incondizionata, che viene visualizzato sempre, indipendentemente dal livello di registrazione o dal componente selezionato.

  • NS_LOG_UNCOND — registrazione incondizionata del messaggio associato (senza livello di log associato).

Ogni livello può essere richiesto singolarmente o cumulativamente. La registrazione può essere configurata tramite la variabile d'ambiente sh-NS_LOG o registrando una chiamata a una funzione di sistema. Come mostrato in precedenza, il sistema di registrazione ha documentazione Doxygen e questo è il momento migliore per esaminarla, se non lo hai già fatto.

Ora che hai esaminato la documentazione in dettaglio, utilizziamo queste conoscenze per estrarre alcune informazioni interessanti dall'esempio di script scratch/myfirst.cc, che hai già compilato.

5.1.2 Abilitazione della registrazione

Utilizziamo la variabile d'ambiente NS_LOG per avviare ulteriori registri, ma prima, per orientarci, esegui l'ultimo script come hai fatto in precedenza,

$ ./waf --run scratch/myfirst

Dovresti vedere il già familiare output del primo programma di esempio ns-3

$ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' 'build'
finished successfully (0.413s)
Sent 1024 bytes to 10.1.1.2
Received 1024 bytes from 10.1.1.1
Received 1024 bytes from 10.1.1.2

Si scopre che i messaggi "inviati" e "ricevuti" che vedi sopra sono in realtà messaggi registrati da UdpEchoClientApplication e UdpEchoServerApplication. Ad esempio, possiamo chiedere all'applicazione client di stampare informazioni aggiuntive impostando il suo livello di registrazione tramite la variabile d'ambiente NS_LOG.

A partire da ora, presumo che tu stia utilizzando una shell simile a sh, che utilizza la sintassi "VARIABLE = value". Se stai usando una shell simile a csh, dovrai convertire i miei esempi nella sintassi "setenv variable value" richiesta da tali shell.

Attualmente, l'applicazione UDP echo client risponde alla seguente riga di codice in scratch/myfirst.cc,

LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);

Questo attiva il livello di log LOG_LEVEL_INFO. Quando passiamo il flag del livello di log, in realtà attiviamo quel livello e tutti i livelli inferiori. In questo caso, abbiamo attivato NS_LOG_INFO, NS_LOG_DEBUG, NS_LOG_WARN e NS_LOG_ERROR. Possiamo aumentare il livello di log e ottenere più informazioni, senza modificare lo script e senza ricompilare, impostando la variabile di ambiente NS_LOG nel seguente modo:

$ export NS_LOG=UdpEchoClientApplication=level_all

Così impostiamo il seguente valore della variabile NS_LOG nella shell sh,

UdpEchoClientApplication=level_all

La parte sinistra dell'assegnazione è il nome del componente registrato che vogliamo configurare, mentre la parte destra è il flag che vogliamo applicare. In questo caso, stiamo per abilitare tutti i livelli di debug nell'applicazione. Se esegui lo script con NS_LOG impostato in questo modo, il sistema di logging ns‑3 recepirà le modifiche e dovresti vedere il seguente output:

Waf: Entrando nella directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
Waf: Uscendo dalla directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
'build' completato con successo (0.404s)
UdpEchoClientApplication:UdpEchoClient()
UdpEchoClientApplication:SetDataSize(1024)
UdpEchoClientApplication:StartApplication()
UdpEchoClientApplication:ScheduleTransmit()
UdpEchoClientApplication:Send()
Inviati 1024 bytes a 10.1.1.2
Ricevuti 1024 bytes da 10.1.1.1
UdpEchoClientApplication:HandleRead(0x6241e0, 0x624a20)
Ricevuti 1024 bytes da 10.1.1.2
UdpEchoClientApplication:StopApplication()
UdpEchoClientApplication:DoDispose()
UdpEchoClientApplication:~UdpEchoClient()

Le informazioni di debug aggiuntive fornite dall'applicazione ora corrispondono al livello NS_LOG_FUNCTION. Questo mostra ogni chiamata di funzione durante l'esecuzione dello script. In generale, è preferibile utilizzare (almeno) nelle funzioni-metodiNS_LOG_FUNCTION (this). Usa NS_LOG_FUNCTION_NOARGS ()
solo nelle funzioni statiche. Tuttavia, si noti che nel sistema ns-3 non ci sono requisiti per mantenere alcuna funzionalità di registrazione. La decisione su quante informazioni registrare rimane a discrezione dello sviluppatore del modello. Nel caso delle applicazioni echo, è disponibile un'ampia quantità di output per la registrazione.

Ora puoi visualizzare il registro delle chiamate di funzione effettuate dall'applicazione. Se guardi attentamente, noterai i due punti tra la riga UdpEchoClientApplication e il nome del metodo, nel punto in cui ti aspetteresti di vedere l'operatore di ambito C++ (::). Questo è stato fatto intenzionalmente.

In realtà, questo non è il nome della classe, ma il nome del componente di registrazione. Quando c'è una corrispondenza tra il file sorgente e la classe, di solito è il nome della classe, ma devi comprendere che in realtà non è il nome della classe, e ci sono un solo due punti invece di due. Questo è un modo per aiutarti, in modo abbastanza sottile, a separare concettualmente il nome del componente di registrazione dal nome della classe.

Tuttavia, in alcuni casi può essere difficile determinare quale metodo stia effettivamente generando il messaggio di log. Se guardi il testo sopra, ti verrà da chiederti da dove provenga la stringa «Ricevuti 1024 byte da 10.1.1.2». Puoi risolvere questo problema impostando il livello prefix_func nella variabile d'ambiente NS_LOG. Prova a fare quanto segue,

$ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func'

Nota che le virgolette sono necessarie, poiché la barra verticale che usiamo per indicare l'operazione OR è anche un connettore di pipeline Unix. Ora, se esegui lo script, vedrai che il sistema di logging garantisce che ogni messaggio di questo log abbia un prefisso con il nome del componente.

Waf: Entrando nella directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
Waf: Uscendo dalla directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' completato con successo (0.417s)
UdpEchoClientApplication:UdpEchoClient()
UdpEchoClientApplication:SetDataSize(1024)
UdpEchoClientApplication:StartApplication()
UdpEchoClientApplication:ScheduleTransmit()
UdpEchoClientApplication:Send()
UdpEchoClientApplication:Send(): Inviati 1024 byte a 10.1.1.2
Ricevuti 1024 byte da 10.1.1.1
UdpEchoClientApplication:HandleRead(0x6241e0, 0x624a20)
UdpEchoClientApplication:HandleRead(): Ricevuti 1024 byte da 10.1.1.2
UdpEchoClientApplication:StopApplication()
UdpEchoClientApplication:DoDispose()
UdpEchoClientApplication:~UdpEchoClient()

Ora puoi vedere che tutti i messaggi in arrivo dall'applicazione UDP echo client sono identificati come tali. Il messaggio «Ricevuti 1024 byte da 10.1.1.2» è ora chiaramente identificato come proveniente dall'applicazione echo client. Il messaggio rimanente dovrebbe provenire dall'applicazione UDP echo server. Possiamo attivare questo componente inserendo un elenco di componenti separati da due punti nella variabile d'ambiente NS_LOG.

$ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func:
               UdpEchoServerApplication=level_all|prefix_func'

Attenzione: nell'esempio di testo sopra, dovrai rimuovere il carattere di nuova linea dopo i due punti (:), poiché è utilizzato per formattare il documento. Ora, se esegui lo script, vedrai tutti i messaggi del registro delle applicazioni di echo client e server. Può essere molto utile durante il debug.

Waf: Inizio directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
Waf: Uscita dalla directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
'build' completato con successo (0.406s)
UdpEchoServerApplication:UdpEchoServer()
UdpEchoClientApplication:UdpEchoClient()
UdpEchoClientApplication:SetDataSize(1024)
UdpEchoServerApplication:StartApplication()
UdpEchoClientApplication:StartApplication()
UdpEchoClientApplication:ScheduleTransmit()
UdpEchoClientApplication:Send()
UdpEchoClientApplication:Send(): Inviati 1024 byte a 10.1.1.2
UdpEchoServerApplication:HandleRead(): Ricevuti 1024 byte da 10.1.1.1
UdpEchoServerApplication:HandleRead(): Risposta pacchetto
UdpEchoClientApplication:HandleRead(0x624920, 0x625160)
UdpEchoClientApplication:HandleRead(): Ricevuti 1024 byte da 10.1.1.2
UdpEchoServerApplication:StopApplication()
UdpEchoClientApplication:StopApplication()
UdpEchoClientApplication:DoDispose()
UdpEchoServerApplication:DoDispose()
UdpEchoClientApplication:~UdpEchoClient()
UdpEchoServerApplication:~UdpEchoServer()

È anche utile avere la possibilità di vedere il tempo di simulazione in cui è stato creato il messaggio di registro. Puoi farlo aggiungendo un bit di PRECEDENZA. prefix_time:

$ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func|prefix_time: UdpEchoServerApplication=level_all|prefix_func|prefix_time'

Dovrai nuovamente rimuovere il simbolo di nuova linea sopra. Se ora esegui lo script, dovresti vedere il seguente output:

Waf: Entrando nella directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
Waf: Uscendo dalla directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
'build' completato con successo (0.418s)
0s UdpEchoServerApplication:UdpEchoServer()
0s UdpEchoClientApplication:UdpEchoClient()
0s UdpEchoClientApplication:SetDataSize(1024)
1s UdpEchoServerApplication:StartApplication()
2s UdpEchoClientApplication:StartApplication()
2s UdpEchoClientApplication:ScheduleTransmit()
2s UdpEchoClientApplication:Send()
2s UdpEchoClientApplication:Send(): Inviati 1024 bytes a 10.1.1.2
2.00369s UdpEchoServerApplication:HandleRead(): Ricevuti 1024 bytes da 10.1.1.1
2.00369s UdpEchoServerApplication:HandleRead(): Rispondo al pacchetto
2.00737s UdpEchoClientApplication:HandleRead(0x624290, 0x624ad0)
2.00737s UdpEchoClientApplication:HandleRead(): Ricevuti 1024 bytes da 10.1.1.2
10s UdpEchoServerApplication:StopApplication()
10s UdpEchoClientApplication:StopApplication()
UdpEchoClientApplication:DoDispose()
UdpEchoServerApplication:DoDispose()
UdpEchoClientApplication:~UdpEchoClient()
UdpEchoServerApplication:~UdpEchoServer()

Nota che il costruttore per UdpEchoServer è stato chiamato durante la simulazione a 0 secondi. Questo avviene in realtà prima dell'inizio della simulazione, ma questo tempo viene visualizzato come zero secondi. Lo stesso vale per il messaggio del costruttore UdpEchoClient.

Waf: Entrando nella directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
Waf: Uscendo dalla directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
'build' completato con successo (0.418s)
0s UdpEchoServerApplication:UdpEchoServer()
0s UdpEchoClientApplication:UdpEchoClient()
0s UdpEchoClientApplication:SetDataSize(1024)
1s UdpEchoServerApplication:StartApplication()
2s UdpEchoClientApplication:StartApplication()
2s UdpEchoClientApplication:ScheduleTransmit()
2s UdpEchoClientApplication:Send()
2s UdpEchoClientApplication:Send(): Inviati 1024 bytes a 10.1.1.2
2.00369s UdpEchoServerApplication:HandleRead(): Ricevuti 1024 bytes da 10.1.1.1
2.00369s UdpEchoServerApplication:HandleRead(): Rispondo al pacchetto
2.00737s UdpEchoClientApplication:HandleRead(0x624290, 0x624ad0)
2.00737s UdpEchoClientApplication:HandleRead(): Ricevuti 1024 bytes da 10.1.1.2
10s UdpEchoServerApplication:StopApplication()
10s UdpEchoClientApplication:StopApplication()
UdpEchoClientApplication:DoDispose()
UdpEchoServerApplication:DoDispose()
UdpEchoClientApplication:~UdpEchoClient()
UdpEchoServerApplication:~UdpEchoServer()

Ricordiamo che lo script scratch/first.cc ho avviato l'applicazione del server echo un secondo prima dell'inizio della simulazione. Ora puoi vedere che il metodo StartApplication del server viene effettivamente chiamato nel primo secondo. Puoi anche notare che il client echo si avvia nel secondo secondo della simulazione, come abbiamo richiesto nello script.

Ora puoi seguire l'andamento della simulazione tramite la chiamata ScheduleTransmit nel client, che chiama il callback Send HandleRead nell'applicazione del server echo. Nota che il tempo scaduto per inviare un pacchetto attraverso il collegamento a due punti è di 3,69 millisecondi. È evidente che il server echo registra un messaggio che indica di aver risposto al pacchetto e, dopo un ritardo del canale, puoi vedere che il client echo riceve il pacchetto echo nel suo metodo HandleRead.

In questa simulazione accade molto, invisibile a te. Ma puoi facilmente tracciare l'intero processo attivando il logging di tutti i componenti nel sistema. Prova a impostare il seguente valore nella variabile NS_LOG,

$ export 'NS_LOG=*=level_all|prefix_func|prefix_time'

L'asterisco sopra funge da wildcard per il componente di registrazione. Questo attiverà tutte le registrazioni in tutti i componenti utilizzati nella simulazione. Non riprodurrò l'output qui (al momento della scrittura, produce 1265 righe di output per un singolo pacchetto di echo), ma puoi reindirizzare queste informazioni in un file e visualizzarlo nel tuo editor preferito.

$ ./waf --run scratch/myfirst > log.out 2>&1

Personalmente utilizzo questa versione estremamente dettagliata del log quando ho un problema e non ho idea di dove le cose siano andate male. Posso seguire piuttosto facilmente l'esecuzione del codice senza impostare punti di interruzione e passo-passo nel debugger. Posso semplicemente modificare l'output nel mio editor preferito e cercare ciò che mi aspetto, vedendo cosa succede quando qualcosa va storto. Quando ho un'idea generale di cosa non vada, passo al debugger per un'analisi più approfondita del problema. Questo tipo di output può essere particolarmente utile quando il tuo script comporta qualcosa di completamente inaspettato. Se utilizzi solo il debugger, potresti perdere completamente una svolta inaspettata. La registrazione rende tali svolte evidenti.

5.1.3 Aggiunta della registrazione al tuo codice

Puoi aggiungere nuove voci alle tue simulazioni effettuando chiamate al componente log da diversi macro. Facciamolo nello script myfirst.cc, che abbiamo nella directory "pulita". Ricordiamo che abbiamo definito in questo script il componente di registrazione:

NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");

Sapevi che puoi abilitare la registrazione di tutti i messaggi di questo componente impostando la variabile ambiente NS_LOG a diversi livelli? Procediamo e aggiungiamo alcune voci allo script. Il macro utilizzato per registrare messaggi a livello informativo è NS_LOG_INFO. Aggiungiamo un messaggio (proprio prima di creare i nodi) che ti informa che lo script è nella fase di creazione della topologia ("Creating Topology"). Questo avviene nel seguente frammento di codice,
Apri scratch/myfirst.cc nel tuo editor preferito e aggiungi la riga,
NS_LOG_INFO ("Creating Topology");
subito prima delle righe,

NodeContainer nodes;
nodes.Create(2);

Ora compila lo script utilizzando waf, e pulisci la variabile NS_LOG per disabilitare il flusso di registrazione che abbiamo attivato in precedenza:

$ ./waf
$ export NS_LOG=
Adesso, se esegui lo script,
$ ./waf --run scratch/myfirst

non vedrai il nuovo messaggio, poiché il componente di registrazione associato (FirstScriptExample) non è stato attivato. Per vedere il tuo messaggio, devi abilitare il componente di registrazione FirstScriptExample con un livello non inferiore a NS_LOG_INFO. Se vuoi vedere solo questo livello specifico di registrazione, puoi attivarlo così,

$ export NS_LOG=FirstScriptExample=info

Se esegui ora lo script, vedrai un nuovo messaggio "Creating Topology".

Waf: Entrando nella directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
Waf: Uscendo dalla directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' completato con successo (0.404s)
Creating Topology
Inviati 1024 byte a 10.1.1.2
Ricevuti 1024 byte da 10.1.1.1
Ricevuti 1024 byte da 10.1.1.2

5.2 Utilizzo degli argomenti della riga di comando

5.2.1 Sovrascrittura dei valori degli attributi predefiniti

Un altro modo per modificare il comportamento degli script ns‑3 senza modificare e ricompilare è utilizzare gli argomenti della riga di comando. Forniamo un meccanismo per analizzare gli argomenti della riga di comando e impostare automaticamente variabili locali e globali basate sui risultati.

Il primo passo nell'utilizzo del sistema degli argomenti della riga di comando è dichiarare l'analizzatore della riga di comando. È abbastanza semplice da fare (nella tua funzione principale), come nel seguente codice:

int
main (int argc, char *argv[])
{
...
CommandLine cmd;
cmd.Parse (argc, argv);
...
}

Questo semplice frammento di due righe è in realtà molto utile di per sé. Apre la porta a variabili globali ns‑3 e al sistema di attributi. Aggiungiamo due righe di codice all'inizio della funzione principale dello script. scratch/myfirst.cc. Двигаясь дальше, компилируем сценарий и запускаем его, при запуске делаем запрос справки следующим образом,

$ ./waf --run "scratch/myfirst --PrintHelp"

Эта команда попросит Waf запустить скрипт scratch/myfirst и передать ему аргумент командной строки —PrintHelp. Кавычки необходимы, чтобы показать, для какой программы предназначен аргумент. Парсер командной строки обнаружит аргумент —PrintHelp и выведет ответ,

Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' finished successfully (0.413s)
TcpL4Protocol:TcpStateMachine()
CommandLine:HandleArgument(): Handle arg name=PrintHelp value=
--PrintHelp: Print this help message.
--PrintGroups: Print the list of groups.
--PrintTypeIds: Print all TypeIds.
--PrintGroup=[group]: Print all TypeIds of group.
--PrintAttributes=[typeid]: Print all attributes of typeid.
--PrintGlobals: Print the list of globals.

Теперь рассмотрим опцию —PrintAttributes. Мы уже упоминали систему атрибутов ns‑3, при изучении скрипта first.cc. Мы видели следующие строки кода,

PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

и говорили, что DataRate на самом деле является атрибутом PointToPointNetDevice. Давайте применим синтаксический анализатор аргументов командной строки для просмотра атрибутов PointToPointNetDevice. La lista di aiuto indica che dobbiamo fornire TypeId. Questo è il nome della classe a cui appartengono gli attributi di interesse. In questo caso sarà ns3::PointToPointNetDevice. Procediamo, inserisci

$ ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointNetDevice"

Il sistema stamperà tutti gli attributi di questo tipo di dispositivo di rete. Vedrai che tra gli attributi ci sono

--ns3::PointToPointNetDevice::DataRate=[32768bps]:
La velocità di trasmissione dati predefinita per i collegamenti punto-punto

Questo è il valore predefinito che sarà utilizzato dal sistema quando viene creato l'oggetto PointToPointNetDevice. Sostituiremo questo valore predefinito con il parametro Attribute in PointToPointHelper sopra. Utilizziamo i valori predefiniti per i dispositivi e i canali punto-punto. Per fare ciò, rimuoviamo le chiamate SetDeviceAttribute e SetChannelAttribute di myfirst.cc, che abbiamo nella directory pulita.

Il tuo script ora deve semplicemente dichiarare PointToPointHelper e non eseguire alcuna operazione di impostazione, come mostrato nell'esempio seguente,

...
NodeContainer nodes;
nodes.Create (2);
PointToPointHelper pointToPoint;
NetDeviceContainer devices;
devices = pointToPoint.Install (nodes);
...

Procedi e crea un nuovo script con Waf (./waf) e torniamo indietro per includere un po' di registrazione dall'applicazione server UDP echo e includiamo un prefisso temporale.

$ export 'NS_LOG=UdpEchoServerApplication=level_all|prefix_time'

Se esegui lo script, dovresti vedere il seguente output:

Waf: In entrare nella directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
Waf: Uscita dalla directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
'build' completato con successo (0.405s)
0s UdpEchoServerApplication:UdpEchoServer()
1s UdpEchoServerApplication:StartApplication()
Inviati 1024 byte a 10.1.1.2
2.25732s Ricevuti 1024 byte da 10.1.1.1
2.25732s Rispondendo al pacchetto
Ricevuti 1024 byte da 10.1.1.2
10s UdpEchoServerApplication:StopApplication()
UdpEchoServerApplication:DoDispose()
UdpEchoServerApplication:~UdpEchoServer()

Ricordiamo che l'ultima volta che abbiamo esaminato il tempo di simulazione, il momento in cui il pacchetto è stato ricevuto dall'echo-server è stato a 2,00369 secondi.

2.00369s UdpEchoServerApplication:HandleRead(): Ricevuti 1024 byte da 10.1.1.1

Ora riceve il pacchetto a 2.25732 secondi. Questo perché abbiamo semplicemente ripristinato la velocità di trasmissione del PointToPointNetDevice da cinque megabit al secondo al valore predefinito, che è di 32768 bit al secondo. Se avessimo inserito un nuovo DataRate tramite la riga di comando, potremmo riaccelerare la nostra simulazione. Faremo ciò nel modo seguente, secondo la formula implicita nell'elemento di aiuto:

$ ./waf --run "scratch/myfirst --ns3::PointToPointNetDevice::DataRate=5Mbps"

Di conseguenza, il valore dell'attributo DataRate tornerà predefinito a cinque megabit al secondo. Sei sorpreso dal risultato? Si scopre che per ripristinare il comportamento originale dello script, dobbiamo impostare anche il ritardo del canale corrispondente alla velocità della luce. Possiamo chiedere al sistema di comando di stampare gli attributi del canale, proprio come abbiamo fatto per il dispositivo di rete:

$ ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointChannel"

Scopriremo che l'attributo di ritardo del canale è impostato nel seguente modo:

--ns3::PointToPointChannel::Delay=[0ns]:
Ritardo di trasmissione attraverso il canale

Poi possiamo impostare entrambi questi valori predefiniti tramite il sistema di comando,

$ ./waf --run "scratch/myfirst
--ns3::PointToPointNetDevice::DataRate=5Mbps
--ns3::PointToPointChannel::Delay=2ms"

in questo caso ripristiniamo il tempo che avevamo quando abbiamo impostato esplicitamente DataRate e Delay nello script:

Waf: Entrando nella directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
Waf: Uscendo dalla directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' completato con successo (0.417s)
0s UdpEchoServerApplication:UdpEchoServer()
1s UdpEchoServerApplication:StartApplication()
Inviati 1024 byte a 10.1.1.2
2.00369s Ricevuti 1024 byte da 10.1.1.1
2.00369s Ripetizione pacchetto
Ricevuti 1024 byte da 10.1.1.2
10s UdpEchoServerApplication:StopApplication()
UdpEchoServerApplication:DoDispose()
UdpEchoServerApplication:~UdpEchoServer()

Si prega di notare che il pacchetto è stato nuovamente ricevuto dal server dopo 2,00369 secondi. Potremmo effettivamente impostare in questo modo qualsiasi attributo utilizzato nello script. In particolare, potremmo impostare valori degli attributi MaxPackets diversi da uno. UdpEchoClient.

Come lo usereste? Provate. Ricordate che dovete commentare il punto in cui ridefiniamo il valore dell'attributo predefinito e impostare esplicitamente MaxPackets nello script. Dovrete poi ricompilare lo script. Potete anche ottenere assistenza sulla sintassi per impostare un nuovo valore dell'attributo predefinito tramite la riga di comando. Una volta compreso questo, sarete in grado di gestire il numero di pacchetti visualizzati nella riga di comando. Poiché siamo persone diligenti, la nostra riga di comando dovrebbe apparire circa così:

$ ./waf --run "scratch/myfirst
--ns3::PointToPointNetDevice::DataRate=5Mbps
--ns3::PointToPointChannel::Delay=2ms
--ns3::UdpEchoClient::MaxPackets=2"

Una domanda naturale che sorge qui è come conoscere l'esistenza di tutti questi attributi. Ancora una volta, il sistema della riga di comando ha una funzione di aiuto a riguardo. Se richiediamo assistenza dalla riga di comando, dovremmo vedere:

$ ./waf --run "scratch/myfirst --PrintHelp"
myfirst [Argomenti del Programma] [Argomenti Generali]
Argomenti Generali:
--PrintGlobals: Stampa l'elenco delle variabili globali.
--PrintGroups: Stampa l'elenco dei gruppi.
--PrintGroup=[gruppo]: Stampa tutti i TypeId del gruppo.
--PrintTypeIds: Stampa tutti i TypeId.
--PrintAttributes=[typeid]: Stampa tutti gli attributi di typeid.
--PrintHelp: Stampa questo messaggio di aiuto.

Se scegli l'argomento "PrintGroups", dovresti vedere un elenco di tutti i gruppi registrati. TypeId. I nomi dei gruppi corrispondono ai nomi dei moduli nella directory sorgente (sebbene con la lettera maiuscola). Stampa tutte le informazioni insieme sarà troppo ingombrante, quindi è disponibile un filtro aggiuntivo per stampare le informazioni per gruppi. Quindi, focalizzandosi nuovamente sul modulo "point-to-point":

./waf --run "scratch/myfirst --PrintGroup=PointToPoint"
TypeIds nel gruppo PointToPoint:
ns3::PointToPointChannel
ns3::PointToPointNetDevice
ns3::PointToPointRemoteChannel
ns3::PppHeader

Qui puoi trovare i nomi disponibili di TypeId per la ricerca di attributi, ad esempio in
--PrintAttributes = ns3::PointToPointChannel, come mostrato sopra.

Un altro modo per conoscere gli attributi è tramite Doxygen ns-3. Lì troverai una pagina che elenca tutti gli attributi registrati nel simulatore.

5.2.2 Catturare i tuoi comandi

Puoi anche aggiungere i tuoi hook tramite il sistema della riga di comando. Questo è abbastanza semplice grazie al metodo del parser della linea di comando. AddValue.
Utilizziamo questa opportunità per specificare il numero di pacchetti che devono essere visualizzati in un modo completamente diverso. Aggiungiamo una variabile locale chiamata nPackets nella funzione main. La imposteremo su uno per corrispondere al nostro comportamento predefinito precedente. Per consentire al parser della linea di comando di modificare questo valore, dobbiamo acquisire questo valore nel parser. Lo facciamo aggiungendo una chiamata AddValue. Vai a modificare lo script scratch/myfirst.cc in modo da iniziare con il seguente codice:

int
main (int argc, char *argv[])
{
uint32_t nPackets = 1;
CommandLine cmd;
cmd.AddValue("nPackets", "Numero di pacchetti da echo", nPackets);
cmd.Parse (argc, argv);
...

Scorri verso il basso fino al punto nello script dove impostiamo l'attributo MaxPackets e modificane il valore per utilizzare la variabile nPackets invece della costante 1, come mostrato di seguito.

echoClient.SetAttribute ("MaxPackets", UintegerValue (nPackets));

Ora, se esegui lo script e inserisci l'argomento —PrintHelp, dovresti vedere un nuovo argomento utente elencato nel display dell'aiuto. Inserire,

$ ./waf --run "scratch/myfirst --PrintHelp"
Waf: Entrando nella directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
Waf: Uscendo dalla directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
'build' completato con successo (0,403s)
--PrintHelp: Stampa questo messaggio di aiuto.
--PrintGroups: Stampa l'elenco dei gruppi.
--PrintTypeIds: Stampa tutti gli TypeIds.
--PrintGroup=[group]: Stampa tutti gli TypeIds del gruppo.
--PrintAttributes=[typeid]: Stampa tutti gli attributi di typeid.
--PrintGlobals: Stampa l'elenco delle variabili globali.
Argomenti utente:
--nPackets: Numero di pacchetti da eco

Se vuoi modificare il numero di pacchetti trasmessi, puoi farlo impostando l'argomento -nPackets nella riga di comando,

$ ./waf --run "scratch/myfirst --nPackets=2"

Ora dovresti vedere

Waf: Entrando nella directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
Waf: Uscendo dalla directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
'build' completato con successo (0,404s)
0s UdpEchoServerApplication:UdpEchoServer()
1s UdpEchoServerApplication:StartApplication()
Inviati 1024 byte a 10.1.1.2
2.25732s Ricevuti 1024 byte da 10.1.1.1
2.25732s Echoing packet
Ricevuti 1024 byte da 10.1.1.2
Inviati 1024 byte a 10.1.1.2
3.25732s Ricevuti 1024 byte da 10.1.1.1
3.25732s Echoing packet
Ricevuti 1024 byte da 10.1.1.2
10s UdpEchoServerApplication:StopApplication()
UdpEchoServerApplication:DoDispose()
UdpEchoServerApplication:~UdpEchoServer()

Hai appena inviato due pacchetti. Abbastanza semplice, vero?
Come utente di ns‑3, puoi utilizzare il sistema di argomenti della riga di comando per gestire i valori globali e gli attributi. Se sei l'autore di un modello, puoi aggiungere nuovi attributi ai tuoi oggetti, i quali saranno automaticamente disponibili per la personalizzazione da parte dei tuoi utenti tramite il sistema della riga di comando. Se sei l'autore di uno script, puoi aggiungere nuove variabili ai tuoi script e collegarle senza problemi al sistema della riga di comando.

5.3 Utilizzo del sistema di tracciamento

L'intero scopo della modellazione è generare output per ulteriori analisi, e il sistema di tracciamento di ns‑3 è il principale meccanismo per farlo. Poiché ns‑3 è un programma in C++, possono essere utilizzati i mezzi standard per la generazione di output di un programma in C++:

#include <iostream>
...
int main ()
{
...
std::cout << "The value of x is " << x << std::endl;
...
}

Puoi persino utilizzare il modulo di logging per aggiungere una piccola struttura alla tua soluzione. Sono noti molti problemi derivanti da questo approccio e per risolverli abbiamo fornito un sottosistema di tracciamento degli eventi.

Gli obiettivi principali del sistema di tracciamento ns‑3:

  • Per le attività di base, il sistema di tracciamento deve consentire all'utente di generare un tracciamento standard per le fonti più popolari e di scegliere gli oggetti che generano il tracciamento;

  • Gli utenti intermedi devono poter estendere il sistema di tracciamento per modificare il formato di output generato o per inserire nuove fonti di tracciamento, senza modificare il nucleo del simulatore;

  • Gli utenti esperti possono modificare il nucleo del simulatore per aggiungere nuove fonti e ricevitori di tracciamento. Il sistema di tracciamento ns-3 è costruito sui principi di fonti e ricevitori di tracciamento indipendenti, oltre a un meccanismo di connessione unificato per collegare le fonti ai consumatori.

Il sistema di tracciamento ns-3 si basa su principi di sorgenti e ricevitori di tracciamento indipendenti, nonché su un meccanismo unificato per collegare le sorgenti ai ricevitori. Le sorgenti di tracciamento sono oggetti che possono segnalare eventi che si verificano nella simulazione e fornire accesso ai dati sottostanti di interesse. Ad esempio, una sorgente di tracciamento può indicare quando un dispositivo di rete ha ricevuto un pacchetto e fornire accesso al contenuto del pacchetto per i ricevitori di tracciamento interessati.

Le sorgenti di tracciamento sono di per sé inutili se non sono "collegate" ad altre parti del codice che effettivamente fanno qualcosa di utile con le informazioni fornite dal ricevitore. I tracciatori sono consumatori di eventi e dati forniti dalle sorgenti di tracciamento. Ad esempio, si può creare un ricevitore di tracciamento che (una volta collegato a una sorgente di tracciamento dell'esempio precedente) stamperà le parti interessanti del pacchetto ricevuto.

Una giustificazione plausibile per una tale netta separazione è quella di consentire agli utenti di collegare nuovi tipi di riceventi a fonti di tracciamento esistenti senza la necessità di modificare e ricompilare il kernel del simulatore. In questo modo, nell'esempio sopra, l'utente può definire un nuovo tracciatore nel proprio script e collegarlo a una fonte di tracciamento già definita nel kernel della simulazione, modificando solo lo script utente.

In questa guida esamineremo alcune fonti e ricevitori predefiniti e mostreremo come possono essere configurati con il minor sforzo da parte dell'utente. Consulta la guida ns-3 o le sezioni con istruzioni per ulteriori informazioni sulla configurazione avanzata del tracciamento, inclusa l'espansione dello spazio dei nomi di tracciamento e la creazione di nuove fonti di tracciamento.

5.3.1 Tracciamento ASCII

ns-3 fornisce funzionalità ausiliarie che offrono un sistema di tracciamento a basso livello, aiutandoti con i dettagli durante la configurazione di semplici tracciamenti dei pacchetti. Abilitando questa funzione, vedrai l'output nei file ASCII. Per coloro che conoscono l'output di ns-2, questo tipo di tracciamento è simile. out.tr, generato da molti script.

Passiamo al sodo e aggiungiamo alcuni risultati di tracciamento ASCII al nostro script scratch/myfirst.cc. Proprio prima della chiamata a Simulator::Run(), aggiungi le seguenti righe di codice:
AsciiTraceHelper ascii;

pointToPoint.EnableAsciiAll(ascii.CreateFileStream("myfirst.tr"));

Come in molte altre idiome di ns-3, questo codice utilizza un oggetto ausiliario per creare tracciamenti ASCII. La seconda riga contiene due chiamate di metodo annidate. Il metodo "interno" CreateFileStream() impiega l'idioma dell'oggetto anonimo per creare un oggetto flusso file nello stack (senza nome dell'oggetto) e lo passa al metodo chiamato. In futuro ci immergeremo più a fondo, ma tutto ciò che devi sapere a questo stadio è che stai creando un oggetto che rappresenta un file con il nome myfirst.tr e di trasferirlo in ns‑3. Ci aspettiamo che ns‑3 si prenda cura dell'oggetto creato per tutta la sua vita, durante la quale saranno risolti problemi causati da una sconosciuta (intenzionale) limitazione connessa ai costruttori di copia degli oggetti di flusso C++.

Chiamata esterna EnableAsciiAll() informa l'assistente che desideri abilitare la registrazione ASCII nella tua simulazione per tutte le connessioni punto a punto e che desideri che i (specificati) ricevitori di registrazione annotino le informazioni sul movimento dei pacchetti in formato ASCII.

Per coloro che sono familiari con ns-2, gli eventi monitorati equivalgono ai noti punti di registrazione, che registrano eventi «+», «-», «d» e «r».
Ora puoi raccogliere lo script e avviarlo dalla riga di comando:

$ ./waf --run scratch/myfirst

Come molte volte prima, vedrai alcuni messaggi da Waf, e poi “‘build’ finished successfully” (costruzione completata con successo) con alcuni messaggi dal programma in esecuzione.

Durante l'esecuzione, il programma creerà un file chiamato myfirst.tr. A causa delle peculiarità del funzionamento Waf, per impostazione predefinita il file non viene creato nella directory locale, ma nella directory di livello superiore del repository. Se desideri cambiare il percorso in cui vengono salvate le tracce, puoi utilizzare il parametro per Waf --cwd. Non lo abbiamo fatto, quindi per visualizzare il file di tracing ASCII myfirst.tr nel tuo editor preferito, dobbiamo andare nella directory di livello superiore del nostro repository.

Parsing del tracciamento ASCII

C'è molte informazioni in una forma piuttosto densa, ma la prima cosa a cui prestare attenzione è che il file è composto da righe separate. Questo sarà chiaramente visibile se allarghi la finestra di visualizzazione.

Ogni riga nel file corrisponde a un evento di tracing. In questo caso stiamo tracciando gli eventi nella coda di trasmissione, presente in ogni dispositivo di rete punto-punto nella simulazione. La coda di trasmissione è la coda attraverso la quale deve passare ogni pacchetto per il canale punto-punto. Nota che ogni riga nel file di tracing inizia con un singolo carattere (e ha uno spazio dopo di esso). Questo carattere avrà il seguente significato:

+: l'operazione di accodamento è stata eseguita nella coda del dispositivo;
-: l'operazione di estrazione dell'elemento è stata eseguita nella coda del dispositivo;
d: il pacchetto è stato scartato, di solito perché la coda è piena;
r: il pacchetto è stato ricevuto dal dispositivo di rete.

Esaminiamo più nel dettaglio la prima riga del file di tracciamento. La suddividerò in parti (con rientri per chiarezza) e con il numero di riga a sinistra:

0 +
1 2
2 /NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue
3 ns3::PppHeader (
4   Protocollo Point-to-Point: IP (0x0021))
6   ns3::Ipv4Header (
7     tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
8     lunghezza: 1052 10.1.1.1 > 10.1.1.2)
9     ns3::UdpHeader (
10      lunghezza: 1032 49153 > 9)
11      Payload (dimensione=1024)

La prima sezione di questo evento di tracciamento esteso (riga 0) è l'operazione. Abbiamo qui il simbolo +, che corrisponde all'operazione di accodamento per la trasmissione. La seconda sezione (riga 1) è il tempo di simulazione, espresso in secondi. Ricorderete che abbiamo richiesto UdpEchoClientApplication di iniziare l'invio dei pacchetti dopo due secondi. Qui vediamo conferma che ciò sta effettivamente accadendo.

Nella seguente sezione dell'esempio di tracciamento (dalla riga 2) viene mostrato quale sorgente di tracciamento ha generato questo evento (indicato come spazio dei nomi). Puoi considerare lo spazio dei nomi di tracciamento più o meno come uno spazio dei nomi del file system. La radice dello spazio dei nomi è NodeList. Questo corrisponde al contenitore gestito dal codice principale di ns‑3. Esso contiene tutti i nodi creati nello script. Proprio come un file system può avere directory nella radice, NodeList possiamo avere molti nodi. Quindi, la riga /NodeList/0 fa riferimento al nodo zero in NodeList, che di solito comprendiamo come "nodo 0". In ogni nodo c'è un elenco di dispositivi che sono stati installati. Questo elenco si trova subito dopo nello spazio dei nomi. Puoi vedere che questo evento di tracciamento proviene da DeviceList/0, che è il dispositivo zero installato nel nodo.

La sottostringa successiva, $ ns3::PointToPointNetDevice, indica quale dispositivo si trova nella posizione zero: elenco dei dispositivi del nodo zero. Ricordiamo che l'operazione +, presente nella riga 0, indicava che nell'attesa di trasferimento del dispositivo è stato aggiunto un elemento. Questo è riflesso negli ultimi segmenti del 'percorso di tracciamento': TxQueue/Enqueue.

Le altre sezioni nel tracciamento dovrebbero essere abbastanza intuitive. Le righe 3-4 indicano che il pacchetto è incapsulato nel protocollo punto-punto. Le righe 5-7 mostrano che il pacchetto ha un'intestazione versione IP4 e ha origine all'indirizzo IP 10.1.1.1 e destinato a 10.1.1.2. Le righe 8-9 mostrano che questo pacchetto ha un'intestazione UDP e, infine, la riga 10 mostra che il payload è di 1024 byte come previsto.

La riga successiva nel file di tracciamento mostra che lo stesso pacchetto è stato estratto dalla coda di trasmissione sullo stesso nodo.

La terza riga nel file di tracciamento mostra che il pacchetto è stato ricevuto dal dispositivo di rete sul nodo con il server di echo. Ho riprodotto questo evento qui sotto.

0 r
1 2.25732
2 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/MacRx
3   ns3::Ipv4Header (
4     tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
5     length: 1052 10.1.1.1 > 10.1.1.2)
6     ns3::UdpHeader (
7       length: 1032 49153 > 9)
8       Payload (size=1024)

Si prega di notare che l'operazione di tracciamento è ora r, e il tempo di simulazione è aumentato a 2,25732 secondi. Se avete seguito attentamente le istruzioni del tutorial, questo significa che avete lasciato il DataRate dei dispositivi di rete e la latenza del canale ai loro valori predefiniti. Questo tempo dovrebbe esservi familiare, poiché lo avete già visto nella sezione precedente.

La registrazione dello spazio dei nomi della sorgente di tracciamento (linea 2) è stata modificata per riflettere che questo evento proviene dal nodo 1 (/NodeList/1) и пакет принят источником трассировки (/MacRx). Dovreste trovare abbastanza facile seguire il movimento del pacchetto attraverso la topologia, osservando ciò che rimane nel file di tracciamento.

5.3.2 Tracciamento PCAP

I dispositivi ns-3 possono anche essere utilizzati per generare file di tracciamento nel formato .pcap. L'acronimo pcap (di solito scritto in minuscolo) sta per cattura pacchetti ed è essenzialmente un'API che include la definizione del formato del file .pcap. Il programma più popolare in grado di leggere e visualizzare questo formato è Wireshark (precedentemente noto come Ethereal). Tuttavia, ci sono molti analizzatori di tracce del traffico che utilizzano questo formato di pacchetto. Raccomandiamo agli utenti di utilizzare diversi strumenti disponibili per analizzare le tracce pcap. In questa guida ci concentreremo sulla visualizzazione delle tracce pcap con tcpdump.

L'attivazione della tracciatura pcap avviene con una sola riga di codice.

pointToPoint.EnablePcapAll ("myfirst");

Incolla questa riga di codice dopo il codice di tracciatura ASCII che abbiamo appena aggiunto a scratch/myfirst.cc. Tieni presente che abbiamo passato solo la stringa «myfirst», non «myfirst.pcap» o qualcosa di simile. Questo perché il parametro è un prefisso, non un nome di file completo. Durante la simulazione, il tool creerà effettivamente un file di tracciatura per ogni dispositivo point-to-point. I nomi dei file saranno costruiti usando il prefisso, il numero del nodo, il numero del dispositivo e il suffisso «.pcap».

Per il nostro esempio di script, alla fine vedremo file con i nomi «myfirst-0-0.pcap» e «myfirst-1-0.pcap», che sono tracciature pcap per il nodo 0-dispositivo 0 e il nodo 1-dispositivo 0 rispettivamente. Dopo aver aggiunto la riga di codice per attivare la tracciatura pcap, puoi eseguire lo script come di consueto:

$ ./waf --run scratch/myfirst

Se guardate nella directory principale della vostra distribuzione, dovreste vedere tre file: il file di tracciamento ASCII myfirst.tr, che abbiamo esaminato in precedenza, i file myfirst-0-0.pcap e myfirst-1-0.pcap — nuovi file pcap appena generati.

Leggere l'output con tcpdump

Al momento, il modo più semplice per visualizzare i file pcap è utilizzare tcpdump.

$ tcpdump -nn -tt -r myfirst-0-0.pcap
reading from file myfirst-0-0.pcap, link-type PPP (PPP)
2.000000 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 1024
2.514648 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, length 1024
tcpdump -nn -tt -r myfirst-1-0.pcap
reading from file myfirst-1-0.pcap, link-type PPP (PPP)
2.257324 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 1024
2.257324 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, length 1024

Nel dump myfirst-0-0.pcap (dispositivo client) potete vedere che il pacchetto di eco viene inviato dopo 2 secondi di simulazione. Se guardate il secondo dump (myfirst-1-0.pcap), vedrete che il pacchetto viene ricevuto al momento 2,257324 secondi. Vedrete nel secondo dump che il pacchetto viene restituito al momento 2,257324 secondi e, infine, che il pacchetto è stato ricevuto dal client nel primo dump al momento 2,514648 secondi.

Leggere l'output con Wireshark

Se non siete familiari con Wireshark, c'è un sito web da cui potete scaricare programmi e documentazione: http://www.wireshark.org/. Wireshark — è un'interfaccia grafica utente che può essere utilizzata per visualizzare questi file di tracciamento. Se hai Wireshark, puoi aprire uno qualsiasi dei file di tracciamento e visualizzarne il contenuto come se avessi catturato pacchetti utilizzando un analizzatore di pacchetti.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster