Linux kernel Analysis

Source: Internet
Author: User
Tags goto socket linux

Kernel version: 2.6.34

UDP packet Reception

The reception of UDP message can be divided into two parts: the protocol stack receives the UDP message, inserts the corresponding queue; the user calls Recvfrom () or recv () system call to take out the message from the queue, the queue here is Sk->sk_receive_queue, it is the link of message relay , the two-part contact is shown in the following figure.

The first part: How the protocol stack collects UDP packets.

The UDP module is registered in Inet_init (), and when a UDP message is received, the handler function Udp_rcv () in Udp_protocol is called.

if (Inet_add_protocol (&udp_protocol, IPPROTO_UDP) < 0)     
 PRINTK (kern_crit "inet_init:cannot add UDP protocol\ n ");

UDP_RCV ()-> __UDP4_LIB_RCV () completes the UDP packet reception, initializes the UDP checksum and does not verify the correctness of the checksum.

If 

(Udp4_csum_init (SKB, uh, proto))     
 goto Csum_error;

In the udptable of sockets in the [Saddr, Sport, DADDR, Dport] to find the corresponding SK, in the previous article has detailed said "SK Lookup", where the source port of the message is equivalent to the source host port, the Dest destination port equivalent to the local port.

SK = __UDP4_LIB_LOOKUP_SKB (SKB, Uh->source, Uh->dest, udptable);

If there is a corresponding SK in the udptable, that is, a socket is received, the message is SKB into the queue through UDP_QUEUE_RCV_SKB (), the function is analyzed later, in short, the message will be placed on the sk->sk_receive_queue queue, Then Sock_put () reduces the reference calculation of SK and returns. The completion of the subsequent receive work will depend on the user's actions.

if (SK!= NULL) {     
 int ret = UDP_QUEUE_RCV_SKB (SK, SKB);     
 Sock_put (SK);     
if (Ret > 0)     
  return-ret;     
 return 0;     
}

When the SK is not found in the udptable, then the machine does not have a socket will receive it, so to send ICMP unreachable message, before this, but also verify checksum udp_lib_checksum_complete (), if checksum error, then directly discard the message If the checksum is correct, the statistics in the MIB are increased, the ICMP Port unreachable message is sent, and the message is discarded.

if (Udp_lib_checksum_complete (SKB))     
 goto Csum_error;     
UDP_INC_STATS_BH (NET, udp_mib_noports, proto = = Ipproto_udplite);     
Icmp_send (SKB, Icmp_dest_unreach, Icmp_port_unreach, 0);     
KFREE_SKB (SKB);

UDP_QUEUE_RCV_SKB () packet into queue

Sock_woned_by_user () to determine the value of sk->sk_lock.owned, if equal to 1, means that SK is in the occupied state, at this time can not add SKB to the SK receive queue, execute else if part, Sk_add_backlog () Add SKB to the Sk->sk_backlog queue; if it equals 0, the SK is not occupied, the if part is executed, and __UDP_QUEUE_RCV_SKB () adds SKB to the Sk->sk_receive_queue queue.

Bh_lock_sock (SK);     
if (!sock_owned_by_user (SK))     
 rc = __UDP_QUEUE_RCV_SKB (SK, SKB);     
else if (Sk_add_backlog (SK, SKB)) {     
 bh_unlock_sock (SK);     
 goto drop;     
}     
Bh_unlock_sock (SK);

So when will SK be occupied? When did the SKB on the sk->sk_backlog be handled?

When creating a socket, Sys_socket ()-> inet_create ()-> sk_alloc ()-> sock_lock_init ()-> () Initialize Sk->sk_lock_owned=0.

For example, when the socket is destroyed, Udp_destroy_sock () will call the Lock_sock () on the SK plus lock, after the operation, call Release_sock () to the SK unlock.

void Udp_destroy_sock (struct sock *sk)     
{     
 lock_sock (SK);     
 Udp_flush_pending_frames (SK);
 Release_sock (SK);     
}

In fact, Lock_sock () sets the sk->sk_lock.owned=1; and Release_sock () sets Sk->sk_lock.owned=0 and processes the messages on the Sk_backlog queue Release_ Sock ()-> __release_sock (), for each message on the Sk_backlog queue, invokes SK_BACKLOG_RCV ()-> SK->SK_BACKLOG_RCV (). Also in the creation of the socket, SK->SK_BACKLOG_RCV = SK->SK_PROT->BACKLOG_RCV () is the __UDP_QUEUE_RCV_SKB (), the function of which has been mentioned above, Add the SKB to the sk_receive_queue so that all the messages on the Sk_backlog are transferred to the Sk_receive_queue. In short, the function of the Sk_backlog queue is that the lock times text is temporarily stored here, and when unlocked, the message moves to the Sk_receive_queue queue.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.