技术周 | qemu网络收发包流程

news2024/9/21 3:24:50

通常我们使用qemu创建虚拟机时,会使用下面的选项指定虚拟网卡设备的类型,以及桥接、tap设备参数等,如下:

 -device选项用于给虚拟机分配虚拟设备,如磁盘设备、网卡设备等

-netdev选项用于配置虚拟设备的后端,对于网卡设备,常见的有tap、bridge、vhost-user等,tap设备是非常常见的一个后端,如使用libvirt创建虚拟机时,libvirt生成的qemu参数中,使用的就是tap设备,直接使用tap设备更加灵活。vhost-user通常用在dpdk等环境。

本文主要使用tap设备为后端,介绍数据包是如果从tap设备中读取出来,发送给虚拟机设备,以及如果从虚拟机中读取数据包,然后发送给tap设备。

tap设备是一个虚拟机设备,在kernel中没有相对应的物理设备,因此只创建出一个tap设备是没有任何用途的,我们可以使用以下命令在linux中创建一个tap设备:

 tap设备主要由内核的tun模块实现,使用'ip tuntap'命令创建设备时,有两种模式,一种是tun,另一个是tap,分别对应点对点设备和以太网设备,或者说一个是三层设备,另一个是二层设备。

即使手工把网卡设置成UP状态,tap也是处于断开的状态,如下:

只有当应用程序连接到这个设备时,tap设备的状态才会被kernel设置为连接状态,我们可以写个demo程序,从tap设备读取数据包,模拟qemu读取的过程。

程序会输出数据包的长度和数据包的目的mac地址,程序代码如下:

执行程序:

 并且此时的tap设备状态为:

qemu使用tap设备时,读写的逻辑和以上的demo程序是一样的,以下是qemu程序从tap设备读取报文的逻辑:

当qemu启动时,会使用qemu_set_fd_handler函数把tap设备的文件描述符注册到事件循环中,当tap设备从kernel收到数据包时,kernel会通知到qemu,然后qemu会调用tap_send函数去读取,如下:

从tap_send,可以看出qemu一次最多读取50个数据包,防止tap_send函数过多的占用cpu时间。

tap_read_packet函数会调用read函数读取数据包。

qemu_send_packet_async函数会调用虚拟设备的相关函数发送给虚拟机。

qemu在初始化虚拟设备的时候,会调用qemu_new_nic函数去注册相关回调函数,如下:

qemu从tap接口读取到数据包后,会调用设备注册的rtl8139_can_receive函数。tap接口的处理流程基本就完成了,后续就是各个虚拟设备的实现了,如e1000/rtl8139等设备要模拟出相关的PCI物理设备,这样虚拟机中的驱动无需做任何修改就可以识别到设备。

通常情况下,这些虚拟设备会做以下工作:

  1. 根据各种硬件特性,预处理数据包,如计算hash值等。

  2. 选择合适的queue。一般qemu在初始化设备时,会把tap的queue和虚拟设备的queue对应起来。

  3. 把数据包放入queue中,构造metadata信息。

  4. 发送中断信息。

本文章选择rtl8139为例,介绍rtl8139如何处理buf。qemu从tap读取数据包后,会调用rtl8139_receive函数去处理数据包,如下:

在rtl8139_receive函数的参数中,我们可以看到两个重要的参数,buf和size。buf就是数据包本身,size是数据包的大小,这两个信息也就是我们平时在抓包时所看到的内容。我们对应着代码中的顺序,介绍下接受函数主要做了什么处理:

  1. rtl8139_receiver_enabled函数检查驱动是否开启了收取功能,如在虚拟机中未加载设备驱动或者关闭了网卡设备,那么rtl8139没有必要再继续进行处理。

  2. 接着是根据驱动的配置是对数据包以太网头部的一个检查,驱动可以配置设备只收取单播、组播、广播或者所有数据包。

  3. 如果数据包小于64bytes,设备会填充至64bytes。

  4. rtl8139设备有两种缓冲管理模式,c mode和c+ mode,后者是一个增强模式,相比前者可以更高效的处理数据包以及支持更多的特性。qemu在这里会把数据包放到rtl8139的缓冲中,这个缓冲区域属于虚拟机的一块内存区域。

  5. 调用qemu相关函数,触发中断。这个时候虚拟机内部OS开始处理设备中断。

从虚拟机中发包的流程和上述收包的流程类似,不过方向是反过来的,发包前,虚拟机内部驱动需要构造出数据包的相关metadata,如并且告诉硬件数据包的地址和长度等信息,我们以rtl8139 c mode为例,看下linux内核如何处理这个过程:

数据包在linux内核中经过tcpip协议栈后,最后一步要调用驱动程序的ndo_start_xmit方法,对于rtl8139设备,这个函数是rtl8139_start_xmit。

  1. 获取数据包的实际大小。

  2. 把数据包复制到发送缓冲区域。rtl8139 c mode对数据包的处理比较简单。

  3. 向PCI设备的IO接口写入数据。

qemu收到设备的IO接口写操作时,会调用如下的rtl8139设备代码:

  1. 获取数据包的实际大小。

  2. 读取数据包的内容到txbuffer。

  3. 调用qemu的接口发送数据包。

以下是qemu发送数据包到tap设备的相关代码:

可以看到qemu调用writev函数往tap设备写入数据包。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/196865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MACD底背离选股公式以及技术指标公式

今天介绍MACD底背离选股公式,整体来说编写难度比较大,按照MACD底背离的定义,需要分别找到2个价格波段低点以及快线DIF的2个低点,并进行比较,最终实现选股。 一、MACD底背离选股公式(平替版) 首先…

ES6 简介(一)

文章目录ES6 简介(一)一、 概述1、 导读2、 Babel 转码器2.1 是什么2.2 配置文件 .babelrc2.3 命令行转码2.4 babel-node2.5 babel/register2.6 polyfill2.7 浏览器环境二、 变量1、 let2、 const3、 ES6 声明变量4、 顶层对象的属性5、 globalThis 对象…

TCP协议面试灵魂12 问(二)

为什么不是两次? 根本原因: 无法确认客户端的接收能力。 分析如下: 如果是两次,你现在发了 SYN 报文想握手,但是这个包滞留在了当前的网络中迟迟没有到达,TCP 以为这是丢了包,于是重传,两次握手建立好了…

机器视觉高速发展催热人工智能市场,深眸科技深度布局把握新机遇

曾经,冰箱侧身的标签、空调背面不显眼的小螺丝、微波炉角落里的型号编码等质量检测,是工业生产线中最费人工、最难检测的“老大难”。这主要是因为我国家电行业长期以混产为主要生产方式,一条生产线上可能有几十种型号的钣金件产品同时经受质…

文档存储Elasticsearch系列--2 ES内部原理

前言:ES作为nosql 的数据存储,为什么它在承载PB级别的数据的同时,又可以对外提高近实时的高效搜索,它又是通过什么算法完成对文档的相关性分析;又是怎么保证聚合的高效性; 1 ES 分布式文档存储&#xff1a…

人工智能导论——谓词公式化为子句集详细步骤

在谓词逻辑中,有下述定义: 原子(atom)谓词公式是一个不能再分解的命题。 原子谓词公式及其否定,统称为文字(literal)。PPP称为正文字,P\neg PP称为负文字。PPP与P\neg PP为互补文字。…

MySQL实战作业示例:从离线文件生成数据库

前言 MySQL实战的课后作业,作业内容具体见 https://bbs.csdn.net/topics/611904749 截至时间是 2023年2月2日,按时提交的同学有一位。确实这次的作业非常有挑战性,作业用到的内容没有百分之百的学过,需要大家进行深入而有效的搜索…

【MyBatis】高级映射多对一,一对多和延迟加载

数据库准备:1. 多对一:多个学生对应一个班级(学生表是主表, 班级表是副表)多种实现方式, 常见的包括三种第一种方式&#xff1a; 一条sql语句, 级联属性映射// StudentMapper.xml // 一条sql语句, 级联属性映射 <resultMap id"studentResultMap" type"Studen…

Java当中的AQS

一、什么是AQS AQS的全称是:AbstractQueuedSynchronizer AQS是java当中的一个抽象类&#xff0c;用来构建锁和同步器。 例如我们常见的ReentrantLock&#xff0c;Semaphore等等都是通过AQS来构建的。 AQS的原理 如果被请求的共享资源没有被占用&#xff0c;那么就把请求资源…

spring boot集成xxl job

目录 1.xxl job介绍 2.搭建说明 (1)配置调度中心 (2)配置执行器 (3).执行 1.xxl job介绍 官网地址:分布式任务调度平台XXL-JOB XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。 2.搭建说明 环境搭建主要分为两个部分…

《深入浅出计算机组成原理》学习笔记 Day19

冒险和预测&#xff08;三&#xff09;乱序执行参考乱序执行 尽管代码生成的指令是顺序的&#xff0c;但是如果后面的指令和前面的指令独立&#xff0c;完全不需要等待前面的指令运算完成&#xff0c;可以先执行。 这种解决方案称为乱序执行&#xff08;Out-of-Order Executi…

程序加载与运行过程中的资源分配与管理

目录 程序的加载 程序的内存空间 程序入口地址 BSS段初始化 程序运行过程中的堆栈管理 栈内存管理 变量的作用域&#xff1a; 栈溢出攻击原理 Linux堆内存管理 查看进程内存布局 内存分配器 内存块合并 top chunk 程序的运行分两种情况&#xff1a;一种是在有操作…

矩阵理论复习(九)

A为正规矩阵时&#xff0c;A的奇异值是A的特征值的模。A为半正定Hermite矩阵时&#xff0c;A的奇异值是A的特征值。 最佳逼近解 最小二乘解 矩阵的单边逆 A是左可逆的充要条件是A为列满秩矩阵 A是左可逆的充要条件是NA{0} 投影矩阵N(A)R(I-A),N(I-A)R(A) A是右可逆的充要…

腾讯电子签小程序跳转(app 跳小程序,小程序跳小程序) Api

腾讯电子签 官网地址&#xff1a;腾讯电子签跳转 api 文档 let id‘yDw9jUUgyg34gq97U7WZ9b1rWEBV******’ let name ‘张**’ let phone ‘MTQ3NDU3Oidioidkl’ let path pages/guide?fromSFY&toMVP_CONTRACT_COVER&id${id}&name${name}&phone${phone} wx…

Echarts解决左右上下边距问题( 两种方法)

第007个点击查看专栏目录文章目录示例效果示例源代码&#xff08;共88行&#xff09;相关资料参考相应的设置参数&#xff08;方法1&#xff09;相应的设置参数&#xff08;方法2&#xff09;专栏介绍示例效果 没有添加grid之前&#xff08;有grid的默认值来控制&#xff09; …

Web 3 财富分配方式

文章作者&#xff1a;Andrew Beal每个星期四&#xff0c;Forta 基金会团队都会在 Zoom 上聚会&#xff0c;享受虚拟欢乐时光。我还没有亲自见过我的一些同事&#xff0c;所以这是我唯一一次了解他们在办公室之外的身份。每个人都有故事要讲&#xff0c;你只需要问。规则是 “我…

Canal安装和配置

Canal安装和配置1.开启MySQL主从1.1.开启binlog1.2.设置用户权限2.安装Canal2.1.创建网络2.2.安装Canal2.3.查看canal是否与mysql建立连接下面我们就开启mysql的主从同步机制&#xff0c;让Canal来模拟salve 1.开启MySQL主从 Canal是基于MySQL的主从同步功能&#xff0c;因此…

wamp内置mysql和学习后端下载mysql相冲突问题

文章目录前言1.将后端的mysql放入wamp路径下2.打包代码文件3&#xff0c;查询wamp集合环境换mysql的办法成功way前言 尝试了各种能够兼容两者的办法都失败了 所以一气之下把wamp内的mysql删了&#xff0c;使前后端都使用一个mysql 1.将后端的mysql放入wamp路径下 将后端的mysq…

【6s965-fall2022】量化 Quantization Ⅱ

什么是线性量化 rS(q−Z)r S(q - Z)rS(q−Z) 式中&#xff0c;SSS是比例因子&#xff0c;通常是一个浮点数&#xff1b;qqq是rrr的量化后的表示&#xff0c;是一个整数&#xff1b;ZZZ也是一个整数&#xff0c;把qqq中和ZZZ相同的整数映射到rrr中零&#xff0c;因此ZZZ是零点偏…

24_mimikatz

mimikatz 一、介绍 二、修改注册表抓取明文密码 当目标为win10或2012R2以上时&#xff0c;默认在内存缓存中禁止保存明文密码&#xff0c;但可以通过修改注册表的方式抓取明文。 重启或用户重新登录后可以成功抓取 reg add HKLM\SYSTEM\CurrentControlSet\Control\Security…