在tcp_ack接收ACK处理函数中,如果确认当前走慢速路径,那么会调用tcp_ack_update_window函数检查窗口是否需要更新并更新之,并且更新未确认数据的位置,即更新窗口左边沿;

  1. static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
  2. {
  3. /* 快速路径&& ack确认了新数据 */
  4. if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
  5. ;
  6. }
  7. /* 慢速路径 */
  8. else {
  9. /* 更新发送窗口 */
  10. flag |= tcp_ack_update_window(sk, skb, ack, ack_seq);
  11. }
  12. }

tcp_ack_update_window执行窗口更新主流程,函数首先根据窗口扩大因子计算实际的窗口大小,然后判断是否需要更新窗口,若需要则对窗口进行更新,注意,只有当窗口不相等的情况下才会实际更新窗口,否则只更新最后一次窗口更新ack序号;窗口更新需要更新窗口,同步MSS,检查是否开启快速路径等;函数最后还将设置未确认数据位置,即窗口左边沿;

  1. /* Update our send window.
  2. *
  3. * Window update algorithm, described in RFC793/RFC1122 (used in linux-2.2
  4. * and in FreeBSD. NetBSD's one is even worse.) is wrong.
  5. */
  6. static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32 ack,
  7. u32 ack_seq)
  8. {
  9. struct tcp_sock *tp = tcp_sk(sk);
  10. int flag = ;
  11. u32 nwin = ntohs(tcp_hdr(skb)->window);
  12.  
  13. /* 根据扩大因子计算窗口大小 */
  14. if (likely(!tcp_hdr(skb)->syn))
  15. nwin <<= tp->rx_opt.snd_wscale;
  16.  
  17. /* 需要更新窗口的话 */
  18. if (tcp_may_update_window(tp, ack, ack_seq, nwin)) {
  19. /* 窗口更新标记 */
  20. flag |= FLAG_WIN_UPDATE;
  21.  
  22. /* 记录窗口更新的ack序号 */
  23. tcp_update_wl(tp, ack_seq);
  24.  
  25. /* 发送窗口与通告窗口不等时 */
  26. if (tp->snd_wnd != nwin) {
  27.  
  28. /* 更新发送窗口*/
  29. tp->snd_wnd = nwin;
  30.  
  31. /* Note, it is the only place, where
  32. * fast path is recovered for sending TCP.
  33. */
  34. /* 判断是否开启快路标志 */
  35. tp->pred_flags = ;
  36. tcp_fast_path_check(sk);
  37.  
  38. /* 有数据要发送 */
  39. if (tcp_send_head(sk))
  40. tcp_slow_start_after_idle_check(sk);
  41.  
  42. /* 窗口大于以前记录的最大窗口 */
  43. if (nwin > tp->max_window) {
  44. /* 更新最大窗口 */
  45. tp->max_window = nwin;
  46. /* 更新mss */
  47. tcp_sync_mss(sk, inet_csk(sk)->icsk_pmtu_cookie);
  48. }
  49. }
  50. }
  51.  
  52. /* 更新未确认的数据位置,即窗口左边沿 */
  53. tcp_snd_una_update(tp, ack);
  54.  
  55. return flag;
  56. }

tcp_may_update_window用于判断窗口是否需要更新,满足以下条件之一则更新:

(1) ACK确认了新的数据;

(2) 未满足(1),ACK未确认数据,通过上面snd_una<=ack的条件,此时只能是snd_una=ack,即未确认新数据,是个重复ack,但是这个ack的序号比之前更新窗口的序号要新,则需要更新snd_wl1;

(3) 未满足(1)(2),未确认数据,ack需要也未更新,但是窗口有所改变,则说明单单发送了一个窗口更新通知;

  1. /* Check that window update is acceptable.
  2. * The function assumes that snd_una<=ack<=snd_next.
  3. */
  4. static inline bool tcp_may_update_window(const struct tcp_sock *tp,
  5. const u32 ack, const u32 ack_seq,
  6. const u32 nwin)
  7. {
  8. /*
  9. 更新条件
  10. ack确认序号确认了数据,意味着窗口要收缩
  11. ack确认序号未确认新数据,ack序号比上一个更新窗口ack序号要新
  12. ack序号与上一个更新装ack序号一致,但是窗口比以前的窗口大
  13. */
  14. return after(ack, tp->snd_una) ||
  15. after(ack_seq, tp->snd_wl1) ||
  16. (ack_seq == tp->snd_wl1 && nwin > tp->snd_wnd);
  17. }

TCP发送窗口更新tcp_ack_update_window的更多相关文章

  1. TCP滑动窗口协议

    TCP的首部中​有一个很重要的字段就是16位长的窗口大小,它出现在每一个TCP数据报中,配合32位的确认序号,用于向对端通告本地socket的接收窗口大小.也就是说,如果本地socket发送一个TCP ...

  2. 彻底搞通TCP滑动窗口

    在我们当初学习网络编程的时候,都接触过TCP,在TCP中,对于数据传输有各种策略,比如滑动窗口.拥塞窗口机制,又比如慢启动.快速恢复.拥塞避免等.通过本文,我们将了解滑动窗口在TCP中是如何使用的. ...

  3. TCP滑动窗口(发送窗口和接受窗口)

    TCP窗口机制 TCP header中有一个Window Size字段,它其实是指接收端的窗口,即接收窗口.用来告知发送端自己所能接收的数据量,从而达到一部分流控的目的. 其实TCP在整个发送过程中, ...

  4. TCP 滑动窗口和 拥塞窗口

    转http://coolshell.cn/articles/11609.html 滑动窗口 -- 表征发送端和接收端的接收能力 拥塞窗口-- 表征中间设备的传输能力 TCP滑动窗口 需要说明一下,如果 ...

  5. TCP 滑动窗口

    滑动窗口协议 流量控制方法 PUSH 慢启动   隔一个报文段确认"的策略实际就是因为 delayed ack,同时接收到两个待确认的ACK包时,就立即发送确认包.   滑动窗口实例   解 ...

  6. TCP发送源码学习(2)--tcp_write_xmit

    一.tcp_write_xmit()将发送队列上的SBK发送出去,返回值为0表示发送成功.函数执行过程如下:1.检测拥塞窗口的大小.2.检测当前报文是否完全处在发送窗口内.3.检测报文是否使用nagl ...

  7. TCP发送源码学习(1)--tcp_sendmsg

    一.tcp_sendmsg()函数分析: int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t ...

  8. TCP 接收窗口自动调节

    https://technet.microsoft.com/zh-cn/magazine/2007.01.cableguy.aspx 欢迎来到 TechNet 杂志“网络专家”的第一部分.TechNe ...

  9. TCP 三次握手四次挥手, ack 报文的大小.tcp和udp的不同之处、tcp如何保证可靠的、tcp滑动窗口解释

    一.TCP三次握手和四次挥手,ACK报文的大小 首先连接需要三次握手,释放连接需要四次挥手 然后看一下连接的具体请求: [注意]中断连接端可以是Client端,也可以是Server端. [注意] 在T ...

随机推荐

  1. JQuery --- 第六期 (Ajax)

    欢迎访问我的个人博客,获取更多有用的东西 链接一 链接二 也可以关注我的微信订阅号:CN丶Moti 点击查看Ajax

  2. Linux学习笔记:7个ssh命令用法

    通过远程控制管理多台服务器. 远程工具:telnet.ssh.vnc ssh采用密文的传输方式,简单安全.Secure Shell 缩写 SSH. 1.基本用法 ssh 192.168.1.1 默认使 ...

  3. Java并发编程——线程的基本概念和创建

    一.线程的基本概念: 1.什么是进程.什么是是线程.多线程? 进程:一个正在运行的程序(程序进入内存运行就变成了一个进程).比如QQ程序就是一个进程. 线程:线程是进程中的一个执行单元,负责当前进程中 ...

  4. (转)Java垃圾回收基本过程

    本编博客内容来自oschina,是一篇译文,文中图片比较直观的介绍了JVM进行垃圾回收的过程.原文内容来自oracle官网:Java Garbage Collection Basics oschina ...

  5. 工控漏洞利用框架 - ISF(Industrial Security Framework)

    一. 框架介绍 本框架主要使用Python语言开发,通过集成ShadowBroker释放的NSA工具Fuzzbunch攻击框架,开发一款适合工控漏洞利用的框架.由于Fuzzbunch攻击框架仅适用于P ...

  6. MyEclipse基本配置及优化【MyEclipse_10.7】

    MyEclipse基本配置 MyEclipse所有的配置都是基于工作空间的,当换了个工作空间,之前的所有配置信息就失效了.(建议每次换工作空间之前就配置好基本信息) 1.修改工作空间编码为UTF-8 ...

  7. Java入门 异常处理

    Java入门 异常处理 1.处理异常(try-catch以及try-catch-finally): a)try会抛出很多种类型的异常-多重catch块的处理 eg:try{ //一些会抛出异常的方法 ...

  8. zabbix 3.2.2 agent端(源码包)安装部署 (二)

    一.zabbix agent 端安装部署 1.创建zabbix用户和组 # groupadd zabbix # useradd -g zabbix zabbix -s /sbin/nologin 2. ...

  9. Spring mvc 初始化过程

    1.DispatcherServlet:获取servlet的name 2.XmlWebApplicationContext:获取contentConfigLocation的xml名称和namespac ...

  10. BPTT

    RNN 的 BP —— Back Propagation Through Time. 参考:零基础入门深度学习(5) - 循环神经网络.知乎. 1 def backward(self, sensiti ...