Sabtu, 06 Februari 2010

Post Interrupt management: "net_rx_action"

We'll see now an example of what happens when we send a TCP packet to Linux, starting from ''netif_rx [net/core/dev.c]'' call.

===============================================
|netif_rx
|__skb_queue_tail
|qlen++
|* simple pointer insertion *
|cpu_raise_softirq
|softirq_active(cpu) |= (1 << NET_RX_SOFTIRQ) // set bit NET_RX_SOFTIRQ in the BH vector

==========================================================

Once IRQ interaction is ended, we need to follow the next part of the frame life and examine what NET_RX_SOFTIRQ does.
We will next call ''net_rx_action [net/core/dev.c]'' according to "net_dev_init [net/core/dev.c]".

===================================================================
|net_rx_action
|skb = __skb_dequeue (the exact opposite of __skb_queue_tail)
|for (ptype = first_protocol; ptype < max_protocol; ptype++) // Determine
|if (skb->protocol == ptype) // what is the network protocol
|ptype->func -> ip_rcv // according to ''struct ip_packet_type [net/ipv4/ip_output.c]''

**** NOW WE KNOW THAT PACKET IS IP ****
|ip_rcv
|NF_HOOK (ip_rcv_finish)
|ip_route_input // search from routing table to determine function to call
|skb->dst->input -> ip_local_deliver // according to previous routing table check, destination is local machine
|ip_defrag // reassembles IP fragments
|NF_HOOK (ip_local_deliver_finish)
|ipprot->handler -> tcp_v4_rcv // according to ''tcp_protocol [include/net/protocol.c]''

**** NOW WE KNOW THAT PACKET IS TCP ****
|tcp_v4_rcv
|sk = __tcp_v4_lookup
|tcp_v4_do_rcv
|switch(sk->state)

*** Packet can be sent to the task which uses relative socket ***
|case TCP_ESTABLISHED:
|tcp_rcv_established
|__skb_queue_tail // enqueue packet to socket
|sk->data_ready -> sock_def_readable
|wake_up_interruptible


*** Packet has still to be handshaked by 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: // We received SYN
|conn_request -> tcp_v4_conn_request
|tcp_v4_send_synack // Send SYN + ACK
|tcp_v4_synq_add // set SYN state
|case TCP_SYN_SENT: // we received 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: // We received ACK
|if (ACK)
|tcp_set_state(TCP_ESTABLISHED)

==================================================================================

Description:

* First we determine protocol type (IP, then TCP)
* NF_HOOK (function) is a wrapper routine that first manages the network filter (for example firewall), then it calls ''function''.
* After we manage 3-way TCP Handshake which consists of:

SERVER (LISTENING) CLIENT (CONNECTING)
SYN
<-------------------


SYN + ACK
------------------->


ACK
<-------------------

3-Way TCP handshake

NB: In the end we only have to launch "tcp_rcv_established [net/ipv4/tcp_input.c]" which gives the packet to the user socket and wakes it up.

Tidak ada komentar:

Posting Komentar