TCP/IP源码学习(24)——tcp_write_xmit

简介:

原文地址:TCP/IP源码学习(24)——tcp_write_xmit 作者:GFree_Wind

本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:gfree.wind@gmail.com
博客:linuxfocus.blog.chinaunix.net
    

昨天把tcp_sendmsg学习完毕,今天开始学习__tcp_push_pending_frames。该函数将所有pending的数据,全部发送出去
  1. void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
  2.              int nonagle)
  3. {
  4.     /* If we are closed, the bytes will have to remain here.
  5.      * In time closedown will finish, we empty the write queue and
  6.      * all will be happy.
  7.      */
  8.     /* 该socket已经关闭,那么直接返回 */
  9.     if (unlikely(sk->sk_state == TCP_CLOSE))
  10.         return;
     /* 发送数据 */
  1.     if (tcp_write_xmit(sk, cur_mss, nonagle, 0, GFP_ATOMIC))
  2.         tcp_check_probe_timer(sk); //发送数据失败,使用probe timer进行检查。
  3. }
下面看函数 tcp_write_xmit
  1. static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
  2.              int push_one, gfp_t gfp)
  3. {
  4.     struct tcp_sock *tp = tcp_sk(sk);
  5.     struct sk_buff *skb;
  6.     unsigned int tso_segs, sent_pkts;
  7.     int cwnd_quota;
  8.     int result;

  9.     sent_pkts = 0;
      /* 检查是不是只发送一个skb buffer,即push one */
  1.     if (!push_one) {
  2.         /* 
  3.         如果要发送多个skb,则需要检测MTU。
  4.         这时会检测MTU,希望MTU可以比之前的大,提高发送效率。
  5.         */
  6.         /* Do MTU probing. */
  7.         result = tcp_mtu_probe(sk);
  8.         if (!result) {
  9.             return 0;
  10.         } else if (result > 0) {
  11.             sent_pkts = 1;
  12.         }
  13.     }
     
     /* 检查是否还有skb要发送 */
  1.     while ((skb = tcp_send_head(sk))) {
  2.         unsigned int limit;
         /* 
         初始化TSO
         关于TSO,参考:http://en.wikipedia.org/wiki/Large_segment_offload
         */
  1.         tso_segs = tcp_init_tso_segs(sk, skb, mss_now);
  2.         BUG_ON(!tso_segs);
          /* 检查congestion windows, 可以发送几个segment */
  1.         cwnd_quota = tcp_cwnd_test(tp, skb);
  2.         if (!cwnd_quota)
  3.             break;
         /* 检查发送窗口,是否可以容纳至少一个segment */
  1.         if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now)))
  2.             break;

  3.         if (tso_segs == 1) {
  4.             /* 根据nagle算法,计算是否需要发送数据 */
  5.             if (unlikely(!tcp_nagle_test(tp, skb, mss_now,
  6.                          (tcp_skb_is_last(sk, skb) ?
  7.                          nonagle : TCP_NAGLE_PUSH))))
  8.                 break;
  9.         } else {
  10.             /* 当不止一个skb时,通过TSO计算是否需要延时发送 */
  11.             if (!push_one && tcp_tso_should_defer(sk, skb))
  12.                 break;
  13.         }

  14.         limit = mss_now;
  15.         /* 在TSO分片大于1的情况下,且TCP不是URG模式。通过MSS计算发送数据的limit */
  16.         if (tso_segs > 1 && !tcp_urg_mode(tp))
  17.             limit = tcp_mss_split_point(sk, skb, mss_now,
  18.                          cwnd_quota);
         /* 当skb的长度大于限制时,需要调用tso_fragment分片 */
  1.         if (skb->len > limit &&
  2.          unlikely(tso_fragment(sk, skb, limit, mss_now, gfp)))
  3.             break;
         /* 更新tcp的时间戳 */
  1.         TCP_SKB_CB(skb)->when = tcp_time_stamp;
         /* 发送skb数据 */
  1.         if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp)))
  2.             break;

  3.         /* Advance the send_head. This one is sent out.
  4.          * This call will increment packets_out.
  5.          */
  6.         /* 更新统计,并启动重传计时器 */
  7.         tcp_event_new_data_sent(sk, skb);

  8.         tcp_minshall_update(tp, mss_now, skb);
  9.         sent_pkts++;

  10.         if (push_one)
  11.             break;
  12.     }

  13.     if (likely(sent_pkts)) {
  14.         tcp_cwnd_validate(sk);
  15.         return 0;
  16.     }
  17.     return !tp->packets_out && tcp_send_head(sk);
  18. }
今天就学到这里。发现TCP的内部机制的复杂度,远胜于UDP。不仅仅是TCP协议所表现的那些,内部机制更为复杂。所以我可能会先再看看资料,把基础打牢,在继续学习tcp/ip的源码了。
目录
相关文章
|
6月前
|
机器学习/深度学习 人工智能 网络协议
TCP/IP五层(或四层)模型,IP和TCP到底在哪层?
TCP/IP五层(或四层)模型,IP和TCP到底在哪层?
113 4
|
监控 网络协议 网络架构
IP协议【图解TCP/IP(笔记九)】
IP协议【图解TCP/IP(笔记九)】
144 0
|
域名解析 网络协议
IP协议, TCP协议 和DNS 服务分别是干什么的?
大家好,我是阿萨。昨天讲解了网络四层协议[TCP/IP协议族分为哪4层?]今天我们学习下IP 协议, TCP 协议和DNS 协议分别是干什么的。
295 0
IP协议, TCP协议 和DNS 服务分别是干什么的?
|
网络协议
ACK的累加规则-wireshark抓包分析-不包含tcp头部、ip头部、数据链路层头部等。
ACK的累加规则-wireshark抓包分析-不包含tcp头部、ip头部、数据链路层头部等。
ACK的累加规则-wireshark抓包分析-不包含tcp头部、ip头部、数据链路层头部等。
|
网络协议 网络架构
六、TCP/IP模型 和 5层参考模型
六、TCP/IP模型 和 5层参考模型
六、TCP/IP模型 和 5层参考模型
|
网络协议
TCP/IP协议族有哪些?
大家好,我是阿萨。昨天我们学习了[URI 和URL 的区别是什么?]了解了URI 和URL的区别。 学习HTTP, 绕不开TCP/IP,那么TCP/IP 协议族分为哪4层?
315 0
TCP/IP协议族有哪些?
|
网络协议 网络性能优化 网络安全
网络协议报文理解刨析篇二(再谈Http和Https), 加上TCP/UDP/IP协议分析(理解着学习), 面试官都惊讶你对网络的见解(2)
网络协议报文理解刨析篇二(再谈Http和Https), 加上TCP/UDP/IP协议分析(理解着学习), 面试官都惊讶你对网络的见解(2)
网络协议报文理解刨析篇二(再谈Http和Https), 加上TCP/UDP/IP协议分析(理解着学习), 面试官都惊讶你对网络的见解(2)
|
域名解析 网络协议 安全
网络协议报文理解刨析篇二(再谈Http和Https), 加上TCP/UDP/IP协议分析(理解着学习), 面试官都惊讶你对网络的见解(1)
网络协议报文理解刨析篇二(再谈Http和Https), 加上TCP/UDP/IP协议分析(理解着学习), 面试官都惊讶你对网络的见解(1)
网络协议报文理解刨析篇二(再谈Http和Https), 加上TCP/UDP/IP协议分析(理解着学习), 面试官都惊讶你对网络的见解(1)
|
网络协议 算法 网络性能优化
网络入门基础模型, 网络大体框架, TCP/IP协议栈, 各种局域网和广域网刨析 (以图解的方式推开网络大门)
网络入门基础模型, 网络大体框架, TCP/IP协议栈, 各种局域网和广域网刨析 (以图解的方式推开网络大门)
网络入门基础模型, 网络大体框架, TCP/IP协议栈, 各种局域网和广域网刨析 (以图解的方式推开网络大门)
|
存储 运维 网络协议
深入浅出:这次终于能把 TCP/IP 协议搞明白了
深入浅出:这次终于能把 TCP/IP 协议搞明白了
深入浅出:这次终于能把 TCP/IP 协议搞明白了