VPP TCP定时器
对于多线程VPP,为主线程和worker线程分别分配timer_wheel,处理函数为tcp_expired_timers_dispatch。
static clib_error_t *
tcp_main_enable (vlib_main_t * vm)
{vlib_thread_main_t *vtm = vlib_get_thread_main ();num_threads = 1 /* main thread */ + vtm->n_threads;vec_validate (tm->wrk_ctx, num_threads - 1);n_workers = num_threads == 1 ? 1 : vtm->n_threads;for (thread = 0; thread < num_threads; thread++){ wrk = &tm->wrk_ctx[thread];tcp_timer_initialize_wheel (&wrk->timer_wheel,tcp_expired_timers_dispatch,vlib_time_now (vm));}
超时处理函数中,首先根据线程号获得对应的tcp_worker_ctx_t上下文结构,并且获取当前待处理的定时器数量。
static void
tcp_expired_timers_dispatch (u32 * expired_timers)
{u32 thread_index = vlib_get_thread_index (), n_left, max_per_loop;u32 connection_index, timer_id, n_expired, max_loops;tcp_worker_ctx_t *wrk;tcp_connection_t *tc;int i;wrk = tcp_get_worker (thread_index);n_expired = vec_len (expired_timers);tcp_worker_stats_inc (wrk, timer_expirations, n_expired);n_left = clib_fifo_elts (wrk->pending_timers);
遍历超时的定时器,参数expired_timers的每个元素,最高的4位保存了定时器的ID,后28位保存了TCP连接的索引值。如果定时器ID为重传的SYN报文定时器,由函数tcp_half_open_connection_get获取TCP连接结构(实际上是根据连接索引,在线程号为0的TCP worker结构中获取TCP连接);否则,由函数tcp_connection_get根据当前的线程号和连接索引获取TCP连接结构。
此处将TCP连接的定时器处理句柄设置为无效,设置挂起定时器ID。
/** Invalidate all timer handles before dispatching. This avoids dangling* index references to timer wheel pool entries that have been freed.*/for (i = 0; i < n_expired; i++){connection_index = expired_timers[i] & 0x0FFFFFFF;timer_id = expired_timers[i] >> 28;if (timer_id != TCP_TIMER_RETRANSMIT_SYN)tc = tcp_connection_get (connection_index, thread_index);elsetc = tcp_half_open_connection_get (connection_index);TCP_EVT (TCP_EVT_TIMER_POP, connection_index, timer_id);tc->timers[timer_id] = TCP_TIMER_HANDLE_INVALID;tc->pending_timers |= (1 << timer_id);}
将到期的定时器添加到worker结构中的挂起定时器。之后,计算每次循环最多处理的定时器数量。首先确定最大的循环次数max_loops,即最大时长0.5 * TCP_TIMER_TICK,乘以每一秒的循环数量,即最大的循环次数。其次,所有待处理的定时器(n_left+n_expired)除以max_loops即为每次循环的最大数量。最后,最大值不能大于每次最多可处理的最大向量长度VLIB_FRAME_SIZE(256),
clib_fifo_add (wrk->pending_timers, expired_timers, n_expired);max_loops =clib_max ((u32) 0.5 * TCP_TIMER_TICK * wrk->vm->loops_per_second, 1);max_per_loop = clib_max ((n_left + n_expired) / max_loops, 10);max_per_loop = clib_min (max_per_loop, VLIB_FRAME_SIZE);wrk->max_timers_per_loop = clib_max (n_left ? wrk->max_timers_per_loop : 0,max_per_loop);if (thread_index == 0)session_queue_run_on_main_thread (wrk->vm);
挂起定时器处理函数tcp_dispatch_pending_timers如下,如果TCP线程结构中没有挂起的定时器,结束处理。
static void
tcp_dispatch_pending_timers (tcp_worker_ctx_t * wrk)
{u32 n_timers, connection_index, timer_id, thread_index, timer_handle;tcp_connection_t *tc;int i;if (!(n_timers = clib_fifo_elts (wrk->pending_timers)))return;
每次遍历处理的定时器数量不能超过以上计算得到到max_timers_per_loop的值,如果挂起定时器已经被重置,即TCP连接的pending_timers已经不再置位,不进行处理。
thread_index = wrk->vm->thread_index;for (i = 0; i < clib_min (n_timers, wrk->max_timers_per_loop); i++){clib_fifo_sub1 (wrk->pending_timers, timer_handle);connection_index = timer_handle & 0x0FFFFFFF;timer_id = timer_handle >> 28;if (PREDICT_TRUE (timer_id != TCP_TIMER_RETRANSMIT_SYN))tc = tcp_connection_get (connection_index, thread_index);elsetc = tcp_half_open_connection_get (connection_index);if (PREDICT_FALSE (!tc))continue;/* Skip if the timer is not pending. Probably it was reset while* waiting for dispatch */if (PREDICT_FALSE (!(tc->pending_timers & (1 << timer_id))))continue;tc->pending_timers &= ~(1 << timer_id);/* Skip timer if it was rearmed while pending dispatch */if (PREDICT_FALSE (tc->timers[timer_id] != TCP_TIMER_HANDLE_INVALID))continue;
否则,调用定时器ID注册的超时处理函数,处理超时的TCP连接。
(*timer_expiration_handlers[timer_id]) (tc);}if (thread_index == 0 && clib_fifo_elts (wrk->pending_timers))session_queue_run_on_main_thread (wrk->vm);
}
TCP连接定义了如下的四种定时器。
#define foreach_tcp_timer \_(RETRANSMIT, "RETRANSMIT") \_(PERSIST, "PERSIST") \_(WAITCLOSE, "WAIT CLOSE") \_(RETRANSMIT_SYN, "RETRANSMIT SYN") \typedef enum _tcp_timers
{
#define _(sym, str) TCP_TIMER_##sym,foreach_tcp_timer
#undef _TCP_N_TIMERS
} __clib_packed tcp_timers_e;
以上四种定时器对应如下四个超时处理函数。
static timer_expiration_handler *timer_expiration_handlers[TCP_N_TIMERS] =
{tcp_timer_retransmit_handler,tcp_timer_persist_handler,tcp_timer_waitclose_handler,tcp_timer_retransmit_syn_handler,
};
VPP TCP定时器相关推荐
- s6-9 TCP 定时器
TCP 定时器管理 重传定时器(retransmission timer,Positive ackn. with retransmit) 最重要的定时器 TCP 定时器管理 持续定时器(per ...
- tcp协议栈实现,tcp定时器与滑动窗口实现
要实现用户态协议栈,必须要搞懂TCP,TCP 11个状态.滑动窗口.拥塞控制.定时器等等. 要使用用户态协议栈,内核提供的epoll就不起作用了,我们需要自己实现用户态的epoll.epoll内部涉及 ...
- TCP的定时器系列 — 超时重传定时器(有图有代码有真相!!!)
转载 主要内容:TCP定时器概述,超时重传定时器.ER延迟定时器.PTO定时器的实现. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd Q:一条TCP连接 ...
- TCP协议(标志位URG、PSH,定时器,连接的建立和断开)
目录 ●TCP段格式 ●TCP定时器 ●TCP三次握手和四次挥手 ●TCP段格式 6位标志位有紧急标志URG.推送标志PSH.确认标志ACK.复位标志RST.链接同步标志SYN以及结束标志FIN. ○ ...
- Linux tcp xmit 定时器
在tcp socket初始化的时候,会初始化设置三个定时器,isck_retransmit_timer.isck_delack_timer.sk_timer,本文主要描述下这三种tcp定时器. voi ...
- TCP/IP详解--第十九章
第19章 TCP的交互数据流 19.1 引言 前一章我们介绍了 TCP连接的建立与释放,现在来介绍使用 TCP进行数据传输的有关问 题. 一些有关 TCP通信量的研究如[Cacereset ...
- LWIP之TCP协议
IP协议提供了在各个主机之间传送数据报的功能,但是数据的最终目的地是主机上的特定应用程序.传输层协议就承担了这样的责任,典型的传输层协议有UDP和TCP两种. UDP只为应用程序提供了一种无连接的.不 ...
- Socket 系统调用深入研究(TCP协议的整个通信过程)
说明 本文主要参考的原文:Know your TCP system call sequences socket api可以参考我的博客:socket API 介绍 TCP DEMO:tcp demo ...
- 了解 TCP 系统调用序列
从内核到应用程序级别的函数调用序列 TCP/IP 编程接口提供各种系统调用,以帮助您有效地使用该协议.TCP 堆栈代码数量繁多,深入到内核级别的完整调用序列可以帮助您了解 TCP 堆栈.在本文中,将回 ...
- TCP/IP协议栈之LwIP(六)---网络传输管理之TCP协议
文章目录 一.TCP协议简介 1.1 正面确认与超时重传 1.2 连接管理与保活机制 1.3 滑动窗口与缓冲机制 1.4 流量控制与拥塞控制 1.5 提高网络利用率的其他机制 二.TCP协议实现 2. ...
最新文章
- 服务器安装系统时无法创建新的分区,重装系统出现“我们无法创建新的分区,也找不到现有的分区”...
- MySQL加索引避免锁表:避开事务 lock_wait_timeout 副本
- WINIO64位模拟键鼠操作
- C语言 - 快速排序算法
- P2408 不同子串个数
- 创建一个带参数的formgoup_gin框架如何获取带文件的formData请求?
- SDN——转控分离、CPU保护机制——COPP技术案列详解及配置命令、
- AD原理图编译ERROR:GND contains Output Pin and Power Pin objects
- MVC中如何实现本地化的解决方案
- linux监听apache代码,linux系统使用python监控apache服务器进程脚本分享
- HTML 上标题栏把右标题栏遮挡,如何编辑组件的样式(编辑样式)?
- vmware workstation14密钥记录
- 如何查看Websphere(was)上的jdk版本
- 线性表的链式存储结构及操作的实现
- 徐思201771010132《面向对象程序设计(java)》第二周学习总结
- 忍无可忍?英特尔执行副总裁撰文《高通的诡辩被戳穿了》指责高通
- 百度百科创建对于文案和措辞有什么要求?
- jsapi 支付缺少appid ¬ify_url
- 安装docker-ce报错
- firefox 下载文件时处理此文件的方法
热门文章
- 完整版身份证前6位判断归属地
- 读书笔记之《Redis开发与运维》—— 一
- IDEA使用教程汇总
- Python(PyCharm)的下载安装汉化(2022)
- 收入时间序列——之预测总结篇
- Axure8授权激活码
- Axure 8.1.0.3382 激活码(转)
- 【目标跟踪】|MOSSE原理及对应代码解释 matlab C
- 华为交换机 tagged 与 untagged 的关系、H5C 开web管理、telnet管理
- workbench动力学周炬_ANSYS WORKBENCH有限元分析实例详解(动力学)