上篇文章中我们主要说明如何skip到一个SACK块对应的开始段,如何walk这个SACK块包含的段,而没有涉及到

如何标志一个段的记分牌。37版本把给一个段打标志的内容独立出来,这就是tcp_sacktag_one()。

本文主要内容:tcp_sacktag_one(),给一个段打上标志。

Author:zhangskd @ csdn

标志一个包

tcp_sacktag_walk()用于遍历块中的数据包,最终会调用tcp_sacktag_one()来标志一个数据包的记分牌,

即TCP_SKB_CB(skb)->sacked。

记分牌有哪些标志呢?

#define TCPCB_SACKED_ACKED 0x01 /* SKB ACK'd by a SACK block, 标志S */

#define TCPCB_SACKED_RETRANS 0x02 /* SKB retransmitted,标志R */

#define TCPCB_LOST 0x04 /* SKB is lot,标志L */

#define TCPCB_TAGBITS 0x07 /* All tag bits,标志位掩码 */

#define TCPCB_EVER_RETRANS 0x08 /* Ever retransmitted frame,曾经重传过 */

#define TCPCB_RETRANS (TCPCB_SACKED_RETRANS | TCPCB_EVER_RETRANS)

以上标志的说明如下:

We have three tag bits: SACKED(S)、RETRANS(R) and LOST(L).

Packets in queue with these bits set are counted in variables sacked_out、retrans_out and lost_out.

tag标志可能的6种情况:

Tag        InFlight        Description

0             1                   orig segment is in flight,正常情况

S             0                   nothing flies, orig reached receiver.

L              0                  nothing flies, orig lost by net.

R             2                  both orig and retransmit is in flight.

L|R          1                  orig is lost, retransmit is in flight.

S|R          1                  orig reached receiver, retrans is still in flight.

(L|S|R is logically valid, it could occur when L|R is sacked, but it is equivalent to plain S and code

short-curcuits it to S.

L|S is logically invalid, it would mean -1 packet in flight.

以上6种情况是由以下事件触发的:

These 6 states form finite state machine, controlled by the following events:

1. New ACK (+SACK) arrives. (tcp_sacktag_write_queue())

2. Retransmission. (tcp_retransmit_skb(), tcp_xmit_retransmit_queue())

3. Loss detection event of one of three flavors:

A. Scoreboard estimator decided the packet is lost.

A'. Reno "three dupacks" marks head of queue lost.

A''. Its FACK modification, head until snd.fack is lost.

B. SACK arrives sacking data retransmitted after never retransmitted hole was sent out.

C. SACK arrives sacking SND.NXT at the moment, when the segment was retransmitted.

4. D-SACK added new rule: D-SACK changes any tag to S.

static u8 tcp_sacktag_one(struct sk_buff *skb, struct sock *sk,
struct tcp_sacktag_state *state, int dup_sack, int pcount)
{
struct tcp_sock *tp = tcp_sk(sk);
u8 sacked = TCP_SKB_CB(skb)->sacked;
int fack_count = state->fack_count;
/* Account D-SACK for retransmitted packet.
* 如果此skb属于DSACK块,且skb被重传过。即此前tag为R、或者R|S。
*/
if (dup_sack && (sacked & TCPCB_RETRANS)) {
/* 位于上次进入Recovery或Loss之后 */
if (after(TCP_SKB_CB(skb)->end_seq, tp->undo_marker))
tp->undo_retrans--; /* 如果减为0,那么说明之前重传都是不必要的,进行拥塞控制调整撤销 */
if (sacked & TCPCB_SACKED_ACKED) /* 如果这个包已经被SACK过,那么说明是乱序 */
state->reord = min(fack_count, state->reord); /* 更新乱序队列的起始点 */
}
/* Nothing to do; acked frame is about to be dropped (was ACKed).
* 这个skb已经被正常确认了,不用再处理了,它即将被丢弃。
*/
if (! after(TCP_SKB_CB(skb)->end_seq, tp->snd_una))
return sacked;
/* 如果skb还没有被SACK,那么进行处理 */
if (! (sacked & TCPCB_SACKED_ACKED)) {
/* 有R标志,表示被重传过 */
if (sacked & TCPCB_SACKED_RETRANS) {
/* If the segment is not tagged as lost, we do not clear RETRANS, believing
* that retransmission is still in flight.
* 如果之前的标志是:R | L,那么好,现在收到包了,可以清除R和L。
* 如果之前的标志是:R,那么认为现在收到的是orig,重传包还在路上,所以不用干活:)
*/
if (sacked & TCPCB_LOST) {
sacked &= ~(TCPCB_LOST | TCPCB_SACKED_RETRANS); /* 取消L和R标志 */
tp->lost_out -= pcount; /* 更新LOST包个数 */
tp->retrans_out -= pcount; /* 更新RETRANS包个数 */
}
} else { /* 没有R标志 */
if (! (sacked & TCPCB_RETRANS)) {
/* New sack for not retransmitted frame, which was in hole. It is reordering.
* 如果一个包落在highest_sack之前,它即没被SACK过,也不是重传的,那么
* 它肯定是乱序了,到现在才被SACK。
*/
if (before(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp)))
state->reord = min(fack_count, state->reord); /* 记录乱序的起始位置 */
/* SACK enhanced F-RTO (RFC4138; Appendix B) */
if (! after(TCP_SKB_CB(skb)->end_seq, tp->frto_highmark))
state->flag |= FLAG_ONLY_ORIG_SACKED; /* SACKs only non-rexmit sent before RTO */
}
/* 如果它有LOST标志,既然收到了,那么要撤销了 */
if (sacked & TCPCB_LOST) {
sacked &= ~TCPCB_LOST; /* 撤销LOST标志 */
tp->lost_out -= pcount; /* 更新LOST包个数 */
}
}
sacked |= TCPCB_SACKED_ACKED; /* 给skb打上SACK标志,就是这里:) */
state->flag |= FLAG_DATA_SACKED;
tp->sacked_out += pcount; /* 更新SACK包个数 */
fack_count += pcount; /* fackets_out =sacked_out + lost_out,也跟着更新 */
/* 没有使用FACK时 */
if (! tcp_is_fack(tp) && (tp->lost_skb_hint != NULL) &&
before(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(tp->lost_skb_hint)->seq))
tp->lost_cnt_hint += pcount;
if (fack_count > tp->fackets_out)
tp->fackets_out = fack_count; /* 更新tp->fackets_out */
}
/* D-SACK. We can detect redundant retransmission in S|R and plain R frames and clear it.
* undo_retrans is decreased above, L|R frames are accounted above as well.
* 如果skb被D-SACK,并且它的重传标志还未被清除,那么现在清除。
*/
if (dup_sack && (sacked & TCPCB_SACKED_RETRANS)) {
sacked &= ~TCPCB_SACKED_RETRANS; /* 清除重传标志 */
tp->retrans_out -= pcount; /* 更新重传包个数 */
}
return sacked; /* 返回此skb的记分牌 */
}

TCP的核心系列 — SACK和DSACK的实现(六)相关推荐

  1. TCP的核心系列 — ACK的处理(二)

    本文主要内容:tcp_ack()中的一些细节,如发送窗口的更新.持续定时器等. 内核版本:3.2.12 Author:zhangskd @ csdn 发送窗口的更新 什么时候需要更新发送窗口呢? (1 ...

  2. TCP的核心系列 — 重传队列的更新和时延的采样(二)

    在tcp_clean_rtx_queue()中,并非对每个ACK都进行时延采样.是否进行时延采样,跟这个ACK是否为 重复的ACK.这个ACK是否确认了重传包,以及是否使用时间戳选项都有关系. 本文主 ...

  3. 以太网 TCP协议交互过程中出现丢包时的解决机制,超时重传、快速重传、SACK与DSACK

    2.7.3 以太网 TCP协议(TCP交互过程中出现丢包时的解决机制-列举部分) 参考:CSDN_TCP的重传机制_博主.Pr Young,对描述进行了整理与结合个人的理解进行编写. 一.超时重传机制 ...

  4. 企业经营私域运营的三大核心系列直播课

    摩天,用友旗下社会化的企业数智化学习认证社区,提供数智营销.智慧医疗.数智金融.智能制造.项目管理等精品课程,数智化人才上摩天!https://mot.yonyou.com/ #企业经营私域运营的三大 ...

  5. Spring核心系列之ApplicationContext

    Spring核心系列之ApplicationContext Hello,大家好,今天开始,小弟准备推出Spring系列的博客,希望大家喜欢.关于Spring其实我就不用再多介绍了,做过Web开发的,基 ...

  6. TCP 的那些事 | SACK

    在文章<TCP 的那些事 | 快速重传>中介绍了基本的重传知识及快速重传,本文讲解相比快速重传更有效的另一种重传方式:SACK(Selective Acknowledgment). SAC ...

  7. 《Microduino实战》——2.3 Microduino STM32核心系列

    本节书摘来自华章出版社<Microduino实战>一 书中的第2章,第2.3节,作者:姚琪 杨立斌,更多章节内容可以访问云栖社区"华章计算机"公众号查看. 2.3 Mi ...

  8. 或许,这是你见过最全的TCP+UDP图解系列

    或许,这是你见过最全的TCP+UDP图解系列 01 图解TCP TCP首部 流量控制 拥塞控制 三次握手,四次挥手 tcp 怎样保证数据正确性? 流量控制是为了让接收方能来得及接收,而拥塞控制是为了降 ...

  9. 遗言 - MQTT 核心系列:第九章

    遗言 - MQTT 核心系列:第九章 欢迎来到MQTT核心系列的第九章.这个系列一共有十章,用来介绍MQTT的核心特性和概念.在这一章,我们将讲解MQTT中的遗言特性. 因为MQTT会运行在网络不好的 ...

最新文章

  1. 13000行代码、19大技术,这位16岁高中生用C++从头到尾构建了一个机器学习库!...
  2. Docker fence
  3. mybatis-plus 错误java.lang.NoClassDefFoundError: org/apache/velocity/context/Context
  4. 理解 Linux 中 `ls` 的输出
  5. IIS负载均衡(转)
  6. SAP License:SAP S/4HANA就是答案
  7. 如何把catia完全卸载干净_catia软件无法卸载怎么办?彻底删除catia等三维软件的方法...
  8. 基数排序(稍微困难)
  9. Delphi 3D Glscene安装
  10. 用漫画让你彻底搞懂 Linux 内核到底长啥样!
  11. Xamarin iOS教程之使用按钮接接收用户输入
  12. oracle 11g数据库安装教程
  13. 苹果电脑更改sd卡只读_SD内存卡禁止写入只读怎么办?另类SPI模式修复坏卡
  14. Defcon - 2015 - 初赛 - r0pbaby writeup
  15. word,ppt等office文档转化为pdf进行展示(POI + iText)(亲测有效)
  16. 写在2020年尾的一点感悟:回朕车以复路兮,及行迷之未远
  17. -bash: lsb_release: 未找到命令
  18. jpg、jpeg、png、gif、bmp、tiff、ai、cdr、eps 图片格式的区别
  19. C++:char数组初始化
  20. Serpent.AI - 游戏代理框架(Python)

热门文章

  1. opengl对图像进行腐蚀和膨胀
  2. UltraEdit for Mac 18.00 强大的文本编辑器 中文破解版下载
  3. 功放限幅保护_一种功放限幅器的制作方法
  4. python pandas str列内置方法
  5. 火柴人生存挑战2html5游戏在线玩,火柴人生存挑战
  6. Gateway网关的使用
  7. iOS 关于leak检测内存问题的使用
  8. 随手记_英语_学术写作_常用近义词区分
  9. 自由宣言-- I Have a Dream 马丁 路德 金
  10. k8s---存储之Volumes配置管理