DPDK之l3fwd-power源码解析
引言
l3fwd-power是DPDK基于网络层的转发示例,该示例演示了五种电源管理策略的使用方法。
1 源码概述
1.1 关键变量
- app_mode
运行模式,有五种运行模式:APP_MODE_LEGACY、APP_MODE_EMPTY_POLL、APP_MODE_TELEMETRY、APP_MODE_INTERRUPT、APP_MODE_PMD_MGMT - hp_lcores
支持睿频的CPU核ID数组,数组长度为nb_hp_lcores; - lcore_params
指向struct lcore_params数组,数组每项表示网卡号为port_id的接收队列号queue_id由核lcore_id处理 - lcore_conf
指向struct lcore_conf数组,数组每项表示ID为数组索引的CPU核处理的接收队列和发送队列等信息
1.2 数据结构
- struct lcore_conf
struct lcore_conf {
//rx_queue_list有效数组长度
uint16_t n_rx_queue;
//数组每项表示对应核须要处理的对应网卡的接收队列信息(包括port_id和queue_id信息)
struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE];
//tx_port_id有效数组长度
uint16_t n_tx_port;
//所有有效网卡号port id组成的升序数组
uint16_t tx_port_id[RTE_MAX_ETHPORTS];
//数组索引为网卡port_id,数组每项为发送队列ID。即每个网卡号在每个核配置一个发送队列
uint16_t tx_queue_id[RTE_MAX_ETHPORTS];
//数组索引为网卡port_id,数组每项为发送缓存
struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS];
//ipv4与ipv4的路由查找对象
lookup_struct_t * ipv4_lookup_struct;
lookup_struct_t * ipv6_lookup_struct;
} __rte_cache_aligned;
2 源码解析
本用例共支持五种运行模式,每种运行模式有不同的电源管理策略
2.1 LEGACY模式
LEGACY模式由应用直接调用DPDK封装的CPU调频接口。具体策略如下:
- 首先,网卡接收到空包,它会记录网卡连续接收到空包的次数zero_rx_packet_count,并计算触发阻塞等待的模式值idle_hint;若网卡接收到数据包,将zero_rx_packet_count置0,并逐次上调freq_up_hint值;
- 当对应核处理的所有接收队列都连续接收到空包,那么进入阻塞状态;阻塞模式分为长时间等待事件模式和短时间阻塞模式:前者是所有的队列的idle_hint值都是长时间值,否则就是后者短时间阻塞模式;
- 当有部分队列收到空包或全部接收到数据包,取最大的freq_up_hint值上调CPU频率。
注:在每次轮询和每次接收数据包以及阻塞都会叠加相关的统计值。当累计阻塞时间大于一定值或成功接收到数据包占沦陷次数比例低于一定值都会在定时器中被检测到,并触发对CPU降频操作。且定时器每次执行都会将相关统计值清零。
2.2 EMPTY_POLL模式
EMPTY_POLL模式本质上与LEGACY模式一样是依赖于DPDK封装的电源管理策略接口。不同的是:EMPTY_POLL是依赖于DPDK封装好的对CPU升频降频策略。具体步骤如下:
- 启动业务线程前,调用rte_power_empty_poll_stat_init初始化策略;
- 业务线程接收到空包,调用一次rte_power_empty_poll_stat_update;接收到包,调用一次rte_power_poll_stat_update;
- 主线程开启定时器,定时执行rte_empty_poll_detection,该函数会根据策略执行CPU的频率设置。
2.3 TELEMETRY模式
2.4 INTERRUPT模式
2.5 PMD_MGMT模式
PMD_MGMT模式也是依赖于DPDK封装的电源管理策略。它比rte_power_empty_poll_系列策略更精细。具体步骤如下:
- 启动业务线程前,调用rte_power_ethdev_pmgmt_queue_enable启动对每个队列的电源管理策略;
- 程序结束,调用rte_power_ethdev_pmgmt_queue_disable关闭对每个队列的电源管理。
注:由于rte_power_ethdev_pmgmt_queue_enable函数会在接收队列上注册回调函数,由回调函数实现信息统计和相关电源管理策略功能。所以不需要业务线程执行有关电源管理的相关操作。
3 主要API
3.1 CPU调频接口
- enum power_management_env
表示底层的CPU变频实现方式,支持ACPI、PSTATE、CPPC、KVM_VM四种方式; - rte_power_init / rte_power_exit
前者用于初始化对应CPU核的CPU调频接口,依次优先使用ACPI、PSTATE、CPPC、KVM_VM模式;后者是释放对应CPU核的CPU调频接口; - rte_power_get_capabilities / rte_power_freqs
前者获取cpu核的睿频能量;后者获取cpu核支持的频率值; - rte_power_freq_enable_turbo / rte_power_freq_disable_turbo / rte_power_turbo_status
rte_power_freq_enable_turbo用于启动cpu核的睿频功能;rte_power_freq_disable_turbo用于关闭cpu核的睿频功能;rte_power_turbo_status用于查询cpu核是否开启了睿频 - rte_power_freq_max / rte_power_freq_min
前者将cpu频率调到最大;后者将cpu频率调到最小; - rte_power_freq_up / rte_power_freq_down
前者将cpu频率调高一档;后者将cpu频率调低一档; - rte_power_set_freq / rte_power_get_freq
前者设置频率;后者获取频率;
3.2 empty_poll电源管理接口
- rte_power_empty_poll_stat_init / rte_power_empty_poll_stat_free
前者初始化电源管理策略;后者注销电源管理策略; - rte_power_empty_poll_stat_update / rte_power_poll_stat_update
每接收一次空包调用一次前者;每接收一次数据包调用一次后者; - rte_empty_poll_detection
定时执行该函数实现电源策略控制
3.3 pmd电源管理接口
- rte_power_pmd_mgmt_set_emptypoll_max / rte_power_pmd_mgmt_set_pause_duration
前者设置最大空轮询次数,超过设定值执行电源管理策略降频或等待;后者设置执行等待的最大时间,单位us; - rte_power_pmd_mgmt_set_scaling_freq_max / rte_power_pmd_mgmt_set_scaling_freq_min
前者设置变频策略可设置的最大值频率值;后者设置变频策略可设置的最小频率值; - rte_power_ethdev_pmgmt_queue_enable / rte_power_ethdev_pmgmt_queue_disable
前者启动核lcore_id对网卡port_id的queue_id队列的电源管理策略;后者是关闭核lcore_id对网卡port_id的queue_id队列的电源管理策略;
3.4 中断接口
- rte_eth_dev_rx_intr_ctl_q / rte_epoll_wait
前者用于在网卡对应队列注册事件;后者用于等待指定的事件发生,调用前开启中断、调用结束关闭中断; - rte_eth_dev_rx_intr_enable / rte_eth_dev_rx_intr_disable
前者用于打开网卡对应队列的中断;后者用于关闭网卡对应队列的中断;
3.5 ip路由接口
相关API集中在setup_lpm和l3fwd_simple_forward函数中