探秘 TCP TLP:从背景到实现
回家的路上还讨论了个关于 TCP TLP 的问题,闲着无事缕一缕。本文内容参考自 Tail Loss Probe (TLP): An Algorithm for Fast Recovery of Tail Losses 以及 Linux 内核源码。
TLP,先说缘由。自 TCP 引入 Fast retrans 机制就是为了尽力避免 RTO,但如果 sender 发送的一系列数据包中尾包被丢弃,就没有触发 dupack,sack 的可能,于是就有了 TLP,它的目的是在原始序列被丢了尾部没有机会触发 FR 时通过发送探测包来触发 FR,避免跌入 RTO。
那么问题就是如何选择探测包。
如果有新数据,当然以发送新数据为主,如果没有新数据,则重传队列中最后一个报文,如果该探测包能顺利到达对端,可以覆盖所有的丢包场景,触发 FR,draft 中总结了所有的几种情况,如下:
number of scoreboard afterlosses TLP retrans ACKed mechanism final outcome-------- ----------------- ----------------- -------------(1) AAAL AAAA TLP loss detection all repaired(2) AALL AALS early retransmit all repaired(3) ALLL ALLS early retransmit all repaired(4) LLLL LLLS FACK fast recovery all repaired(5) >=5 L ..LS FACK fast recovery all repairedkey:A = ACKed segmentL = lost segmentS = SACKed segment
无论如何,紧着越后面的数据包发送,可避免重传浪费,最值得注意的是,TLP 的核心目标是通过这次探测来诱导对端携带足够的 sack 以触发 FR,ER,enhanced ER(这些不再赘述,详见 TCP-TLP,ER),而不是通过这次探测来补洞。核心一句话,它的目的不是重传,而是探测。
相反,TLP 还要额外区分成功捎带的重传。如果发送的是新数据,该新数据诱导了对端足够的 sack 并触发了 FR,那么没有任何无用功,但如果没有新数据,重传了队列中最后一个数据包,而该数据包恰好补足了空洞,它没有触发 FR,但确实发生了丢包恢复,按照 congestion control 原则,此时应该执行收敛降窗动作:ssthresh = β*cwnd & cwnd = ssthresh。
因此要识别这种探测补洞,以满足并执行拥塞控制收敛原则,即降窗。
用新数据进行探测当然无需任何额外检查,因为它并没有重传任何东西,需要检查的是重传最后一个数据包的情形。TLP draft 没有规定重传探测包发送的次数,但限制在 2(约数,为什么不是 3?) 次以内:
(2) Conditions for scheduling PTO:...(c) Number of consecutive PTOs <= 2.(3) When PTO fires:...(d) If conditions in (2) are satisfied:-> Reschedule next PTO.Else:-> Rearm RTO to fire at epoch 'now+RTO'.
这意味着它可以发送好多遍,这就需要计数器管理这些重传探测包的功效,即是否发生了补洞。只要有一次发生了补洞,就应该执行收敛降窗。
那么如何界定检查时机,draft 规定 after(ack, TLPHighRxt) 是合理的,如果不满足,可能马上下一个 ack = HighRxt 就来了,至于何时,又不好确定,因此 ack 越过 HighRxt 就很合理,在此之前,通过下面的规则计数 TLPRtxOut:
(3) Upon sending a TLP retransmission:if (TLPRtxOut == 0)TLPHighRxt = SND.NXT;TLPRtxOut++;(4) Upon receiving an ACK:(a) Tracking ACKsWe define a "TLP dupack" as a dupack that has all the regularproperties of a dupack that can trigger fast retransmit, plus the ACKacknowledges TLPHighRxt, and the ACK carries no new SACK information(as noted earlier, TLP requires that the receiver supports SACK).This is the kind of ACK we expect to see for a TLP transmission ifthere were no losses. More precisely, the TLP sender considers a TLPprobe segment as acknowledged if all of the following conditions aremet:(a) TLPRtxOut > 0(b) SEG.ACK == TLPHighRxt(c) the segment contains no SACK blocks for sequence rangesabove TLPHighRxt(d) the ACK does not advance SND.UNA(e) the segment contains no data(f) the segment is not a window updateIf all of those conditions are met, then the sender executes thefollowing:TLPRtxOut--;
最后,当满足 after(ack, TLPHighRxt),只要 TLPRtxOut > 0,就执行降窗:ssthresh = β*cwnd & cwnd = ssthresh。
为了一碟醋,包了一顿饺子,这个判定 “是否探测包补足了空洞” 过程有点复杂,着实让人觉得有什么深意,但理解了 TLP 的根本目的就觉得其实没什么大不了的。在大多数情况下,TLP 探测后带来足够的 sack 足以触发 FR,丢包重传流程自然交给 FR,只有在极小概率下,即这个重传探测包恰好补足了空洞,且恰好只有重传探测包这一个包丢失的情形下,这一大坨才起作用。
所以说回到写这篇文章最初的原因,为什么 Linux TCP 没有实现多次重传探测,而仅仅实现了一次(这是允许的):
Implementations MAY use one or two consecutive PTOs.
我以为 Linux 是对的,首先这种复杂判定发生的概率并不高,其次它的实现非常复杂,特别是定时器管理。如果一次 PTO 超时都没能搞定尾部丢包问题,再来一次大概率还是无解,不如交给 RTO 兜底更加简洁,所以你会发现Linux TLP 的实现非常简单,核心十几行代码就完事了。
再者说,TCP 非常难以精确区别原始包和重传包,以至于 TLP 必须谨慎行事:
(5) Senders must only send a TLP loss probe retransmission if all theconditions from section 2.1 are met and the following condition alsoholds:(TLPRtxOut == 0) || (SND.NXT == TLPHighRxt)This ensures that there is at most one sequence range withoutstanding TLP retransmissions. The sender maintains this invariantso that there is at most one TLP retransmission "episode" happeningat a time, so that the sender can use the algorithm described abovein this section to determine when the episode is over, and thus whenit can infer whether any data segments were lost.
而 QUIC 做这件事非常简单,QUIC 对每包编号,可轻松区别一次重传是不是无效的,因此它的实现就非常简单,多一行代码不多,这又是结构决定行为的例子。
最后,说说 TLP 初衷。
较大的 RTO 通常是由测量 RTT 的差异引起,这在无线环境和低密度统计复用环境尤其明显。大 RTO 造成了统计长尾。但简单减少 RTO 时间并不能解决问题。首先,它增加了统计意义上虚假重传,其次,更重要的是,RTO 一旦发生,将极大影响性能。这对现代 TCP 传输影响巨大,在此背景下,TLP 是对 RTO 的精细化优化,它做了更多的事,以避免 RTO 发生。当然,这又是一次买卖。
To get a sense of just how long the RTOs are in relation toconnection RTTs, following is the distribution of RTO/RTT values onGoogle Web servers. [percentile, RTO/RTT]: 50th percentile, 4.375th percentile, 11.390th percentile, 28.995th percentile, 53.999th percentile, 214 Large RTOs, typically caused by variance in measured RTTs, can be a result of intermediate queuing, and service variability in mobile channels. Such large RTOs make a huge contribution to the long tail on the latency statistics of short flows. Note that simply reducing the length of RTO does not address the latency problem for two reasons: first, it increases the chances of spurious retransmissions. Second and more importantly, an RTO reduces TCP's congestion window to one and forces a slow start. Recovery of losses without relying primarily on the RTO mechanism is beneficial for short TCP transfers.
今天除夕夜,祝各位经理和工人,新年快乐!
浙江温州皮鞋湿,下雨进水不会胖。
相关文章:
探秘 TCP TLP:从背景到实现
回家的路上还讨论了个关于 TCP TLP 的问题,闲着无事缕一缕。本文内容参考自 Tail Loss Probe (TLP): An Algorithm for Fast Recovery of Tail Losses 以及 Linux 内核源码。 TLP,先说缘由。自 TCP 引入 Fast retrans 机制就是为了尽力避免 RTO…...
MCU内部ADC模块误差如何校准
本文章是笔者整理的备忘笔记。希望在帮助自己温习避免遗忘的同时,也能帮助其他需要参考的朋友。如有谬误,欢迎大家进行指正。 一、ADC误差校准引言 MCU 片内 ADC 模块的误差总包括了 5 个静态参数 (静态失调,增益误差,微分非线性…...
国产之光DeepSeek架构理解与应用分析
目录 初步探索DeepSeek的设计 一、核心架构设计 二、核心原理与优化 三、关键创新点 四、典型应用场景 五、与同类模型的对比优势 六、未来演进方向 从投入行业生产的角度看 一、DeepSeek的核心功能扩展 二、机械电子工程产业中的具体案例 1. 预测性维护(Predictive…...
群晖NAS安卓Calibre 个人图书馆
docker 下载镜像johngong/calibre-web,安装之 我是本地的/docker/xxx/metadata目录 映射到 /usr/local/calibre-web/app/cps/metadata_provider CALIBREDB_OTHER_OPTION 删除 CALIBRE_SERVER_USER calibre_server_user 缺省用户名口令 admin admin123 另外有个N…...
openRv1126 AI算法部署实战之——Tensorflow模型部署实战
在RV1126开发板上部署Tensorflow算法,实时目标检测RTSP传输。视频演示地址 rv1126 yolov5 实时目标检测 rtsp传输_哔哩哔哩_bilibili 一、准备工作 从官网下载tensorflow模型和数据集 手动在线下载: https://github.com/tensorflow/models/b…...
HTML特殊符号的使用示例
目录 一、基本特殊符号的使用 1、空格符号: 2、小于号 和 大于号: 3、引号: 二、版权、注册商标符号的使用 1、版权符号:© 2、注册商标符号: 三、数学符号的使用 四、箭头符号的使用 五、货币符号的使用…...
如何对系统调用进行扩展?
扩展系统调用是操作系统开发中的一个重要任务。系统调用是用户程序与操作系统内核之间的接口,允许用户程序执行内核级操作(如文件操作、进程管理、内存管理等)。扩展系统调用通常包括以下几个步骤: 一、定义新系统调用 扩展系统调用首先需要定义新的系统调用的功能。系统…...
【MFC】C++所有控件随窗口大小全自动等比例缩放源码(控件内字体、列宽等未调整) 20250124
MFC界面全自动等比例缩放 1.在初始化里 枚举每个控件记录所有控件rect 2.在OnSize里,根据当前窗口和之前保存的窗口的宽高求比例x、y 3.枚举每个控件,根据比例x、y调整控件上下左右,并移动到新rect struct ControlInfo {CWnd* pControl;CRect original…...
前端 | 深入理解Promise
1. 引言 JavaScript 是一种单线程语言,这意味着它一次仅能执行一个任务。为了处理异步操作,JavaScript 提供了回调函数,但是随着项目处理并发任务的增加,回调地狱 (Callback Hell) 使异步代码很难维护。为此,ES6带来了…...
【视频+图文讲解】HTML基础2-html骨架与基本语法
图文教程 基本骨架 举个例子,下图所展示的为html的源代码 -!DOCTYPE:表示文档类型(后边写的html表示文档类型是html);其中“!”表示声明 只要是加这个声明标签的,浏览器就会把下边的源代码当…...
LabVIEW在电机自动化生产线中的实时数据采集与生产过程监控
在电机自动化生产线中,实时数据采集与生产过程监控是确保生产效率和产品质量的重要环节。LabVIEW作为一种强大的图形化编程平台,可以有效实现数据采集、实时监控和自动化控制。详细探讨如何利用LabVIEW实现这一目标,包括硬件选择、软件架构设…...
《深入理解HTTP交互与数据监控:完整流程与优化实践》
文章目录 🌐 全链路解析:HTTP请求响应与数据可视化监控一、HTTP请求响应全流程解析1. 全链路交互流程图2.关键技术实现2.1 前端请求构造(ES6语法示例)2.2 服务端处理架构(Node.js/Express) 二、数据可视化监…...
pytorch使用SVM实现文本分类
人工智能例子汇总:AI常见的算法和例子-CSDN博客 完整代码: import torch import torch.nn as nn import torch.optim as optim import jieba import numpy as np from sklearn.model_selection import train_test_split from sklearn.feature_extract…...
Recommender Systems with Large Models
一、引言 信息爆炸时代,用户面临信息过载,传统推荐系统依赖经典算法,难以满足需求。大模型基于深度学习,经大规模预训练,具备强大能力,能实现更精准推荐,为推荐系统发展开辟新路径。 二、大模…...
团体程序设计天梯赛-练习集——L1-028 判断素数
前言 一道10分的题目,相对来说比较简单,思考的时候要仔细且活跃,有时候在写代码的时候一些代码的出现很多余,并且会影响最后的结果 L1-028 判断素数 本题的目标很简单,就是判断一个给定的正整数是否素数。 输入格式…...
SCRM开发为企业提供全面客户管理解决方案与创新实践分享
内容概要 在当今的商业环境中,客户关系管理(CRM)变得越来越重要。而SCRM(社交客户关系管理)作为一种新兴的解决方案,正在帮助企业彻底改变与客户的互动方式。快鲸SCRM是一个引人注目的工具,它通…...
Axure PR 9 旋转效果 设计交互
大家好,我是大明同学。 这期内容,我们将学习Axure中的旋转效果设计与交互技巧。 旋转 创建旋转效果所需的元件 1.打开一个新的 RP 文件并在画布上打开 Page 1。 2.在元件库中拖出一个按钮元件。 创建交互 创建按钮交互状态 1.选中按钮元件…...
自定义数据集 使用pytorch框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测,对预测结果计算精确度和召回率及F1分数
代码: import torch import numpy as np import torch.nn as nn from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score# 定义数据:x_data 是特征,y_data 是标签(目标值) data [[-0…...
Linux02——Linux的基本命令
目录 ls 常用选项及功能 综合示例 注意事项 cd和pwd命令 cd命令 pwd命令 相对路径、绝对路径和特殊路径符 特殊路径符号 mkdir命令 1. 功能与基本用法 2. 示例 3. 语法与参数 4. -p选项 touch-cat-more命令 1. touch命令 2. cat命令 3. more命令 cp-mv-rm命…...
MySQL数据库(二)- SQL
目录 编辑 一 DDL (一 数据库操作 1 查询-数据库(所有/当前) 2 创建-数据库 3 删除-数据库 4 使用-数据库 (二 表操作 1 创建-表结构 2 查询-所有表结构名称 3 查询-表结构内容 4 查询-建表语句 5 添加-字段名数据类型 6 修改-字段数据类…...
Docker自定义镜像
Dockerfile自定义镜像 一:镜像结构 镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。 我们以MySQL为例,来看看镜像的组成结构: 简单来说,镜像就是在系统函数库、运行环境基础上,添加应用程序文件、…...
网络协议基础
文章目录 前言一、网络协议分层1.应用层2.传输层3.网络层4.数据链路层5.物理层 二、图解IP1.IP基本认识(1)IP的作用(2)IP与MAC的关系 2.IP地址的基础知识(1)IP地址的定义(2)IP地址的…...
c语言进阶(简单的函数 数组 指针 预处理 文件 结构体)
c语言补充 格式 void函数头 {} 中的是函数体 sum函数名 () 参数表 #include <stdio.h>void sum(int begin, int end) {int i;int sum 0;for (i begin ; i < end ; i) {sum i;}printf("%d到%d的和是%d\n", begin, end, sum); …...
Pytorch框架从入门到精通
目录 一、Tensors 1.1 初始化一个Tensor 1)赋值初始化 2)从 NumPy 数组初始化 3)从另一个张量 4)使用随机值或常量值 1.2 Tensor 的属性 1.3 对 Tensor 的操作 1.3.1 总体介绍 1.3.2 索引和切片 1.3.3 算术运算 矩阵乘…...
Vue.js组件开发-实现全屏图片文字缩放切换特效
使用 Vue 实现全屏图片文字缩放切换特效 步骤 创建 Vue 项目:使用 Vue CLI 来快速创建一个新的 Vue 项目。设计组件结构:创建一个包含图片和文字的组件,并实现缩放和切换效果。实现样式:使用 CSS 来实现全屏显示、缩放和切换动画…...
在 WSL2 中重启 Ubuntu 实例
在 WSL2 中重启 Ubuntu 实例,可以按照以下步骤操作: 方法 1: 使用 wsl 命令 关闭 Ubuntu 实例: 打开 PowerShell 或命令提示符,运行以下命令: wsl --shutdown这会关闭所有 WSL2 实例。 重新启动 Ubuntu: 再次打开 Ubuntu&#x…...
Flutter 新春第一弹,Dart 宏功能推进暂停,后续专注定制数据处理支持
在去年春节,Flutter 官方发布了宏(Macros)编程的原型支持, 同年的 5 月份在 Google I/O 发布的 Dart 3.4 宣布了宏的实验性支持,但是对于 Dart 内部来说,从启动宏编程实验开始已经过去了几年,但…...
Signature
打开得到加密脚本: import ecdsa import randomdef ecdsa_test(dA,k):sk ecdsa.SigningKey.from_secret_exponent(secexpdA,curveecdsa.SECP256k1)sig1 sk.sign(databHi., kk).hex()sig2 sk.sign(databhello., kk).hex()r1 int(sig1[:64], 16)s1 int(sig1[64:…...
UE求职Demo开发日志#18 数据表获取物品信息,添加背包模块
1 把获取物品信息改为读取数据表 先创建结构,暂时有这几个属性: USTRUCT(BlueprintType) struct ARPG_CPLUS_API FMyItemData:public FTableRowBase {GENERATED_USTRUCT_BODY()UPROPERTY(EditAnywhere, BlueprintReadWrite)int ItemId;//物品Id&#x…...
neo4j-community-5.26.0 create new database
1.edit neo4j.conf 把 # The name of the default database initial.dbms.default_databasehonglouneo4j # 写上自己的数据库名称 和 # Name of the service #5.0 server.windows_service_nameneo4j #4.0 dbms.default_databaseneo4j #dbms.default_databaseneo4jwind serve…...
项目中用的网关Gateway及SpringCloud
在现代微服务架构中,网关(Gateway)起到了至关重要的作用。它不仅负责路由请求,还提供了统一的认证、授权、负载均衡、限流等功能。Spring Cloud Gateway 是 Spring Cloud 生态系统中的一个重要组件,专门为微服务架构提…...
《Ollama Python 库》
Ollama Python 库 Ollama Python 库提供了将 Python 3.8 项目与 Ollama 集成的最简单方法。 先决条件 应该安装并运行 Ollama拉取一个模型以与库一起使用:例如ollama pull <model>ollama pull llama3.2 有关可用模型的更多信息,请参阅 Ollama.com。…...
大模型概述(方便不懂技术的人入门)
1 大模型的价值 LLM模型对人类的作用,就是一个百科全书级的助手。有多么地百科全书,则用参数的量来描述, 一般地,大模型的参数越多,则该模型越好。例如,GPT-3有1750亿个参数,GPT-4可能有超过1万…...
Ubuntu16.04编译安装Cartographer 1.0版本
说明 官方文档 由于Ubuntu16.04已经是很老的系统,如果直接按照Cartographer官方安装文档安装会出现代码编译失败的问题,本文给出了解决这些问题的办法。正常情况下执行本文给出的安装方法即可成功安装。 依赖安装 # 这里和官方一致 # Install the req…...
AI-ISP论文Learning to See in the Dark解读
论文地址:Learning to See in the Dark 图1. 利用卷积网络进行极微光成像。黑暗的室内环境。相机处的照度小于0.1勒克斯。索尼α7S II传感器曝光时间为1/30秒。(a) 相机在ISO 8000下拍摄的图像。(b) 相机在ISO 409600下拍摄的图像。该图像存在噪点和色彩偏差。©…...
2 MapReduce
2 MapReduce 1. MapReduce 介绍1.1 MapReduce 设计构思 2. MapReduce 编程规范3. Mapper以及Reducer抽象类介绍1.Mapper抽象类的基本介绍2.Reducer抽象类基本介绍 4. WordCount示例编写5. MapReduce程序运行模式6. MapReduce的运行机制详解6.1 MapTask 工作机制6.2 ReduceTask …...
OpenCV:SIFT关键点检测与描述子计算
目录 1. 什么是 SIFT? 2. SIFT 的核心步骤 2.1 尺度空间构建 2.2 关键点检测与精细化 2.3 方向分配 2.4 计算特征描述子 3. OpenCV SIFT API 介绍 3.1 cv2.SIFT_create() 3.2 sift.detect() 3.3 sift.compute() 3.4 sift.detectAndCompute() 4. SIFT 关…...
初识Cargo:Rust的强大构建工具与包管理器
初识Cargo:Rust的强大构建工具与包管理器 如果你刚刚开始学习Rust,一定会遇到一个名字:Cargo。Cargo是Rust的官方构建工具和包管理器,它让Rust项目的创建、编译、测试和依赖管理变得非常简单。本文将带你快速了解Cargo的基本用法…...
LightM-UNet(2024 CVPR)
论文标题LightM-UNet: Mamba Assists in Lightweight UNet for Medical Image Segmentation论文作者Weibin Liao, Yinghao Zhu, Xinyuan Wang, Chengwei Pan, Yasha Wang and Liantao Ma发表日期2024年01月01日GB引用> Weibin Liao, Yinghao Zhu, Xinyuan Wang, et al. Ligh…...
2025年02月01日Github流行趋势
项目名称:oumi 项目地址url:https://github.com/oumi-ai/oumi 项目语言:Python 历史star数:544 今日star数:103 项目维护者:xrdaukar, oelachqar, taenin, wizeng23, kaisopos 项目简介:一切你需…...
自动化测试框架搭建-封装requests-优化
目的 1、实际的使用场景,无法避免的需要区分GET、POST、PUT、PATCH、DELETE等不同的方式请求,以及不同请求的传参方式 2、python中requests中,session.request方法,GET请求,只支持params传递参数 session.request(me…...
什么是线性化PDF?
线性化PDF是一种特殊的PDF文件组织方式。 总体而言,PDF是一种极为优雅且设计精良的格式。PDF由大量PDF对象构成,这些对象用于创建页面。相关信息存储在一棵二叉树中,该二叉树同时记录文件中每个对象的位置。因此,打开文件时只需加…...
XML DOM 浏览器差异
DOM 解析中的浏览器差异 所有现代的浏览器都支持 W3C DOM 规范。 然而,浏览器之间是有差异的。一个重要的差异是: 处理空白和换行的方式 DOM - 空白和换行 XML 经常在节点之间包含换行或空白字符。这是在使用简单的编辑器(比如记事本&…...
电子电气架构 --- 汽车电子拓扑架构的演进过程
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活…...
01-六自由度串联机械臂(ABB)位置分析
ABB工业机器人(IRB2600)如下图所示(d1444.8mm,a1150mm,a2700mm,a3115mm,d4795mm,d685mm),利用改进DH法建模,坐标系如下所示: 利用改进…...
04树 + 堆 + 优先队列 + 图(D1_树(D6_B树(B)))
目录 一、学习前言 二、基本介绍 三、特性 1. 从概念上说起 2. 举个例子 四、代码实现 节点准备 大体框架 实现分裂 实现新增 实现删除 五、完整源码 一、学习前言 前面我们已经讲解过了二叉树、二叉搜索树(BST)、平衡二叉搜索树(…...
350.两个数组的交集 ②
目录 题目过程解法 题目 给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑…...
C#,入门教程(09)——运算符的基础知识
上一篇: C#,入门教程(08)——基本数据类型及使用的基础知识https://blog.csdn.net/beijinghorn/article/details/123906998 一、算术运算符号 算术运算符号包括:四则运算 加 , 减-, 乘*, 除/与取模%。 // 加法,运算 int va 1 …...
Python-基于PyQt5,wordcloud,pillow,numpy,os,sys等的智能词云生成器
前言:日常生活中,我们有时后就会遇见这样的情形:我们需要将给定的数据进行可视化处理,同时保证呈现比较良好的量化效果。这时候我们可能就会用到词云图。词云图(Word cloud)又称文字云,是一种文…...
海外问卷调查之渠道查,企业经营的指南针
海外问卷调查,是企业调研最常用到的方法,有目的、有计划、有系统地收集研究对象的现实状况或历史状况的一种有效手段,是指导企业经营的有效手段。 海外问卷调查充分运用历史法、观察法等方法,同时使用谈话、问卷、个案研究、测试…...