Linux2.6 Core Stack Series--TCP Protocol 1. Send

Source: Internet
Author: User
Tags error handling goto

Before we introduce the TCP send function, we need to introduce a very important structure sk_buff, in Linux, the Sk_buff structure represents a message:

Then see the Send function source code, here is not concerned about the decentralized-aggregation of hardware support:

/* SENDMSG system call implementation in TCP layer */int tcp_sendmsg (struct KIOCB *iocb, struct sock *sk, struct MSGHDR *msg,size_t size) {struct IOVEC *iov;struct Tcp_sock *TP = Tcp_sk (SK); struct Sk_buff *skb;/* a message */int Iovlen, Flags;int mss_now;int err, Copied;long time O;/* Gets the lock */lock_sock (SK) of the socket interface; Tcp_check_timer (SK);/* Calculate blocking timeout based on flag */flags = Msg->msg_flags;timeo = Sock_sndtimeo (SK, Flags & msg_dontwait);/* Wait for a connection to finish. */if ((1 << sk->sk_state) & ~ (tcpf_established | tcpf_close_wait)/* Only these two states can send Message */if ((err = Sk_stream_wait_connect (SK, &timeo))! = 0)/* Wait for the connection to be properly established in other states, and error handling when timed out * /goto out_err;/* This should is in poll */clear_bit (Sock_async_nospace, &sk->sk_socket->flags);/* Get a valid MSS, If OOB is supported, then TSO,MSS is not supported and should be a smaller value */mss_now = TCP_CURRENT_MSS (SK,!) ( Flags&msg_oob));/* Ok commence sending. *//* gets the array pointer to send buffer and its length */iovlen = Msg->msg_iovlen;iov = msg->msg_iov;/* copied indicates the number of bytes copied from the user data block to the SKB. */copied = 0;err =-epipe;/* If there is an error in the socket, it is not allowed to send data, return epipe error */if (Sk->sk_err | | (Sk->sk_shutdown & Send_shutdown)) Goto Do_error;while (--iovlen >= 0) {/* handles all data blocks to be sent *//* pointers and lengths to fragment buffers */int Seglen = iov->iov_len;unsigned Char __user *from = iov->iov_base;iov++;while (Seglen > 0) {/* processes all data in a single data block */int copy;/* the previous sk_buff pointer of the transmit queue, The purpose of this sub-paragraph is to check if the transmission queue has an unfinished segment and the current segment length is less than 1MSS. A new data fragment can be generated only if the existing segment is full load */SKB = sk->sk_write_queue.prev;/* queue is a doubly linked list that accesses the last segment of the socket through the prev of the queue header. First, check if the transmission queue header has data fragmentation, and if the value is null, there is no need to check for sub-full fragmentation. */if (!sk->sk_send_head | | /* The Send queue is empty, the previously obtained SKB is invalid *//* if SKB is valid, but it has no extra space to copy the new data */(copy = Mss_now-skb->len) <= 0) {/* Create a new segment for user data */new_s egment:/* the data length in the Send queue reaches the upper limit of the send buffer, waiting for buffer */if (!sk_stream_memory_free (SK)) Goto wait_for_sndbuf;/* If there is enough memory, Allocates a new buffer for TCP data fragmentation. If the hardware supports scatter-gather technology, allocate a buffer of data page size. Otherwise, allocate a buffer of size 1MSS.  */SKB = SK_STREAM_ALLOC_PSKB (SK, Select_size (SK, TP), 0, sk->sk_allocation);/* Assigning a new SKB *//* allocation failure, indicating insufficient system memory, waiting for memory release */if (!SKB) Goto wait_for_memory;/* Determines whether the checksum */if is performed by hardware based on the characteristics of the routed network device (Sk->sk_route_caps & (Netif_f_ip_csum |Netif_f_no_csum | netif_f_hw_csum)) skb->ip_summed = Checksum_hw;skb_entail (SK, TP, SKB);/* Add SKB new segment to send queue trailer */copy = mss_now;/* The amount of data that needs to be replicated is MSS */}/* the length of the data to be copied cannot be greater than the remaining length of the current segment, and the subtraction of Seglen is below. */if (Copy > Seglen) copy = seglen;/* SKB linear Storage Bottom There is also space */if (Skb_tailroom (SKB) > 0) {/* This time only copies the amount of data remaining at the bottom of the SKB storage */if (c opy > Skb_tailroom (SKB)) copy = Skb_tailroom (SKB);/* Copy the specified length of data from the user space into SKB, and if it fails, exit */if (err = Skb_add_data (SKB, from, copy))! = 0) goto Do_fault;} /* There is no space at the bottom of the linear store, copy to the scatter/aggregate store */else {...//ignore}if (!copied)/* If no data is copied, cancel PSH flag */TCP_SKB_CB (SKB)->flags &= ~tcpcb_flag_psh;/* update send queue last packet ordinal */tp->write_seq + = copy;/* Updates the ending ordinal of the current data fragment SKB so that it can include all the sequences covered by the current segment. */TCP_SKB_CB (SKB)->end_seq + = Copy;skb_shinfo (SKB)->tso_segs = 0;/* Update the data copy pointer to the next data start location to be copied, and then update the number of bytes to replicate. */from + = copy;copied + = copy;/* If all the data has been copied out, it will call Tcp_push () to send data fragments from the transmission queue. */if ((Seglen-= copy) = = 0 && iovlen = 0) goto out;/* go here to show that the full user buffer has not beenCopy to the socket buffer and check that if the data in the current SKB is less than MSS, you can continue copying the data inside. Or the OOB data is sent, you also skip the Send process and continue copying the data */if (skb->len! = Mss_now | | (Flags & Msg_oob)) continue;/* This indicates that the current data segment is full. Call Foced_push () to check whether the mandatory push flag is set for the last segment in the transmission queue. If you set the force push flag, you need to tell the receiving application to process the data first. Data must be sent immediately, that is, the data generated after the last send has exceeded half of the advertised window value */if (Forced_push (TP)) {/* Set PSH flag after sending data */tcp_mark_push (TP, SKB);/* Then according to Nagle algorithm, congestion window , the Send window calls this function to initiate the transfer of the segment to be sent. */__tcp_push_pending_frames (SK, TP, Mss_now, Tcp_nagle_push);} /* Although it is not necessary to send the data, there is only the current segment on the Send queue, and it is sent out *//* if the data cannot be forced to push and there is only one data segment in the transmission queue, call Tcp_push_one () to push the data segment to the transmission queue. */else if (SKB = = sk->sk_send_head) tcp_push_one (SK, Mss_now);/* Then fragment the remaining data in the inner loop iteration. */continue;wait_for_sndbuf:/* Waiting for */set_bit (Sock_nospace, &sk->sk_socket->flags) due to the full cause of the sending queue; wait_for_ Memory:if (copied)/* Although there is no memory, but this call copied the data to the buffer, call Tcp_push send it out */tcp_push (SK, TP, Flags & ~msg_more, Mss_now, Tcp_ Nagle_push);/* Wait for memory available */if (err = sk_stream_wait_memory (SK, &timeo))! = 0) Goto do_error;/* does not have memory, timeout after returning failure *//* sleep after M SS may have changed, recalculate */mss_now =TCP_CURRENT_MSS (SK,! ( Flags&msg_oob));}} Out:if (copied)/* Copies the data from the user state, sends it */tcp_push (SK, TP, flags, Mss_now, tp->nonagle); Tcp_check_timer (SK), Release_sock (SK);/* Release lock returned */return copied;do_fault:if (!skb->len) {/* Copy data failed, if SKB length is 0, Description is newly assigned, release it */if (sk->sk_send_head = = SKB)/* If SKB is the Send queue header, empty the queue header */sk->sk_send_head = Null;__skb_unlink (SKB, skb-& gt;list); SK_STREAM_FREE_SKB (SK, SKB);/* Release SKB */}do_error:if (copied) goto Out;out_err:err = Sk_stream_error (SK, Flags, ERR); Tcp_check_timer (SK); Release_sock (SK); return err;}

See note for detailed explanations.

Note the main processes:

1.TCP sends the data in 1MSS as a unit, the maximum segment size is based on the MTU calculation, the MTU is a feature parameter of the link layer, and can be obtained from TCP_CURRENT_MSS ().

2.SK_STREAM_ALLOC_PSKB () Allocates a new buffer for TCP data with a minimum length of 1MSS.

3.skb_entail () sends messages to the transmit buffer queue and calculates the allocated buffers memory.

4.tcp_push_one () is responsible for transmitting a data segment in the Write queue. __tcp_push_pending_frames () is responsible for transmitting multiple segments of data that are queued in the write queue.

Linux2.6 Core Stack Series--TCP Protocol 1. Send

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.