基于dpdk的用户态协议栈f-stack实现分析
f-stack是腾讯基于dpdk开发的一套用户态协议栈,目前已经开源,相关介绍可以看这里:https://cloud.tencent.com/developer/article/1005179。 开源代码在这里:https://github.com/F-Stack/f-stack.git 。
项目背景
F-Stack 这个项目起始于DNSPod的授权DNS项目,当时是12年,DPDK还未开源的时候,腾讯就基于DPDK做了授权DNS,做完的时候正好DPDK也开源了,正式上线后10GE单网卡性能达到1100万qps,后面又实现了一个简易的TCP协议栈用于支持TCP DNS。后来DNSPod合并进入腾讯云,腾讯云有大量业务需要高性能的接入服务,所以就在原来授权DNS的TCP协议栈基础上实现了较为完整的TCP/IP协议栈(参考了mTCP,SeaStar,lwIP等),加上了协程框架,并且上层兼容了腾讯SNG的服务端框架SPP,使得腾讯云原有的业务可以无缝迁入,但是经过近一年的线上使用运行,腾讯发现,线上的网络环境各式各样,这个TCP/IP协议栈并不能满足全部需求(各种tunnel等),而自己去实现各种协议既费力又不讨好,所以经过一段时间的调研,决定移植FreeBSD的协议栈。
整体介绍
这里不再对这个协议栈的特点和介绍展开,网上都有,其实就是dpdk的一些特点,另一点就是对现有posix编程接口比较友好吧,提供了线程和epoll等接口,方便应用的移植。这里主要是对f-stack的实现框架转发路径做一个简单分析。
f-stack没有使用自己开发的协议栈,据说早期使用的是基于mTCP的自研协议栈,但后来因为兼容性,在公有云环境使用会有诸多问题。如果比较笼统的说,f-stack可以等价于dpdk+freebsd协议栈。F-stack自己的关键工作就是将两者结合起来,入方向将流量从dpdk导入freebsd协议栈,出方向由freebsd协议栈导入dpdk。当然freebsd协议栈也是做了少量改动的,比如:
1) 调度:对 FreeBSD Network Stack 的内核线程、中断线程、定时器线程、sched、sleep 等进行了去除。
2) 锁:对 FreeBSD Network Stack 的锁操作进行了去除,包括 mtx、rw、rm、sx、cond 等。
3) 内存相关:phymem、uma_page_slab_hash、uma、kmem_malloc、malloc 等实现。
4) 全局变量:pcpu、curthread、proc0、thread0 等初始化。
5) 环境变量:setenv、getenv 实现
6) SYS_INIT:mi_startup。
7) 时钟:timecounter、ticks、hz、定时器等实现。
8) 其他:Linux 和 FreeBSD 的 errno 转换、胶水代码、移除了不需要的功能模块等。
但这些改动涉及的代码非常少,据说只有几百行,所以非常方便将最新的freebsd代码更新过来,便于维护。这样的设计的优势就是一方面可以高效的利用dpdk框架的高性能转发,另一方面不至于陷入协议栈的复杂开发当中。
下面简单的看一下f-stack的代码结构:
## Structure of F-Stack code
├── app -- Nginx(1.11.10)/Redis(3.2.8)/Microthread framework (适配f-stack的Nginx和Redis)
├── config.ini (f-stack的配置文件)
├── doc (f-stack的一些说明文档)
├── dpdk -- Intel DPDK(16.07) directory (放置dpdk代码)
├── example – DEMO (使用f-stack的例子)
├── freebsd -- FreeBSD(11.0) Network Stack directory (freebsd协议栈代码)
├── lib -- F-Stack lib directory (f-stack自身的代码)
├── mk
└── start.sh
初始化分析
我们直接先看一下f-stack提供的demo的main函数,有一个宏观认识。
代码非常简单,和正常的socket编程一样调用socket,bind,listen等接口,可以看到f-stack其提供的ff_socket,ff_bind,ff_listen和posix接口是完全兼容的。其他关键的区别就是最开始的ff_init(argc, argv)调用,这个主意是为了f-stack框架的启动初始化,下面会分析,另一个就是ff_run(loop, NULL),熟悉dpdk的人应该能猜到,这就是启动主循环开始网卡的收发逻辑。
下面一张图看一下ff_init的主要初始化逻辑。
其中最关键的就是ff_dpdk_if_up,这个函数为每个dpdk接管的port创建一个struct ifnet结构,并将这个结构注册到freebsd中,其中调用的ether_ifattach就是freebsd的接口,这个结构可以理解为网卡对应的虚拟设备,这个设备也是dpdk和freebsd关联的核心。Ifnet有很多handle函数,会被做如下初始化:
ifp->if_start = ff_veth_start;
ifp->if_transmit = ff_veth_transmit;
ifp->if_qflush = ff_veth_qflush;
ifp->if_output = ether_output;
ifp->if_input = ether_input;
……
其中核心是if_input,if_output和if_transmit三个函数,if_input就是ifnet的收包函数,可以理解为协议栈的入口函数,有些类似于kernel协议栈的netif_receive_skb函数;但是把if_output比喻成协议栈的出口函数就有点不恰当了,因为启动还有bridge的转发逻辑,其中(ether_output)调用的ifp->if_transmit可以理解为真正的协议栈出口函数,类似于kernel的dev_queue_xmit。
转发流程分析
转发流程以ff_run开始的main_loop开始,我们以tcp收到syn+ack及回复流程为例,分析这个转发过程(syn+ack处理不会上送app,由协议栈完成),直接上图,流程如下:
基于dpdk的用户态协议栈f-stack实现分析相关推荐
- FD.io VSAP(VPP Stack Acceleration Project),通过FD.io VSAP构建用户态协议栈
目录 VSAP Scope-使用范围 Releases List of all subpages (used or unused) 通过FD.io VSAP构建用户态协议栈 VSAP https:// ...
- Linux网络设计之用户态协议栈与dpdk
用户态协议栈设计与dpdk dpdk环境开启 Windowe下配置静态IP表 DPDK API介绍 struct rte_memzone结构体 struct rte_mempool结构体 struct ...
- 架构决定可扩展性--聊聊用户态协议栈的意义
在进入这个话题之前先说说通用和专业之间的区别. 举个很好的例子,好比我们个人,绝大部分的人都是"通用"的,而只有极少部分的人是"专业"的.通用的人主要目标是 ...
- 用户态协议栈设计实现
目录 1. 网络模式 2. 获取原始数据 3. UDP数据帧格式 以太网协议头(数据链路层) -- 14byte IP数据头(网络层) -- 20byte UDP协议的数据格式(传输层) -- 8by ...
- 用户态协议栈之tcp/ip设计
1 解决问题 对于服务器而言,正常的接受一帧Data的过程,客户端先通过网络发送一帧数据到网卡,再经过协议栈,最后通过系统调用叨叨应用程序.具体的流程图如下: 针对上面的两个流程,涉及到两次拷贝(网卡 ...
- 用户态协议栈tcp/ip设计
1 解决问题 对于服务器而言,正常的接受一帧Data的过程,客户端先通过网络发送一帧数据到网卡,再经过协议栈,最后通过系统调用叨叨应用程序.具体的流程图如下: 针对上面的两个流程,涉及到两次拷贝(网卡 ...
- 深入浅出用户态协议栈
一.前言 在讲网络协议栈前,先理解一个数据包在网络传输是一个怎么样的流程,如下图所示. 正常的流程是网卡接收到数据后,把数据copy到协议栈(sk_buff),协议栈把sk_buff数据解析完后再把数 ...
- 【高阶知识】用户态协议栈之Epoll实现原理
Epoll 是 Linux IO 多路复用的管理机制.作为现在 Linux 平台高性能网络 IO 必要的组件.内核的实现可以参照:fs/eventpoll.c . 为什么需要自己实现 epoll 呢? ...
- 一文彻底掌握用户态协议栈,一看就懂的
用户态协议栈 那我们先跟大家解释这个协议栈这个东西啊协议栈这个东西呢或多或少啊各个朋友应该都听过,我们站在一个设计者的角度,站在一个设计者的角度,站在tcpip的个人的角度,我们怎么去设计这个协议的? ...
- 100行源代码搞定用户态协议栈丨udp,icmp,arp协议的现实丨网络协议栈丨Linux服务器开发丨C++后端开发丨Linux后台开发
100行源代码搞定用户态协议栈 视频讲解如下,点击观看: 100行源代码搞定用户态协议栈丨udp,icmp,arp协议的现实丨网络协议栈丨Linux服务器开发丨C++后端开发丨Linux后台开发丨网络 ...
最新文章
- [转]centos5.2用memcache 来作PHP 的session.save_handler
- 内部数据中心不会消失的6个原因
- 【转】利用matlab生成随机数函数
- 直接使用Berkeley DB的Memory Pool 功能
- .NET跨平台之旅:将QPS 100左右的ASP.NET Core站点部署到Linux服务器上
- mysql 重置密码语音_数字语音信号处理学习笔记语音信号的同态处理(2)
- 在excel中创建日历
- Anaconda及TensorFlow安装
- 2019辽宁公务员考试:申论突破80+学习计划第一步
- python怎么变成动图_python 生成动图
- centos审计服务audit导致使centos服务器不能登录,部署的应用不能运行和访问。
- 智能计算系统课程笔记05:编程框架机理
- web集群之通过tomcat部署jpress应用
- 美术加:想要画好人物头像,头骨结构先吃透~
- 搭建mpi测试环境,使用intell的mpi库
- 抖音拍摄脚本怎么写,掌握这几点快速拍摄爆款视频丨国仁网络资讯
- 电商o2o系统开发原理和解决方案你get了吗?
- 如何运营个人技术博客
- VS编译OpenCV和OpenCV-contrib
- Vue2 必备的50个知识点
热门文章
- further occurrences of HTTP header parsing errors will be logged at DEBUG level.
- 泛函编程(14)-try to map them all
- C 中的左值(Lvalues)和右值(Rvalues)
- php服务端setcookie()原理
- VB中PictureBox控件使用教程
- FastReport使用一——简介
- 前台传来的文件通过流stream转成bytes 再把文件写入数据库 类型是blob
- mysql本地连接1045_MySQL密码正确却无法本地登录-1045
- 那些不需要你知道的Chrome DevTool - 使用技巧篇
- Linux 系统磁盘满处理方法