X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=sockctrl.tex;h=89a4b61ab699517007def414f9ddf0f0d8a5a916;hp=886d6d09edfa281ef3cb205d3f99c29390aaeb0a;hb=3812c62e758fdb4ce73de0b4d10908ce5606f680;hpb=cebc759ef695405a69328538834883d9d470b06e diff --git a/sockctrl.tex b/sockctrl.tex index 886d6d0..89a4b61 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -2299,6 +2299,8 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni: \func{select} che ritorna a causa dello stesso. \end{basedescript} +% TODO documentare SO_ATTACH_FILTER e SO_DETACH_FILTER + \subsection{L'uso delle principali opzioni dei socket} \label{sec:sock_options_main} @@ -2727,9 +2729,9 @@ sono definite in \file{netinet/ip.h}, ed accessibili includendo detto file. \const{IP\_RECVERR} &$\bullet$&$\bullet$&$\bullet$&\texttt{int}& abilita la gestione degli errori.\\ \const{IP\_MTU\_DISCOVER} &$\bullet$&$\bullet$& &\texttt{int}& - imposta il Path MTU Discovery.\\ + imposta il Path MTU \itindex{Maximum~Transfer~Unit} Discovery.\\ \const{IP\_MTU} &$\bullet$& & &\texttt{int}& - legge il valore attuale della MTU.\\ + legge il valore attuale della \itindex{Maximum~Transfer~Unit} MTU.\\ \const{IP\_ROUTER\_ALERT} &$\bullet$&$\bullet$&$\bullet$&\texttt{int}& imposta l'opzione \textit{IP router alert} sui pacchetti.\\ \const{IP\_MULTICAST\_TTL} &$\bullet$&$\bullet$& &\texttt{int}& @@ -2773,7 +2775,9 @@ seguente elenco: una struttura \struct{pktinfo} (vedi fig.~\ref{fig:sock_pktinfo_struct}) che mantiene una serie di informazioni riguardo i pacchetti in arrivo. In particolare è possibile conoscere l'interfaccia su cui è stato ricevuto un - pacchetto (nel campo \var{ipi\_ifindex}), l'indirizzo locale da esso + pacchetto (nel campo \var{ipi\_ifindex}),\footnote{in questo campo viene + restituito il valore numerico dell'indice dell'interfaccia, + sez.~\ref{sec:sock_ioctl_netdevice}.} l'indirizzo locale da esso utilizzato (nel campo \var{ipi\_spec\_dst}) e l'indirizzo remoto dello stesso (nel campo \var{ipi\_addr}). @@ -2934,13 +2938,13 @@ sez.~\ref{sec:net_sendmsg}). esplicitamente connesso con \func{connect}. Ad esempio con i socket UDP si potrà ottenere una stima iniziale della - \textit{Path MTU} eseguendo prima una \func{connect} verso la destinazione, - e poi usando \func{getsockopt} con questa opzione. Si può anche avviare - esplicitamente il procedimento di scoperta inviando un pacchetto di grosse - dimensioni (che verrà scartato) e ripetendo l'invio coi dati aggiornati. Si - tenga infine conto che durante il procedimento i pacchetti iniziali possono - essere perduti, ed è compito dell'applicazione gestirne una eventuale - ritrasmissione. + \itindex{Maximum~Transfer~Unit} \textit{Path MTU} eseguendo prima una + \func{connect} verso la destinazione, e poi usando \func{getsockopt} con + questa opzione. Si può anche avviare esplicitamente il procedimento di + scoperta inviando un pacchetto di grosse dimensioni (che verrà scartato) e + ripetendo l'invio coi dati aggiornati. Si tenga infine conto che durante il + procedimento i pacchetti iniziali possono essere perduti, ed è compito + dell'applicazione gestirne una eventuale ritrasmissione. \itindend{Maximum~Transfer~Unit} @@ -3031,14 +3035,14 @@ precedenti opzioni di sez.~\ref{sec:sock_ipv4_options}.\footnote{in realt Il protocollo che supporta il maggior numero di opzioni è TCP; per poterle utilizzare occorre specificare \const{SOL\_TCP} (o l'equivalente \const{IPPROTO\_TCP}) come valore per l'argomento \param{level}. Si sono -riportate le varie opzioni disponibili in tab.~\ref{tab:sock_opt_tcp}, dove -sono elencate le rispettive costanti da utilizzare come valore per l'argomento -\param{optname}. Dette costanti e tutte le altre costanti e strutture -collegate all'uso delle opzioni TCP sono definite in \file{netinet/tcp.h}, ed -accessibili includendo detto file.\footnote{in realtà questo è il file usato - dalle librerie; la definizione delle opzioni effettivamente supportate da - Linux si trova nel file \texttt{linux/tcp.h}, dal quale si sono estratte le - costanti di tab.~\ref{tab:sock_opt_tcplevel}.} +riportate le varie opzioni disponibili in tab.~\ref{tab:sock_opt_tcplevel}, +dove sono elencate le rispettive costanti da utilizzare come valore per +l'argomento \param{optname}. Dette costanti e tutte le altre costanti e +strutture collegate all'uso delle opzioni TCP sono definite in +\file{netinet/tcp.h}, ed accessibili includendo detto file.\footnote{in realtà + questo è il file usato dalle librerie; la definizione delle opzioni + effettivamente supportate da Linux si trova nel file \texttt{linux/tcp.h}, + dal quale si sono estratte le costanti di tab.~\ref{tab:sock_opt_tcplevel}.} \begin{table}[!htb] \centering @@ -3050,12 +3054,12 @@ accessibili includendo detto file.\footnote{in realt \hline \hline \const{TCP\_NODELAY} &$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - spedisce tutti i pacchetti il prima possibile.\\ + spedisce immediatamente i dati in segmenti singoli.\\ \const{TCP\_MAXSEG} &$\bullet$&$\bullet$& &\texttt{int}& - valore della \itindex{Maximum~Segment~Size} MSS per i pacchetti in + valore della \itindex{Maximum~Segment~Size} MSS per i segmenti in uscita.\\ \const{TCP\_CORK} &$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - non invia frame parziali.\\ + accumula i dati in un unico segmento.\\ \const{TCP\_KEEPIDLE} &$\bullet$&$\bullet$& &\texttt{int}& tempo in secondi prima di inviare un \textit{keepalive}.\\ \const{TCP\_KEEPINTVL} &$\bullet$&$\bullet$& &\texttt{int}& @@ -3074,8 +3078,8 @@ accessibili includendo detto file.\footnote{in realt restituisce informazioni sul socket.\\ \const{TCP\_QUICKACK} &$\bullet$&$\bullet$&$\bullet$&\texttt{int}& abilita la modalità \textit{quickack}.\\ - \const{TCP\_CONGESTION} &$\bullet$&$\bullet$&? &\texttt{?}& %??? - non ancora documentata.\\ + \const{TCP\_CONGESTION} &$\bullet$&$\bullet$& &\texttt{char *}& + imposta l'algoritmo per il controllo della congestione.\\ \hline \end{tabular} \caption{Le opzioni per i socket TCP disponibili al livello @@ -3087,113 +3091,186 @@ Le descrizioni delle varie opzioni riportate in tab.~\ref{tab:sock_opt_tcplevel} sono estremamente sintetiche ed indicative, la spiegazione del funzionamento delle singole opzioni con una maggiore quantità di dettagli è fornita nel seguente elenco: -\begin{basedescript}{\desclabelwidth{3.3cm}\desclabelstyle{\nextlinelabel}} - -\item[\const{TCP\_NODELAY}] il protocollo TCP un meccanismo di bufferizzazione - dei pacchetti uscenti, per evitare la trasmissione di tanti pacchetti - piccoli con un utilizzo non ottimale della banda disponibile. Questo - meccanismo è controllato da un apposito algoritmo (detto \textsl{algoritmo - di Nagle}, vedi sez.\ref{sez:tcp_protocol_xxx}). Il comportamento normale - del protocollo prevede che i pacchetti siano accumulati fintanto che non si - raggiunge una quantità di dati considerata adeguata per eseguire la - trasmissione. - - Impostando questa opzione si disabilita questo meccanismo ed i pacchetti - vengono inviati immediatamente qualunque sia la loro dimensione; l'opzione - viene sovrascritta dall'eventuale impostazione dell'opzione - \const{TCP\_CORK}, che blocca l'invio immediato. Tuttavia quando la si - abilita viene sempre forzato lo scaricamento della coda di invio (con - conseguente trasmissione di tutti i pacchetti pendenti), anche qualora si - fosse già abilitata \const{TCP\_CORK}.\footnote{si tenga presente però che - \const{TCP\_CORK} può essere specificata insieme a \const{TCP\_NODELAY} - soltanto a partire dal kernel 2.5.71.} - -\item[\const{TCP\_MAXSEG}] permette di leggere e modificare il valore della - \itindex{Maximum~Segment~Size} MSS (vedi sez.~\ref{sec:net_lim_dim} e - sez.\ref{sez:tcp_protocol_xxx}) dei pacchetti uscenti, e se l'opzione è - impostata prima di stabilire la connessione, cambia anche il valore della - \itindex{Maximum~Segment~Size} MSS annunciata all'altro capo della - connessione. Se si specificano valori maggiori della MTU questi verranno - ignorati, inoltre TCP imporrà anche i suoi limiti massimo e minimo per - questo valore. - -\item[\const{TCP\_CORK}] quando questa opzione viene abilitata non vengono - inviati pacchetti di dati fintanto che essa non venga disabilitata; a quel - punto tutti i dati rimasti in coda saranno inviati in un solo pacchetto. - Questa opzione viene usata per gestire manualmente il flusso dei dati - mettendo una sorta di ``\textsl{tappo}'' (da cui il nome in inglese) al - flusso di uscita, in modo ottimizzare a mano l'uso della banda. È molto - utile anche quando si effettua il trasferimento di dati da un file con - \func{sendfile} (vedi sez.~\ref{sec:file_sendfile}), se si vuole inserire - una intestazione prima della chiamata a questa funzione. +\begin{basedescript}{\desclabelwidth{2.5cm}\desclabelstyle{\nextlinelabel}} + + +\item[\const{TCP\_NODELAY}] il protocollo TCP utilizza un meccanismo di + bufferizzazione dei dati uscenti, per evitare la trasmissione di tanti + piccoli segmenti con un utilizzo non ottimale della banda + disponibile.\footnote{il problema è chiamato anche \textit{silly window + syndrome}, per averne un'idea si pensi al risultato che si ottiene + quando un programma di terminale invia un segmento TCP per ogni tasto + premuto, 40 byte di intestazione di protocollo con 1 byte di dati + trasmessi; per evitare situazioni del genere è stato introdotto + l'\textsl{algoritmo di Nagle}.} Questo meccanismo è controllato da un + apposito algoritmo (detto \textsl{algoritmo di Nagle}, vedi + sez.~\ref{sez:tcp_protocol_xxx}). Il comportamento normale del protocollo + prevede che i dati siano accumulati fintanto che non si raggiunge una + quantità considerata adeguata per eseguire la trasmissione di un singolo + segmento. + + Ci sono però delle situazioni in cui questo comportamento può non essere + desiderabile, ad esempio quando si sa in anticipo che l'applicazione invierà + soltanto un piccolo quantitativo di dati;\footnote{è il caso classico di una + richiesta HTTP.} in tal caso l'attesa introdotta dall'algoritmo di + bufferizzazione non soltanto è inutile, ma peggiora le prestazioni + introducendo un ritardo. Impostando questa opzione si disabilita l'uso + dell'\textsl{algoritmo di Nagle} ed i dati vengono inviati immediatamente in + singoli segmenti, qualunque sia la loro dimensione. Ovviamente l'uso di + questa opzione è dedicato a chi ha esigenze particolari come quella + illustrata, che possono essere stabilite solo per la singola applicazione. + + Si tenga conto che questa opzione viene sovrascritta dall'eventuale + impostazione dell'opzione \const{TCP\_CORK} (il cui scopo è sostanzialmente + l'opposto) che blocca l'invio immediato. Tuttavia quando la si abilita viene + sempre forzato lo scaricamento della coda di invio (con conseguente + trasmissione di tutti i dati pendenti), anche qualora si fosse già abilitata + \const{TCP\_CORK}.\footnote{si tenga presente però che \const{TCP\_CORK} può + essere specificata insieme a \const{TCP\_NODELAY} soltanto a partire dal + kernel 2.5.71.} + +\item[\const{TCP\_MAXSEG}] con questa opzione si legge o si imposta il valore + della \itindex{Maximum~Segment~Size} MSS (\textit{Maximum~Segment~Size}, + vedi sez.~\ref{sec:net_lim_dim} e sez.~\ref{sez:tcp_protocol_xxx}) dei + segmenti TCP uscenti. Se l'opzione è impostata prima di stabilire la + connessione, si cambia anche il valore della \itindex{Maximum~Segment~Size} + MSS annunciata all'altro capo della connessione. Se si specificano valori + maggiori della \itindex{Maximum~Transfer~Unit} MTU questi verranno ignorati, + inoltre TCP imporrà anche i suoi limiti massimo e minimo per questo valore. + +\item[\const{TCP\_CORK}] questa opzione è il complemento naturale di + \const{TCP\_NODELAY} e serve a gestire a livello applicativo la situazione + opposta, cioè quella in cui si sa fin dal principio che si dovranno inviare + grosse quantità di dati. Anche in questo caso l'\textsl{algoritmo di Nagle} + tenderà a suddividerli in dimensioni da lui ritenute + opportune,\footnote{l'algoritmo cerca di tenere conto di queste situazioni, + ma essendo un algoritmo generico tenderà comunque ad introdurre delle + suddivisioni in segmenti diversi, anche quando potrebbero non essere + necessarie, con conseguente spreco di banda.} ma sapendo fin dall'inizio + quale è la dimensione dei dati si potranno di nuovo ottenere delle migliori + prestazioni disabilitandolo, e gestendo direttamente l'invio del nostro + blocco di dati in soluzione unica. + + Quando questa opzione viene abilitata non vengono inviati segmenti di dati + fintanto che essa non venga disabilitata; a quel punto tutti i dati rimasti + in coda saranno inviati in un solo segmento TCP. In sostanza con questa + opzione si può controllare il flusso dei dati mettendo una sorta di + ``\textsl{tappo}'' (da cui il nome in inglese) al flusso di uscita, in modo + ottimizzare a mano l'uso della banda. Si tenga presente che per l'effettivo + funzionamento ci si deve ricordare di disattivare l'opzione al termine + dell'invio del blocco dei dati. + + Si usa molto spesso \const{TCP\_CORK} quando si effettua il trasferimento + diretto di un blocco di dati da un file ad un socket con \func{sendfile} + (vedi sez.~\ref{sec:file_sendfile}), per inserire una intestazione prima + della chiamata a questa funzione; senza di essa l'intestazione potrebbe + venire spedita in un segmento a parte, che a seconda delle condizioni + potrebbe richiedere anche una risposta di ACK, portando ad una notevole + penalizzazione delle prestazioni. Si tenga presente che l'implementazione corrente di \const{TCP\_CORK} non - consente di bloccare l'invio dei pacchetti per più di 200 millisecondi, - passati i quali i dati accumulati in coda sanno inviati comunque. Questa - opzione non è disponibile su tutti i kernel unix-like e deve essere evitata - se si vuole scrivere codice portabile. - -\item[\const{TCP\_KEEPIDLE}] imposta l'intervallo di tempo, in secondi, che - deve trascorrere senza traffico sul socket prima che vengano inviati, - qualora si sia attivata su di esso l'opzione \const{SO\_KEEPALIVE}, i - messaggi di \textit{keep-alive} (si veda la trattazione relativa al - \textit{keep-alive} in sez.~\ref{sec:sock_options_main}). Anche questa - opzione non è disponibile su tutti i kernel unix-like e deve essere evitata - se si vuole scrivere codice portabile. - -\item[\const{TCP\_KEEPINTVL}] imposta l'intervallo di tempo, in secondi, fra - due messaggi di \textit{keep-alive} successivi (si veda sempre quanto - illustrato in sez.~\ref{sec:sock_options_main}). Come la precedente non è - disponibile su tutti i kernel unix-like e deve essere evitata se si vuole - scrivere codice portabile. + consente di bloccare l'invio dei dati per più di 200 millisecondi, passati i + quali i dati accumulati in coda sanno inviati comunque. Questa opzione è + tipica di Linux\footnote{l'opzione è stata introdotta con i kernel della + serie 2.4.x.} e non è disponibile su tutti i kernel unix-like, pertanto + deve essere evitata se si vuole scrivere codice portabile. + +\item[\const{TCP\_KEEPIDLE}] con questa opzione si legge o si imposta + l'intervallo di tempo, in secondi, che deve trascorrere senza traffico sul + socket prima che vengano inviati, qualora si sia attivata su di esso + l'opzione \const{SO\_KEEPALIVE}, i messaggi di \textit{keep-alive} (si veda + la trattazione relativa al \textit{keep-alive} in + sez.~\ref{sec:sock_options_main}). Anche questa opzione non è disponibile + su tutti i kernel unix-like e deve essere evitata se si vuole scrivere + codice portabile. + +\item[\const{TCP\_KEEPINTVL}] con questa opzione si legge o si imposta + l'intervallo di tempo, in secondi, fra due messaggi di \textit{keep-alive} + successivi (si veda sempre quanto illustrato in + sez.~\ref{sec:sock_options_main}). Come la precedente non è disponibile su + tutti i kernel unix-like e deve essere evitata se si vuole scrivere codice + portabile. -\item[\const{TCP\_KEEPCNT}] imposta il numero totale di messaggi di - \textit{keep-alive} da inviare prima di concludere che la connessione è - caduta per assenza di risposte ad un messaggio di \textit{keep-alive} (di - nuovo vedi sez.~\ref{sec:sock_options_main}). Come la precedente non è - disponibile su tutti i kernel unix-like e deve essere evitata se si vuole +\item[\const{TCP\_KEEPCNT}] con questa opzione si legge o si imposta il numero + totale di messaggi di \textit{keep-alive} da inviare prima di concludere che + la connessione è caduta per assenza di risposte ad un messaggio di + \textit{keep-alive} (di nuovo vedi sez.~\ref{sec:sock_options_main}). Come + la precedente non è disponibile su tutti i kernel unix-like e deve essere + evitata se si vuole scrivere codice portabile. + +\item[\const{TCP\_SYNCNT}] con questa opzione si legge o si imposta il numero + di tentativi di ritrasmissione dei segmenti SYN usati nel + \itindex{three~way~handshake} \textit{three way handshake} prima che il + tentativo di connessione venga abortito (si ricordi quanto accennato in + sez.\ref{sec:TCP_func_connect}). Sovrascrive per il singolo socket il valore + globale impostato con la \textit{sysctl} \texttt{tcp\_syn\_retries} (vedi + sez.~\ref{sec:sock_ipv4_sysctl}). Non vengono accettati valori maggiori di + 255; anche questa opzione non è standard e deve essere evitata se si vuole scrivere codice portabile. -\item[\const{TCP\_SYNCNT}] imposta il numero di tentativi di ritrasmissione - dei segmenti SYN usati nel \itindex{three~way~handshake} \textit{three way - handshake} prima che il tentativo di connessione venga abortito (si - ricordi quanto accennato in sez.\ref{sec:TCP_func_connect}). Sovrascrive per - il singolo socket il valore globale impostato con la \textit{sysctl} - \texttt{tcp\_syn\_retries} (vedi sez.~\ref{sec:sock_ipv4_sysctl}). Non - vengono accettati valori maggiori di 255; anche questa opzione non è - standard e deve essere evitata se si vuole scrivere codice portabile. - -\item[\const{TCP\_LINGER2}] imposta, in numero di secondi, il tempo di - sussistenza dei socket terminati nello stato \texttt{FIN\_WAIT2} (si ricordi - quanto visto in sez.~\ref{sec:TCP_conn_term}).\footnote{si tenga ben - presente che questa opzione non ha nulla a che fare con l'opzione - \const{SO\_LINGER} che abbiamo visto in sez.~\ref{sec:sock_options_main}.} - Questa opzione consente di sovrascrivere per il singolo socket il valore - globale impostato con la \textit{sysctl} \texttt{tcp\_fin\_timeout} (vedi +\item[\const{TCP\_LINGER2}] con questa opzione si legge o si imposta, in + numero di secondi, il tempo di sussistenza dei socket terminati nello stato + \texttt{FIN\_WAIT2} (si ricordi quanto visto in + sez.~\ref{sec:TCP_conn_term}).\footnote{si tenga ben presente che questa + opzione non ha nulla a che fare con l'opzione \const{SO\_LINGER} che + abbiamo visto in sez.~\ref{sec:sock_options_main}.} Questa opzione + consente di sovrascrivere per il singolo socket il valore globale impostato + con la \textit{sysctl} \texttt{tcp\_fin\_timeout} (vedi sez.~\ref{sec:sock_ipv4_sysctl}). Anche questa opzione è da evitare se si ha a cuore la portabilità del codice. -\item[\const{TCP\_DEFER\_ACCEPT}] consente ad un socket in ascolto di - ritornare da \func{accept} soltanto quando sono presenti dati sullo stesso, - e non alla conclusione del \itindex{three~way~handshake} \textit{three way - handshake}. Prende un valore intero che indica il numero massimo di - secondi per cui il ritorno di \func{accept} viene rimandato; non deve essere +\item[\const{TCP\_DEFER\_ACCEPT}] questa opzione consente di modificare il + comportamento standard del protocollo TCP nello stabilirsi di una + connessione; se ricordiamo il meccanismo del \itindex{three~way~handshake} + \textit{three way handshake} illustrato in fig.~\ref{fig:TCP_TWH} possiamo + vedere che in genere un client inizierà ad inviare i dati ad un server solo + dopo l'emissione dell'ultimo segmento di ACK. + + Di nuovo esistono situazioni (e la più tipica è quella di una richiesta + HTTP) in cui sarebbe utile inviare immediatamente la richiesta all'interno + del segmento con l'ultimo ACK del \itindex{three~way~handshake} + \textit{three way handshake}; si potrebbe così risparmiare l'invio di un + segmento successivo per la richiesta e il ritardo sul server fra la + ricezione dell'ACK e quello della richiesta. + + Se si invoca \const{TCP\_DEFER\_ACCEPT} su un socket dal lato client (cioè + dal lato da cui si invoca \func{connect}) si istruisce il kernel a non + inviare immediatamente l'ACK finale del \itindex{three~way~handshake} + \textit{three way handshake}, attendendo per un po' di tempo la prima + scrittura, in modo da inviare i dati di questa insieme col segmento ACK. + Chiaramente la correttezza di questo comportamento dipende in maniera + diretta dal tipo di applicazione che usa il socket; con HTTP, che invia una + breve richiesta, permette di risparmiare un segmento, con FTP, in cui invece + si attende la ricezione del prompt del server, introduce un inutile ritardo. + + Allo stesso tempo il protocollo TCP prevede che sul lato del server la + funzione \func{accept} ritorni dopo la ricezione dell'ACK finale, in tal + caso quello che si fa usualmente è lanciare un nuovo processo per leggere i + successivi dati, che si bloccherà su una \func{read} se questi non sono + disponibili; in questo modo si saranno impiegate delle risorse (per la + creazione del nuovo processo) che non vengono usate immediatamente. L'uso + di \const{TCP\_DEFER\_ACCEPT} consente di intervenire anche in questa + situazione; quando la si invoca sul lato server (vale a dire su un socket in + ascolto) l'opzione fa sì che \func{accept} ritorni soltanto quando sono + presenti dei dati sul socket, e non alla ricezione dell'ACK conclusivo del + \itindex{three~way~handshake} \textit{three way handshake}. + + L'opzione prende un valore intero che indica il numero massimo di secondi + per cui mantenere il ritardo, sia per quanto riguarda il ritorno di + \func{accept} su un server, che per l'invio dell'ACK finale insieme ai dati + su un client. L'opzione è specifica di Linux non deve essere utilizzata in + codice che vuole essere portabile.\footnote{su FreeBSD è presente una + opzione \texttt{SO\_ACCEPTFILTER} che consente di ottenere lo stesso + comportamento di \const{TCP\_DEFER\_ACCEPT} per quanto riguarda il lato + server.} + +\item[\const{TCP\_WINDOW\_CLAMP}] con questa opzione si legge o si imposta + alla dimensione specificata, in byte, il valore dichiarato della + \itindex{advertised~window} \textit{advertised window} (vedi + sez.~\ref{sez:tcp_protocol_xxx}). Il kernel impone comunque una dimensione + minima pari a \texttt{SOCK\_MIN\_RCVBUF/2}. Questa opzione non deve essere utilizzata in codice che vuole essere portabile. -\item[\const{TCP\_WINDOW\_CLAMP}] limita alla dimensione specificata (in byte) - il valore dichiarato della \itindex{advertised~window} \textit{advertised - window} (vedi sez.\ref{sez:tcp_protocol_xxx}). Il kernel impone comunque - una dimensione minima pari a \texttt{SOCK\_MIN\_RCVBUF/2}. Questa opzione - non deve essere utilizzata in codice che vuole essere portabile. - -\item[\const{TCP\_INFO}] opzione, specifica di Linux, ma introdotta anche in - altri kernel (ad esempio FreeBSD) di controllare lo stato di un socket TCP - in user space. L'opzione restituisce in una speciale struttura - \struct{tcp\_info}, la cui definizione è riportata in - fig.~\ref{fig:tcp_info_struct}, tutta una serie di dati relativi al socket. - Anche questa opzione deve essere evitata se si vuole scrivere codice - portabile. - \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} @@ -3204,45 +3281,148 @@ quantit \label{fig:tcp_info_struct} \end{figure} -Con questa opzione diventa possibile ricevere una serie di informazioni -relative ad un socket TCP così da poter effettuare dei controlli senza dover -passare attraverso delle operazioni di lettura. Ad esempio si può verificare -se un socket è stato chiuso usando una funzione analoga a quella illustrata in -fig.~\ref{fig:is_closing}, in cui si utilizza il valore del campo -\var{tcpi\_state} di \struct{tcp\_info} per controllare lo stato del socket. +\item[\const{TCP\_INFO}] questa opzione, specifica di Linux, ma introdotta + anche in altri kernel (ad esempio FreeBSD) permette di controllare lo stato + interno di un socket TCP direttamente da un programma in user space. + L'opzione restituisce in una speciale struttura \struct{tcp\_info}, la cui + definizione è riportata in fig.~\ref{fig:tcp_info_struct}, tutta una serie + di dati che il kernel mantiene, relativi al socket. Anche questa opzione + deve essere evitata se si vuole scrivere codice portabile. + + Con questa opzione diventa possibile ricevere una serie di informazioni + relative ad un socket TCP così da poter effettuare dei controlli senza dover + passare attraverso delle operazioni di lettura. Ad esempio si può verificare + se un socket è stato chiuso usando una funzione analoga a quella illustrata + in fig.~\ref{fig:is_closing}, in cui si utilizza il valore del campo + \var{tcpi\_state} di \struct{tcp\_info} per controllare lo stato del socket. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \includestruct{listati/tcp_info.h} + \includecodesnip{listati/is_closing.c} \end{minipage} \caption{Codice della funzione \texttt{is\_closing.c}, che controlla lo stato di un socket TCP per verificare se si sta chiudendo.} \label{fig:is_closing} \end{figure} -\item[\const{TCP\_QUICKACK}] abilita o disabilita la modalità speciale - \textit{quickack}, in cui i pacchetti ACK vengono inviati immediatamente - senza le attese talvolta imposte dal normale funzionamento del protocollo - TCP. Questa opzione prende un valore logico, e non è permanente, nel senso - che si limita a forzare al momento della chiamata un passaggio da o verso la - modalità \textit{quickack}; le operazioni successive potrebbero a loro volta - entrare o uscire da questa modalità a seconda del processo interno del - protocollo o dalle condizioni della connessione (ad esempio in presenza di - timeout ritardati per i pacchetti ACK). +%Si noti come nell'esempio si sia ( + + +\item[\const{TCP\_QUICKACK}] con questa opzione è possibile eseguire una forma + di controllo sull'invio dei segmenti ACK all'interno di in flusso di dati su + TCP. In genere questo invio viene gestito direttamente dal kernel, il + comportamento standard, corrispondente la valore logico di vero (in genere + 1) per questa opzione, è quello di inviare immediatamente i segmenti ACK, in + quanto normalmente questo significa che si è ricevuto un blocco di dati e si + può passare all'elaborazione del blocco successivo. + + Qualora però la nostra applicazione sappia in anticipo che alla ricezione di + un blocco di dati seguirà immediatamente l'invio di un altro + blocco,\footnote{caso tipico ad esempio delle risposte alle richieste HTTP.} + poter accorpare quest'ultimo al segmento ACK permette di risparmiare sia in + termini di dati inviati che di velocità di risposta. Per far questo si può + utilizzare \const{TCP\_QUICKACK} impostando un valore logico falso (cioè 0), + in questo modo il kernel attenderà così da inviare il prossimo segmento di + ACK insieme ai primi dati disponibili. + + Si tenga presente che l'opzione non è permanente, vale a dire che una volta + che la si sia impostata a 0 il kernel la riporterà al valore di default dopo + il suo primo utilizzo. Sul lato server la si può impostare anche una volta + sola su un socket in ascolto, ed essa verrà ereditata da tutti i socket che + si otterranno da esso al ritorno di \func{accept}. % TODO trattare con gli esempi di apache -\item[\const{TCP\_CONGESTION}] questa opzione permette di controllare gli - algoritmi usati dal protocollo TCP per la gestione della connessione. É - stata introdotta con il kernel 2.6.13, e non è documentata. +\item[\const{TCP\_CONGESTION}] questa opzione permette di impostare quale + algoritmo per il controllo della congestione\footnote{il controllo della + congestione è un meccanismo previsto dal protocollo TCP (vedi + sez.~\ref{sez:tcp_protocol_xxx}) per evitare di trasmettere inutilmente + dati quando una connessione è congestionata; un buon algoritmo è + fondamentale per il funzionamento del protocollo, dato che i pacchetti + persi andrebbero ritrasmessi, per cui inviare un pacchetto su una linea + congestionata potrebbe causare facilmente un peggioramento della + situazione.} utilizzare per il singolo socket. L'opzione è stata + introdotta con il kernel 2.6.13,\footnote{alla data di stesura di queste + note (Set. 2006) è pure scarsamente documentata, tanto che non è neanche + definita nelle intestazioni delle \acr{glibc} per cui occorre definirla a + mano al suo valore che è 13.} e prende come per \param{optval} il + puntatore ad un buffer contenente il nome dell'algoritmo di controllo che + si vuole usare. + + L'uso di un nome anziché di un valore numerico è dovuto al fatto che gli + algoritmi di controllo della congestione sono realizzati attraverso + altrettanti moduli del kernel, e possono pertanto essere attivati a + richiesta; il nome consente di caricare il rispettivo modulo e di introdurre + moduli aggiuntivi che implementino altri meccanismi. + + Per poter disporre di questa funzionalità occorre aver compilato il kernel + attivando l'opzione di configurazione generale + \texttt{TCP\_CONG\_ADVANCED},\footnote{disponibile come \textit{TCP: + advanced congestion control} nel menù \textit{Network->Networking + options}, che a sua volta renderà disponibile un ulteriore menù con gli + algoritmi presenti.} e poi abilitare i singoli moduli voluti con le varie + \texttt{TCP\_CONG\_*} presenti per i vari algoritmi disponibili; un elenco + di quelli attualmente supportati nella versione ufficiale del kernel è + riportato in tab.~\ref{tab:sock_tcp_congestion_algo}.\footnote{la lista è + presa dalla versione 2.6.17.} + + + Si tenga presente che prima della implementazione modulare alcuni di questi + algoritmi erano disponibili soltanto come caratteristiche generali del + sistema, attivabili per tutti i socket, questo è ancora possibile con la + \textit{sysctl} \texttt{tcp\_congestion\_control} (vedi + sez.~\ref{sec:sock_ipv4_sysctl}) che ha sostituito le precedenti + \textit{sysctl}.\footnote{riportate anche, alla data di stesura di queste + pagine (Set. 2006) nelle pagine di manuale, ma non più presenti.} + + \begin{table}[!htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|l|p{10cm}|} + \hline + \textbf{Nome}&\textbf{Configurazione}&\textbf{Riferimento} \\ + \hline + \hline + reno& -- &algoritmo tradizionale, usato in caso di assenza degli altri.\\ + \texttt{bic} &\texttt{TCP\_CONG\_BIC} & + \href{http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/index.htm} + {\texttt{http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/index.htm}}.\\ + \texttt{cubic} &\texttt{TCP\_CONG\_CUBIC} & + \href{http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/index.htm} + {\texttt{http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/index.htm}}.\\ + \texttt{highspeed}&\texttt{TCP\_CONG\_HSTCP} & + \href{http://www.icir.org/floyd/hstcp.html} + {\texttt{http://www.icir.org/floyd/hstcp.html}}.\\ + \texttt{htcp} &\texttt{TCP\_CONG\_HTCP} & + \href{http://www.hamilton.ie/net/htcp/} + {\texttt{http://www.hamilton.ie/net/htcp/}}.\\ + \texttt{hybla} &\texttt{TCP\_CONG\_HYBLA} & + \href{http://www.danielinux.net/projects.html} + {\texttt{http://www.danielinux.net/projects.html}}.\\ + \texttt{scalable}&\texttt{TCP\_CONG\_SCALABLE}& + \href{http://www.deneholme.net/tom/scalable/} + {\texttt{http://www.deneholme.net/tom/scalable/}}.\\ + \texttt{vegas} &\texttt{TCP\_CONG\_VEGAS} & + \href{http://www.cs.arizona.edu/protocols/} + {\texttt{http://www.cs.arizona.edu/protocols/}}.\\ + \texttt{westwood}&\texttt{TCP\_CONG\_WESTWOOD}& + \href{http://www.cs.ucla.edu/NRL/hpi/tcpw/} + {\texttt{http://www.cs.ucla.edu/NRL/hpi/tcpw/}}.\\ +% \texttt{}&\texttt{}& .\\ + \hline + \end{tabular} + \caption{Gli algoritmi per il controllo della congestione disponibili con + Linux con le relative opzioni di configurazione da attivare.} + \label{tab:sock_tcp_congestion_algo} + \end{table} \end{basedescript} Il protocollo UDP, anche per la sua maggiore semplicità, supporta un numero -ridotto di opzioni, riportate in tab.~\ref{tab:sock_opt_udp}; anche in questo -caso per poterle utilizzare occorrerà impostare l'opportuno valore per +ridotto di opzioni, riportate in tab.~\ref{tab:sock_opt_udplevel}; anche in +questo caso per poterle utilizzare occorrerà impostare l'opportuno valore per l'argomento \param{level}, che è \const{SOL\_UDP} (o l'equivalente \const{IPPROTO\_UDP}). Le costanti che identificano dette opzioni sono definite in \file{netinet/udp.h}, ed accessibili includendo detto @@ -3417,9 +3597,10 @@ sono le seguenti: effettivamente la identifica nelle operazioni a basso livello, il nome dell'interfaccia è soltanto una etichetta associata a detto \textsl{indice}, che permette di rendere più comprensibile l'indicazione dell'interfaccia - all'interno dei comandi; si può ottenere un elenco delle interfacce che - contiene anche il valore del relativo indice usando il comando \cmd{ip - link}. + all'interno dei comandi. Una modalità per ottenere questo valore è usare il + comando \cmd{ip link}, che fornisce un elenco delle interfacce presenti + ordinato in base a tale valore (riportato come primo campo). + \item[\const{SIOCGIFINDEX}] restituisce nel campo \var{ifr\_ifindex} il valore numerico dell'indice dell'interfaccia specificata con \var{ifr\_name}, è in @@ -3487,8 +3668,8 @@ sono le seguenti: \item[\const{SIOCGIFMETRIC}] permette di leggere il valore della metrica del dispositivo associato all'interfaccia specificata nel campo - \var{ifr\_metric}, attualmente non ancora implementato, restituisce sempre 0 - come valore. + \var{ifr\_metric}. Attualmente non è implementato, e l'operazione + restituisce sempre un valore nullo. \item[\const{SIOCSIFMETRIC}] permette di impostare il valore della metrica del dispositivo al valore specificato nel campo \var{ifr\_metric}, attualmente @@ -3572,11 +3753,12 @@ sono le seguenti: \end{basedescript} -Una ulteriore operazione che consente di ricavare le caratteristiche delle -interfacce di rete, che però è disponibile soltanto per socket della famiglia -\const{AF\_INET} (vale ad dire per socket IPv4), è \const{SIOCGIFCONF}. In -questo caso l'utente dovrà passare come argomento una struttura -\struct{ifconf}, definita in fig.~\ref{fig:netdevice_ifconf_struct}. +Una ulteriore operazione, che consente di ricavare le caratteristiche delle +interfacce di rete, è \const{SIOCGIFCONF}; però per ragioni di compatibilità +questa operazione è disponibile soltanto per i socket della famiglia +\const{AF\_INET} (vale ad dire per socket IPv4). In questo caso l'utente dovrà +passare come argomento una struttura \struct{ifconf}, definita in +fig.~\ref{fig:netdevice_ifconf_struct}. \begin{figure}[!htb] \footnotesize \centering @@ -3587,6 +3769,69 @@ questo caso l'utente dovr \label{fig:netdevice_ifconf_struct} \end{figure} +Per eseguire questa operazione occorrerà allocare preventivamente un buffer di +contenente un vettore di strutture \struct{ifreq}. La dimensione (in byte) di +questo buffer deve essere specificata nel campo \var{ifc\_len} di +\struct{ifconf}, mentre il suo indirizzo andrà specificato nel campo +\var{ifc\_req}. Qualora il buffer sia stato allocato come una stringa, il suo +indirizzo potrà essere fornito usando il campo \var{ifc\_buf}.\footnote{si + noti che l'indirizzo del buffer è definito in \struct{ifconf} con una + \ctyp{union}, questo consente di utilizzare una delle due forme a piacere.} + +La funzione restituisce nel buffer indicato una serie di strutture +\struct{ifreq} contenenti nel campo \var{ifr\_name} il nome dell'interfaccia e +nel campo \var{ifr\_addr} il relativo indirizzo IP. Se lo spazio allocato nel +buffer è sufficiente il kernel scriverà una struttura \struct{ifreq} per +ciascuna interfaccia attiva, restituendo nel campo \var{ifc\_len} il totale +dei byte effettivamente scritti. Il valore di ritorno è 0 se l'operazione ha +avuto successo e negativo in caso contrario. + +Si tenga presente che il kernel non scriverà mai sul buffer di uscita dati +eccedenti numero di byte specificato col valore di \var{ifc\_len} impostato +alla chiamata della funzione, troncando il risultato se questi non dovessero +essere sufficienti. Questa condizione non viene segnalata come errore per cui +occorre controllare il valore di \var{ifc\_len} all'uscita della funzione, e +verificare che esso sia inferiore a quello di ingresso. In caso contrario si è +probabilmente\footnote{probabilmente perché si potrebbe essere nella + condizione in cui sono stati usati esattamente quel numero di byte.} avuta +una situazione di troncamento dei dati. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includecodesample{listati/iflist.c} + \end{minipage} + \caption{Il corpo principale del programma \texttt{iflist.c}.} + \label{fig:netdevice_iflist} +\end{figure} + +Come esempio dell'uso di queste funzioni si è riportato in +fig.~\ref{fig:netdevice_iflist} il corpo principale del programma +\texttt{iflist} in cui si utilizza l'operazione \const{SIOCGIFCONF} per +ottenere una lista delle interfacce attive e dei relativi indirizzi. Al solito +il codice completo è fornito nei sorgenti allegati alla guida. + +Il programma inizia (\texttt{\small 7--11}) con la creazione del socket +necessario ad eseguire l'operazione, dopo di che si inizializzano +opportunamente (\texttt{\small 13--14}) i valori della struttura +\struct{ifconf} indicando la dimensione del buffer ed il suo +indirizzo;\footnote{si noti come in questo caso si sia specificato l'indirizzo + usando il campo \var{ifc\_buf}, mentre nel seguito del programma si accederà + ai valori contenuti nel buffer usando \var{ifc\_req}.} si esegue poi +l'operazione invocando \func{ioctl}, controllando come sempre la corretta +esecuzione, ed uscendo in caso di errore (\texttt{\small 15--19}). + +Si esegue poi un controllo sulla quantità di dati restituiti segnalando un +eventuale overflow del buffer (\texttt{\small 21--23}); se invece è tutto a +posto (\texttt{\small 24--27}) si calcola e si stampa a video il numero di +interfacce attive trovate. L'ultima parte del programma (\texttt{\small + 28--33}) è il ciclo sul contenuto delle varie strutture \struct{ifreq} +restituite in cui si estrae (\texttt{\small 30}) l'indirizzo ad esse +assegnato\footnote{si è definito \var{access} come puntatore ad una struttura + di tipo \struct{sockaddr\_in} per poter eseguire un \textit{casting} + dell'indirizzo del valore restituito nei vari campi \var{ifr\_addr}, così + poi da poterlo poi usare come argomento di \func{inet\_ntoa}.} e lo si +stampa (\texttt{\small 31--32}) insieme al nome dell'interfaccia. @@ -3845,8 +4090,8 @@ accessibile con \texttt{man 7 ip}, sono i seguenti: conflitti con le porte usate dai servizi noti. \item[\texttt{ip\_no\_pmtu\_disc}] imposta la disciplina di ricerca della - \textit{Path MTU} (vedi sez.~\ref{sec:net_lim_dim} e - sez.~\ref{sec:sock_ipv4_options}). + \itindex{Maximum~Transfer~Unit} \textit{Path MTU} (vedi + sez.~\ref{sec:net_lim_dim} e sez.~\ref{sec:sock_ipv4_options}). \item[\texttt{ipfrag\_high\_thresh}] limite massimo (espresso in numero di byte) sui pacchetti IP frammentati presenti in coda; quando questo valore @@ -4029,14 +4274,12 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: % LocalWords: intvl probes latency orphans l'ACK SYNQ HSIZE tw buckets mem rfc % LocalWords: orphan reordering collapse sack stdurg synack syncookies recycle % LocalWords: timestamps scaling vegas avoid westwood tcpi l'incapsulazione - - - - +% LocalWords: metric EOPNOTSUPP mtu hwaddr ARPHRD interrupt DMA map qlen silly +% LocalWords: rename ifconf syndrome dell'ACK FTP ACCEPTFILTER advanced reno +% LocalWords: congestion control Networking cubic CUBIC highspeed HSTCP htcp +% LocalWords: HTCP hybla HYBLA scalable SCALABLE ifc req iflist access ntoa %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil" %%% End: -% LocalWords: metric EOPNOTSUPP mtu hwaddr ARPHRD interrupt DMA map qlen -% LocalWords: rename ifconf