当前位置: 首页 > news >正文

virtio设备input节点

注册virtio_input_node节点,节点类型为VLIB_NODE_TYPE_INPUT。

VLIB_REGISTER_NODE (virtio_input_node) = {.name = "virtio-input",.sibling_of = "device-input",.format_trace = format_virtio_input_trace,.flags = VLIB_NODE_FLAG_TRACE_SUPPORTED,.type = VLIB_NODE_TYPE_INPUT,.state = VLIB_NODE_STATE_INTERRUPT,.n_errors = VIRTIO_INPUT_N_ERROR,.error_strings = virtio_input_error_strings,
};

如下,virtio-input节点。

vpp# show node virtio-input
node virtio-input, type input, state disabled, index 432, sibling-of device-inputnode function variants:Name             Priority  Active  Descriptionhsw                    50    yes   Intel Haswelldefault                 0          defaultnext nodes:next-index  node-index               Node               Vectors0          627          ip4-input-no-checksum         01          626                ip4-input               02          589                ip6-input               03          467               mpls-input               04          690             ethernet-input             05          701               error-drop               06          631                ip4-drop                07          595                ip6-drop                08          710              punt-dispatch             09          517            esp4-decrypt-tun            010          519            esp6-decrypt-tun            0

virtio节点对应的处理函数virtio_input_node。首先获得节点运行时所需处理的接收队列向量(p),其次,遍历向量中的每个接收队列,逐一处理,其中接收队列所属的接口处于UP状态,才需要处理。

接收队列向量(p)中的结构vnet_hw_if_rxq_poll_vector_t包含两个成员:virtio接口的索引值(dev_instance),和接收队列索引值(queue_id)。函数virtio_device_input_inline处理设备对应的队列。

节点结构体vlib_node_runtime_t的初始化参见VPP接口INPUT节点运行数据。virtio input节点在不同的线程拥有不同的node运行数据,例如不同线程的virtio input函数处理同一个virtio接口的不同队列。

VLIB_NODE_FN (virtio_input_node) (vlib_main_t * vm,vlib_node_runtime_t * node, vlib_frame_t * frame)
{u32 n_rx = 0;virtio_main_t *vim = &virtio_main;vnet_hw_if_rxq_poll_vector_t *p,*pv = vnet_hw_if_get_rxq_poll_vector (vm, node);vec_foreach (p, pv) {virtio_if_t *vif;vif = vec_elt_at_index (vim->interfaces, p->dev_instance);if (vif->flags & VIRTIO_IF_FLAG_ADMIN_UP){if (vif->type == VIRTIO_IF_TYPE_TAP)n_rx += virtio_device_input_inline (vm, node, frame, vif, p->queue_id, VIRTIO_IF_TYPE_TAP);else if (vif->type == VIRTIO_IF_TYPE_TUN)n_rx += virtio_device_input_inline (vm, node, frame, vif, p->queue_id, VIRTIO_IF_TYPE_TUN);}}return n_rx;

节点state为中断状态VLIB_NODE_STATE_INTERRUPT,由函数vnet_hw_if_generate_rxq_int_poll_vector获取当前已经产生的中断,生成需要处理的向量pv。

否则,节点state不等于中断VLIB_NODE_STATE_INTERRUPT,使用rxq_vector_poll为所需轮询的向量。

以上都不成立的情况下,节点state为VLIB_NODE_STATE_POLLING,返回向量rxq_vector_int。节点的运行state由其处理的所有接收队列来决定,如果其中存在接收队列为VNET_HW_IF_RX_MODE_POLLING接收模式,节点的state优先使用VLIB_NODE_STATE_POLLING。

static_always_inline vnet_hw_if_rxq_poll_vector_t *
vnet_hw_if_get_rxq_poll_vector (vlib_main_t *vm, vlib_node_runtime_t *node)
{  vnet_hw_if_rx_node_runtime_t *rt = (void *) node->runtime_data;vnet_hw_if_rxq_poll_vector_t *pv = rt->rxq_vector_int;if (PREDICT_FALSE (node->state == VLIB_NODE_STATE_INTERRUPT))pv = vnet_hw_if_generate_rxq_int_poll_vector (vm, node);else if (node->flags & VLIB_NODE_FLAG_ADAPTIVE_MODE)pv = rt->rxq_vector_poll;return pv;
}

此函数仅运行在节点状态为VLIB_NODE_STATE_INTERRUPT时,遍历向量rxq_interrupts,依次找到发生中断的接收队列,将接收队列对应的接口索引和队列索引,添加到rxq_vector_int向量中,此向量之后作为函数返回值。清除rxq_interrupts中记录的中断队列值(int_num)。

vnet_hw_if_rxq_poll_vector_t *
vnet_hw_if_generate_rxq_int_poll_vector (vlib_main_t *vm, vlib_node_runtime_t *node)
{vnet_hw_if_rx_node_runtime_t *rt = (void *) node->runtime_data;vnet_main_t *vnm = vnet_get_main ();int int_num = -1;ASSERT (node->state == VLIB_NODE_STATE_INTERRUPT);vec_reset_length (rt->rxq_vector_int);while ((int_num = clib_interrupt_get_next (rt->rxq_interrupts, int_num)) != -1){vnet_hw_if_rx_queue_t *rxq = vnet_hw_if_get_rx_queue (vnm, int_num);vnet_hw_if_rxq_poll_vector_t *pv;clib_interrupt_clear (rt->rxq_interrupts, int_num);vec_add2 (rt->rxq_vector_int, pv, 1);pv->dev_instance = rxq->dev_instance;pv->queue_id = rxq->queue_id;}return rt->rxq_vector_int;

如下,vpp_wk_0线程中,virtio-input节点运行状态为polling。

vpp# show runtime
Thread 1 vpp_wk_0 (lcore 2)
Time 33.3, 10 sec internal node vector rate 0.00 loops/sec 6111789.66vector rates in 1.0214e0, out 1.0214e0, drop 0.0000e0, punt 0.0000e0Name                 State         Calls          Vectors        Suspends         Clocks       Vectors/Call
dpdk-input                       polling         232754435               0               0          1.48e2            0.00
ethernet-input                   active                 34              34               0          6.34e3            1.00
virtio-input                     polling         193182449              34               0          1.33e9            0.00
http://www.lryc.cn/news/30863.html

相关文章:

  • 《计算机网络:自顶向下方法》学习笔记——第一章:计算机网络和因特网
  • PDF 解析格式化输出 API 数据接口
  • RL笔记:基于策略迭代求CliffWaking-v0最优解(python实现)
  • 350. 两个数组的交集 II
  • Android仿微信选择图片
  • python+嵌入式——串口通信篇(收发解包)
  • 剖析G1 垃圾回收器
  • 如何打造一款专属于自己的高逼格电脑桌面
  • 【C++】string的使用及其模拟实现
  • 怀念在青鸟的日子
  • 学习记录---Python内置类型
  • Python笔记 -- 列表
  • 谈谈UVM中的uvm_info打印
  • 矩阵理论1 集合上的等价关系(equivalence relations on a set S)
  • 【网络监控】Zabbix详细安装部署(最全)
  • 阿里云轻量服务器--Docker--Nacos安装(使用外部Mysql数据存储)
  • unity开发知识点小结01
  • 软件系统[软件工程]
  • 电力系统稳定性的定义与分类
  • 基于java的俱乐部会员管理系统
  • 线程池执行父子任务,导致线程死锁
  • Ubuntu系统新硬盘挂载
  • 【亲测】Centos7系统非管理(root)权限编译NCNN
  • 四种常见的异步请求方式
  • Linux操作系统学习(进程间通信)
  • 单目标追踪——【相关滤波】C-COT原理与ECO基于C-COT的改进
  • C++中栈是如何实现,以及常用的栈函数都有哪些
  • 我就不信你还不懂HashSet/HashMap的底层原理
  • Qt中调用gtest进行单元测试及生成覆盖率报告
  • ChatGPT vs Bard 背后的技术对比分析和未来发展趋势