|
Per ogni tipo di NIC vi e' un device driver che lo gestisce (ad esempio per la il device NE2000 compatibile oppure per la periferica 3COM 3C59X, ecc.).
Dopo il device a basso livello, Linux chiama SEMPRE la routine di routing ad alto livello "netif_rx [net/core/dev.c]", che controlla:
Vedremo un esempio di quello che accade quando mandamo dobbiamo ricevere un pacchetto TCP, partendo dalla ''netif_rx [net/core/dev.c]'' (in sostanza analizziamo ''a grandi linee'' lo stack TCP/IP di Linux).
|netif_rx |__skb_queue_tail |qlen++ |* Inserimento tramite puntatori nella coda pacchetti* |cpu_raise_softirq |softirq_active(cpu) |= (1 << NET_RX_SOFTIRQ) // settiamo il bit NET_RX_SOFTIRQ nel vettore BH
Una volta che l'interazione IRQ e' terminata, seguiamo cosa accade in fase di scheduling quando si esegue il BH relativo alla rete che abbiamo attivato tramite NET_RX_SOFTIRQ: in pratica andiamo a chiamare la ''net_rx_action [net/core/dev.c]'' come specificato da "net_dev_init [net/core/dev.c]".
|net_rx_action |skb = __skb_dequeue (operazione inversa della __skb_queue_tail) |for (ptype = first_protocol; ptype < max_protocol; ptype++) // Determiniamo |if (skb->protocol == ptype) // qual'e' il protocollo di rete |ptype->func -> ip_rcv // come specificato sulla ''struct ip_packet_type [net/ipv4/ip_output.c]'' **** ADESSO SAPPIAMO CHE IL PACCHETTO E' DI TIPO IP **** |ip_rcv |NF_HOOK (ip_rcv_finish) |ip_route_input // accediamo alla tabella di routing per capire qual e' la funzione da chiamare (qual e' cioe' l'interfaccia) |skb->dst->input -> ip_local_deliver // come da controllo della tabella di routing la destinazione e' la macchina locale |ip_defrag // riassembliamo i frammenti IP |NF_HOOK (ip_local_deliver_finish) |ipprot->handler -> tcp_v4_rcv // come da ''tcp_protocol [include/net/protocol.c]'' **** ADESSO SAPPIAMO CHE IL PACCHETTO E' TCP **** |tcp_v4_rcv |sk = __tcp_v4_lookup |tcp_v4_do_rcv |switch(sk->state) *** Il pacchetto puo' essere mandato al Task tramite il socket aperto *** |case TCP_ESTABLISHED: |tcp_rcv_established |__skb_queue_tail // accoda il pacchetto sul socket |sk->data_ready -> sock_def_readable |wake_up_interruptible *** Dobbiamo gestire il 3-way TCP handshake *** |case TCP_LISTEN: |tcp_v4_hnd_req |tcp_v4_search_req |tcp_check_req |syn_recv_sock -> tcp_v4_syn_recv_sock |__tcp_v4_lookup_established |tcp_rcv_state_process *** 3-Way TCP Handshake *** |switch(sk->state) |case TCP_LISTEN: // Riceviamo il SYN |conn_request -> tcp_v4_conn_request |tcp_v4_send_synack // Mandiamo SYN + ACK |tcp_v4_synq_add // settiamo lo stato SYN |case TCP_SYN_SENT: // riceviamo SYN + ACK |tcp_rcv_synsent_state_process tcp_set_state(TCP_ESTABLISHED) |tcp_send_ack |tcp_transmit_skb |queue_xmit -> ip_queue_xmit |ip_queue_xmit2 |skb->dst->output |case TCP_SYN_RECV: // Riceviamo ACK |if (ACK) |tcp_set_state(TCP_ESTABLISHED)
Descrizione:
SERVER (LISTENING) CLIENT (CONNECTING) SYN <------------------- SYN + ACK -------------------> ACK <------------------- 3-Way TCP handshake
Hosting by: hurra.com
Generated: 2007-01-26 17:56:17