Network Flow using Sankey Diagram

Qualche mese fa ho sviluppato un plugin, scritto in python, per la visualizzazione dei flussi di rete, per il programma nTop di Luca Deri. Il plugin è presente di default nella versione 5.0 di ntop.

Il diagramma “Sankey” è uno specifico diagramma di flusso, nel quale viene mostrata la larghezza delle frecce in proporzione alla quantità di flusso. Generalmente sono utilizzati per visualizzare le quantità di energia o materiali o costi tra i processi.
In questo programma, Network Flows, il diagramma di flusso Sankey viene utilizzato per mostrare le quantità di dati (flussi di rete), espressi in bytes, transitati tra uno o più host.

Network Flow using Sankey Diagram 1

Si può facilmente notare che in questo primo diagramma non si evidenziano le informazioni dei protocolli presenti nei flussi. Si è scelto di proposito di dare, in primo luogo, una visione d’insieme dei flussi maggiori della rete, lasciando, tuttavia, la possibilità di cliccare su un particolare flusso per aumentare il livello di dettaglio dei dati ed, eventualmente, di filtrarli selezionando solo i protocolli voluti.
In questo primo diagramma tutti i flussi di rete tra due host sono accorpati, le uniche informazioni mostrate sul flusso sono la sua direzione e dimensione.

Il programma Network Flows nella sua versione dimostrativa, liberamente scaricabile in licenza gpl, acquisisce le informazioni da visualizzare da un file, dove ogni riga è definita come:

host sorgente | host destinazione | bytes in | bytes out | proto layer 4| proto layer 7

Questo file viene elaborato dallo script python sankey.py che produrrà un output in formato json. I dati sono organizzati in:

  • una lista di nodi, dove ogni nodo è definito da un nome rappresentante l’indirizzo ip dell’host, altrimenti dal suo nome risolto, seguita da
  • una lista di archi, dove per ogni arco è definito il suo nodo di origine, il suo nodo di destinazione, il suo peso e la sua direzione;
  • meta informazioni, che definiscono:
    • il numero massimo di host che si è scelto di visualizzare nel diagramma;
    • l’ordine di misura del peso di un arco;
    • i protocolli layer 4 e layer 7 presenti nei flussi dati;
    • i sottoinsiemi dei predetti protocolli che si è scelto di visualizzare nel diagramma;
    • più alcune variabili di stato.

Lo script sankey.py computa i dati letti da file creando, per ogni nuova tupla di indirizzi degli host sorgente/destinazione, un nuovo elemento nell’hashmap archi, se la tupla è già presente i dati verranno sommati a quelli esistenti.

Per ogni chiave (sorgente/destinazione) vengono memorizzate più informazioni:

  • la somma dei byte in ingresso e in uscita; dato che poi verrà usato per rappresentare il peso di quell’arco, sia per ordinare i flussi in ordine decrescente;
  • i byte in ingresso;
  • i byte in uscita;
  • un hashmap rappresentante i protocolli layer 4, la cui chiave è il nome del protocollo del livello di trasporto, che, a sua volta, memorizzerà:
    • la somma dei byte in ingresso e uscita per quel protocollo;
    • un’ultima hashmap, rappresentante i protocolli layer 7, le cui chiavi sono in nomi dei protocolli del livello applicativo, che, a sua volta, memorizzerà:
      • la somma dei byte in ingresso e in uscita;
      • i byte in ingresso;
      • I byte in uscita per ogni protocollo layer 7.

La ragione di questo gioco di matriosche è di poter dare all’utente, una volta valutata la visione d’insieme dei flussi di rete, la possibilità di avere delle informazioni più dettagliate su un paticolare flusso, tra due specifici host, cliccandovi sopra.

Il diagramma di flusso sankey ha dunque due visualizzazioni.
La prima, nella quale ogni host è definito come un rettangolo a cui viene associato un nome e un colore che lo identificano. In questa visualizzazione ogni rettangolo avrà almeno due archi uno uscente e l’altro entrante (almeno di non trovarci nel caso limite di un flusso in un’unica direzione one-way flow), in cui l’arco dello stesso colore rappresenterà sempre i dati in uscita per quel nodo e l’arco di colore diverso rappresenterà il flusso di dati in ingresso avente come origine il suo host di destinazione.

Nella seconda modalità di visualizzazione si potranno vedere uno o più archi, dove ogni arco rappresenta il protocollo applicativo, mentre, il colore non identifica più la direzione del flusso bensì il protocollo layer 7. I rettangoli al centro del diagramma identificano, invece, i protocolli del livello di trasporto.

Network Flow using Sankey Diagram 2

È comunque sempre possibile selezionare un sottoinsieme di protocolli o definire un numero massimo di nodi da visualizzare al fine di raffinare la rappresentazione dei dati nel diagramma di flusso in base alle esigenze dell’utente.

Il compito di visualizzare i dati, una volta che lo script sankey.py ha finito di elaborarli, è lasciato alla libreria grafica d3.js, la quale produrrà un grafico in formato svg.

É opportuno far notare che il codice che disegna il grafo di flusso sankey, quando è stato scritto il programma Network Flow, non era presente nella libreria d3, poiché era ancora in fase di sviluppo. Lo sviluppatore della libreria, Mike Bostock, prevede in futuro un possibile miglioramento dell’algoritmo al fine di minimizzare la sovrapposizione dei collegamenti o per supportare grafi ciclici come i cicli al primo hop o connessioni di loopback.

In merito agli archi di ritorno, per ovviare al problema ho scelto di confrontare, come stringhe, per ogni arco la sua sorgente e la sua destinazione. Se la sorgente è maggiore della destinazione la computazione dei dati rimane invariata, altrimenti, viene eseguito il complementare dei dati, invertendo la tupla sorgente/destinazione e viene eseguita la somma dei dati in ingresso alla variabile che conta i dati in uscita e viceversa.

Per chi ha installato python 3 di default, è d’obbligo modificare la prima riga del file: sankey.py da

#!/usr/bin/env python

a

#!/usr/bin/env python2

Grazie nignux per la segnalazione :-).

Per avviare il programma bisogna dare il comando

python webserver.py

mentre per visualizzare il diagramma basta andare alla pagina

http://localhost:8090/

Codice sorgente in licenza gpl v3.

TCP Socket (af_inet)(IPv4/IPv6)(with ssl) – c language

This program is an example of programming a TCP socket in C language, using the well-known client-server programming model.
The server side is multi-threaded, but the thread is optional since the developer/designer is still responsible for deciding if he/she needs it.

The library “commv6.c” develops all the functions to create, bind, listen, and remove a socket AF_INET, and the functions to send and receive messages (using the methods read and write). It supports: IPv4/IPv6 and SSL (see commSSL.c).
The structure of a message is defined in the file “msg.h”.

Code tested under debian-like and arch linux platform (thanks to nignux).


Questo programma è un esempio di programmazione di un socket TCP in linguaggio C, utilizzando il ben noto paradigma di programmazione client-server.
Il lato server è multi-threaded, ma è del tutto opzionale, e sarà responsabilità dello sviluppatore decidere se ne ha bisogno.

La libreria “commv6.c” sviluppa tutte le funzioni per creare, pubblicare, rimanere in ascolto e rimuovere una  socket af_inet, e le funzioni per inviare e ricevere messaggi (usando i metodi read e write). Il codice supporta socket ipv4/ipv6 e SSL (commSSL.c)
La struttura di un messaggio è definita nel file “msg.h”.

Codice testato sotto piattaforma debian-like e arch linux (ringraziamenti a nignux).


Be careful when you do a read(/write) on a socket: the machine at the other end of the socket is of your own platform (x86/x64)?
Fate attenzione quando fate una read(/write) su una socket: la macchina dall’altro capo della socket è della vostra stessa piattaforma (x86/x64)?
x86 x64
sizeof(char)  1  1
sizeof(short)  2  2
sizeof(float)  4  4
sizeof(int)  4  4
sizeof(unsigned int)  4  4
sizeof(long)  4  8
sizeof(double)  8  8
sizeof(long unsigned int)  4  8
sizeof(long double) 12 16
sizeof(long int)  4  8

x64

Linux 3.0.0-16-generic #28-Ubuntu SMP Fri Jan 27 17:44:39 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

x32

Linux 2.6.18-6-k7 #1 SMP Thu Aug 20 22:36:26 UTC 2009 i686 GNU/Linux

Si consiglia di utilizzare:

sys/types.h

dove vengono dichiarati i tipi:

int8_t
u_int8_t
int16_t
u_int16_t
int32_t
u_int32_t
int64_t
u_int64_t

Threads pool (posix) – c language (ver 2)

Example of generalized thread pool in C language with signal handling.

rev 2: Completely revised the code of the library.
Now there is a queue of jobs, a thread is awakened when a new job is available, following the classic mechanism of producer / consumer.

You can set: the thread pool size, its signal mask and the size of the job queue, calling the poolInit function that returns a new pool. If the signal mask is null then the signal mask shall be inherited from the creating thread.

The function poolDispatcher gets three arguments the pointer to the pool; a void pointer to function (start_routine), with a single argument void arg. (very similar to pthread_create). The poolDispather when executed creates a new job that is inserted into the queue of jobs.

If you send too many jobs to the pool and the queue fills up, the poolDispatcher reject the new job and returns the error code “-5” (to avoid DOS attacks).
The function poolDestroy, puts the pool in termination state, (the pool is no longer available to run new job), it waits for all active and pending jobs to finish; execute the join of the threads; free resources and exit.
doxygen docomuntation and source code (license GPLv2)

 

Esempio di pool di thread in linguaggio C generalizzato con gestione dei segnali.

E’ possibile passare a questa libreria un proprio puntatore a funzione.
La funzione verrà eseguita dal primo thread disponibile del pool di threads.

E’ facile notare come la funzione addjob esegue, nel caso in cui tutti i threads siano impegnati, attesa attiva.
La soluzione è presto detta, implementare una lista di jobs, oppure (per chi non ha voglia) aumentare opportunamente la dimensione del pool threads.

[update]
Rivisto completamente il codice della libreria.
Adesso esiste una lista di job; un thread del pool viene risvegliato quando un nuovo job è disponibile, seguendo il classico meccanismo di produttore/consumatore.

La dimensione massima della coda dei job è settabile in fase di creazione del pool.
Se si inviano troppi job al pool e la coda si riempie, la poolDispatcher rifiuterà il nuovo job ritornando il codice di errore “-5” (evitiamo attacchi di DOS).

La funzione poolDestroy, mette il pool in fase di terminazione, (ovvero il pool non è più disponibile ad eseguire nuovi job), aspetta che tutti i job attivi e pendenti terminino; esegue la join dei threads; libera le risorse ed esce.
[update-end]

Una volta terminato il job, il thread viene reso automaticamente disponibile per un nuovo job.
La dimensione del pool e la maschera dei segnali per i threads sono passate in fase di inizializzazione del pool stesso.

E’ possibile creare infiniti pool di threads, dato che ogni struttura dati viene creata dinamicamente in fase di inizializzazione del pool stesso. La maschera dei segnali è invece opzionale.

Per commenti e info più dettagliate sul codice: documentazione html (doxygen).

E per scaricare il codice sorgente: codice sorgente (in licenza gpl v2).