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

智能网卡之hinic3 WQE(Work Queue Element)结构梳理

hinic3 WQE(Work Queue Element)结构详解

本文基于 hinic3 驱动源码,对 WQE(Work Queue Element)做详细讲解。如需查阅完整源码和结构体定义可参考hinic3_nic_qp.h等文件。


1. WQE 的作用

  • WQE(Work Queue Element):网卡芯片可识别的数据格式。
  • sk_buff:Linux 协议栈中的数据结构,硬件不可直接识别。
  • 驱动作用:负责将 sk_buff 转换为 WQE,供硬件使用。

类比

+---------------------+        转换        +------------------+        交互
|   上层 sk_buff      |  ------------->    |      WQE         |  ---->  网卡芯片
+---------------------+        驱动        +------------------+        硬件

2. SQ队列与wqebb

  • SQ:发送队列(Send Queue)。
  • wqebb(Work Queue Element Basic Block):SQ的最小分配单元,每个大小为16字节(16B)。
  • 最大深度:16K(16384)个 wqebb。
  • 一个WQE 可以包括多个 wqebb。
+---------+---------+---------+ ... +---------+
| wqebb 0 | wqebb 1 | wqebb 2 | ... | wqebb N |
+---------+---------+---------+ ... +---------+|<---  一个WQE由多个wqebb组成  --->|

相关宏定义见 hinic3_nic_io.h:

#define HINIC3_SQ_WQEBB_SHIFT 4
#define HINIC3_SQ_WQEBB_SIZE  BIT(HINIC3_SQ_WQEBB_SHIFT) // 16B

3. SQ WQE 的三种类型

设计目的

为提升端到端性能,hinic3 的 SQ WQE 结构支持三种类型:

  • 1. Extended SQ WQE with normal TS(支持无状态卸载,结构最复杂,支持各种 offload)
  • 2. Extended SQ WQE with small TS(不支持无状态卸载,支持多SGE)
  • 3. Compact SQ normal WQE(不支持无状态卸载,且只含单SGE,结构最简单)

4. WQE 结构与bit详细解析

4.1 Extended SQ WQE with normal TS(支持无状态卸载)

结构组成
  • CTRL(Control Segment):描述WQE属性、部分卸载信息
  • TASK:状态卸载标志(16B)
  • BDSL(Buffer Descriptor Segment List):指向数据块的指针数组
  • QSF:卸载相关任务字段
结构框图

在这里插入图片描述

CTRL字段详细bit位解释(来自hinic3_nic_qp.h)
字段含义
OOwner bit,在队列翻转时,需要进行 obit 的翻转
ECwqe type: 1’b1 - extended wqe type;1’b0 - compact wqe type
DN1’b1 - Direct wqe type;1’b0 - Normal wqe type,NIC 默认设置为 0
DFData format:1’b0 – SGL;1’b1 - inline data,NIC 使用 SGL 方式
TSTask section size:1’b1 - 16B;1’b0 - 46bit
BDSLSGE number(包括 wqe header 和 BDSL section 中的 sge 数量)

相关宏定义:

#define SQ_CTRL_BD0_LEN_SHIFT 0
#define SQ_CTRL_RSVD_SHIFT 18
#define SQ_CTRL_BUFDESC_NUM_SHIFT 19
#define SQ_CTRL_TASKSECT_LEN_SHIFT 27
#define SQ_CTRL_DATA_FORMAT_SHIFT 28
#define SQ_CTRL_DIRECT_SHIFT 29
#define SQ_CTRL_EXTENDED_SHIFT 30
#define SQ_CTRL_OWNER_SHIFT 31#define SQ_CTRL_BD0_LEN_MASK 0x3FFFFU
#define SQ_CTRL_RSVD_MASK 0x1U
#define SQ_CTRL_BUFDESC_NUM_MASK 0xFFU
#define SQ_CTRL_TASKSECT_LEN_MASK 0x1U
#define SQ_CTRL_DATA_FORMAT_MASK 0x1U
#define SQ_CTRL_DIRECT_MASK 0x1U
#define SQ_CTRL_EXTENDED_MASK 0x1U
#define SQ_CTRL_OWNER_MASK 0x1U
TASK字段结构(16B)

在这里插入图片描述
相关宏定义:

#define SQ_TASK_INFO0_TUNNEL_FLAG_SHIFT 19
#define SQ_TASK_INFO0_ESP_NEXT_PROTO_SHIFT 22
#define SQ_TASK_INFO0_INNER_L4_EN_SHIFT 24
#define SQ_TASK_INFO0_INNER_L3_EN_SHIFT 25
#define SQ_TASK_INFO0_INNER_L4_PSEUDO_SHIFT 26
#define SQ_TASK_INFO0_OUT_L4_EN_SHIFT 27
#define SQ_TASK_INFO0_OUT_L3_EN_SHIFT 28
#define SQ_TASK_INFO0_OUT_L4_PSEUDO_SHIFT 29
#define SQ_TASK_INFO0_ESP_OFFLOAD_SHIFT 30
#define SQ_TASK_INFO0_IPSEC_PROTO_SHIFT 31#define SQ_TASK_INFO0_TUNNEL_FLAG_MASK 0x1U
#define SQ_TASK_INFO0_ESP_NEXT_PROTO_MASK 0x3U
#define SQ_TASK_INFO0_INNER_L4_EN_MASK 0x1U
#define SQ_TASK_INFO0_INNER_L3_EN_MASK 0x1U
#define SQ_TASK_INFO0_INNER_L4_PSEUDO_MASK 0x1U
#define SQ_TASK_INFO0_OUT_L4_EN_MASK 0x1U
#define SQ_TASK_INFO0_OUT_L3_EN_MASK 0x1U
#define SQ_TASK_INFO0_OUT_L4_PSEUDO_MASK 0x1U
#define SQ_TASK_INFO0_ESP_OFFLOAD_MASK 0x1U
#define SQ_TASK_INFO0_IPSEC_PROTO_MASK 0x1U
QSF 字段(主要和卸载相关)
FieldRangeComments
pri[31:29]RSV
Uc[28]RSV
sctp[27]Sctp packet.
mss[26:13]mss
tcp_udp_cs[12]RSV
tso[11]Transmit segmentation offload is activated when the tso flag is set.
Not support TSO, when pkt_type=2’b01;
ufo[10]For UDP packet, engine reads the whole UDP packet from host by 1 DMA read, and IPSU calculates UDP checksum, uCode does IP segment.
Pld_ofs[9:2]Pkt_type = 2’b00:
Payload offset. It is the start position to calculate tcp/udp checksum or sctp CRC.
Unit is 2B, the max value is 239 (239*2=478B)
Pkt_type = 2’b01:
Bit9:5 – RSV
Bit4:2 – cmd_code to AAD
Pkt_type[1:0]pkt_type:
2’b00 – normal sq WQE;
2’b01 – sq direct-forward WQE;
Others – RSV;

相关宏定义:

#define SQ_CTRL_QUEUE_INFO_PKT_TYPE_SHIFT 0
#define SQ_CTRL_QUEUE_INFO_PLDOFF_SHIFT 2
#define SQ_CTRL_QUEUE_INFO_UFO_SHIFT 10
#define SQ_CTRL_QUEUE_INFO_TSO_SHIFT 11
#define SQ_CTRL_QUEUE_INFO_TCPUDP_CS_SHIFT 12
#define SQ_CTRL_QUEUE_INFO_MSS_SHIFT 13
#define SQ_CTRL_QUEUE_INFO_SCTP_SHIFT 27
#define SQ_CTRL_QUEUE_INFO_UC_SHIFT 28
#define SQ_CTRL_QUEUE_INFO_PRI_SHIFT 29#define SQ_CTRL_QUEUE_INFO_PKT_TYPE_MASK 0x3U
#define SQ_CTRL_QUEUE_INFO_PLDOFF_MASK 0xFFU
#define SQ_CTRL_QUEUE_INFO_UFO_MASK 0x1U
#define SQ_CTRL_QUEUE_INFO_TSO_MASK 0x1U
#define SQ_CTRL_QUEUE_INFO_TCPUDP_CS_MASK 0x1U
#define SQ_CTRL_QUEUE_INFO_MSS_MASK 0x3FFFU
#define SQ_CTRL_QUEUE_INFO_SCTP_MASK 0x1U
#define SQ_CTRL_QUEUE_INFO_UC_MASK 0x1U
#define SQ_CTRL_QUEUE_INFO_PRI_MASK 0x7U
BDSL(Buffer Descriptor Segment List)

由若干个 struct hinic3_sq_bufdesc 组成,每个struct hinic3_sq_bufdesc 结构体可以包含一个SGE 数据:

struct hinic3_sq_bufdesc {u32 len;     // 31bit长度u32 rsvd;u32 hi_addr; // 高32位物理地址u32 lo_addr; // 低32位物理地址
};

4.2 Extended SQ WQE with small TS(不支持无状态卸载,多SGE)

  • 结构类似normal TS,但不能用offload。
  • BDSL部分要求sge_num >= 2,CTRL里可以带一个SGE指针。
    在这里插入图片描述

4.3 Compact SQ normal WQE(单SGE,极简)

  • 只占用1个wqebb(16B),极致精简。
  • 适用于不需要offload且报文只含1个SGE的场景。
    在这里插入图片描述

5. Doorbell 结构详解

驱动填充完WQE后,用doorbell机制通知硬件。hinic3采用64bit doorbell,结构如下:

Doorbell数据结构(hinic3_nic_io.h)

struct hinic3_nic_db {u32 db_info;u32 pi_hi;
};

db_info字段按位解释:
在这里插入图片描述

  • QID[12:0]:队列编号
  • CFLAG[23]:0表示SQ, 1表示RQ
  • Cos[26:24]:优先级
  • Type[31:27]:类型(一般1)
  • PI: Producer Index
    相关宏定义:
#define DB_INFO_QID_SHIFT          0
#define DB_INFO_NON_FILTER_SHIFT   22
#define DB_INFO_CFLAG_SHIFT        23
#define DB_INFO_COS_SHIFT          24
#define DB_INFO_TYPE_SHIFT         27#define DB_INFO_QID_MASK           0x1FFFU
#define DB_INFO_NON_FILTER_MASK    0x1U
#define DB_INFO_CFLAG_MASK         0x1U
#define DB_INFO_COS_MASK           0x7U
#define DB_INFO_TYPE_MASK          0x1FU

6. RQ WQE 结构与bit详细解析

6.1 RQ WQE 结构体

hinic3 的 RQ(Receive Queue)WQE 主要有两种结构:普通模式和扩展模式。其核心结构体如下:

struct hinic3_rq_normal_wqe {u32 buf_hi_addr;u32 buf_lo_addr;u32 cqe_hi_addr;u32 cqe_lo_addr;
};struct hinic3_rq_extend_wqe {struct hinic3_sge_sect buf_desc;struct hinic3_sge_sect cqe_sect;
};struct hinic3_rq_wqe {union {struct hinic3_rq_normal_wqe normal_wqe;struct hinic3_rq_extend_wqe extend_wqe;};
};
  • buf_hi_addr / buf_lo_addr:数据缓冲区物理地址高/低 32 位。
  • cqe_hi_addr / cqe_lo_addr:CQE 缓冲区物理地址高/低 32 位。
  • buf_desc / cqe_sect:扩展模式下的 SGE 描述符。

由结构体可见,RQ WQE 也是16byte。其内存分配和管理与SQ WQE共用一套代码和接口。有差异的是结构体中每bit 的含义不一样。

6.2 RQ CQE 结构体

硬件收包后会写入 CQE(Completion Queue Element),结构如下:

struct hinic3_rq_cqe {u32 status;u32 vlan_len;u32 offload_type;u32 hash_val;u32 xid;u32 decrypt_info;u32 rsvd6;u32 pkt_info;
};

RQ WQE/CQE 结构框图

+-------------------+-------------------+-------------------+-------------------+
|   status (32b)    |  vlan_len (32b)   | offload_type (32b)|   hash_val (32b)  |
+-------------------+-------------------+-------------------+-------------------+
|    xid (32b)      | decrypt_info(32b) |   rsvd6 (32b)     |  pkt_info (32b)   |
+-------------------+-------------------+-------------------+-------------------+
主要字段说明
字段含义
status状态字段,包含校验和错误、LRO、RXDONE 等信息
vlan_len高 16 位为 VLAN Tag,低 16 位为包长度
offload_type硬件卸载类型,包含包类型、IP 类型、VLAN、RSS 等
hash_valRSS Hash 值
xid交换 ID
decrypt_info解密相关信息
pkt_info超级 CQE、包数、首包/尾包长度等

6.3 关键bit位与宏定义

1. offload_type 字段
字段位宽/偏移说明
PKT_TYPE[4:0]包类型
IP_TYPE[6:5]IP 类型
ENC_L3_TYPE[7]封装 L3 类型
TUNNEL_FMT[11:8]隧道包格式
PKT_UMBCAST[20:19]组播/广播
VLAN_EN[21]VLAN 有效
RSS_TYPE[31:24]RSS 类型

相关宏定义:

#define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_SHIFT 0
#define RQ_CQE_OFFOLAD_TYPE_IP_TYPE_SHIFT 5
#define RQ_CQE_OFFOLAD_TYPE_ENC_L3_TYPE_SHIFT 7
#define RQ_CQE_OFFOLAD_TYPE_TUNNEL_PKT_FORMAT_SHIFT 8
#define RQ_CQE_OFFOLAD_TYPE_PKT_UMBCAST_SHIFT 19
#define RQ_CQE_OFFOLAD_TYPE_VLAN_EN_SHIFT 21
#define RQ_CQE_OFFOLAD_TYPE_RSS_TYPE_SHIFT 24#define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_MASK 0x1FU
#define RQ_CQE_OFFOLAD_TYPE_IP_TYPE_MASK 0x3U
#define RQ_CQE_OFFOLAD_TYPE_ENC_L3_TYPE_MASK 0x1U
#define RQ_CQE_OFFOLAD_TYPE_TUNNEL_PKT_FORMAT_MASK 0xFU
#define RQ_CQE_OFFOLAD_TYPE_PKT_UMBCAST_MASK 0x3U
#define RQ_CQE_OFFOLAD_TYPE_VLAN_EN_MASK 0x1U
#define RQ_CQE_OFFOLAD_TYPE_RSS_TYPE_MASK 0xFFU
2. vlan_len 字段
  • 高 16 位为 VLAN Tag,低 16 位为包长度。

相关宏定义:

#define RQ_CQE_SGE_VLAN_SHIFT 0
#define RQ_CQE_SGE_LEN_SHIFT 16#define RQ_CQE_SGE_VLAN_MASK 0xFFFFU
#define RQ_CQE_SGE_LEN_MASK 0xFFFFU
3. status 字段
字段位宽/偏移说明
CSUM_ERR[15:0]校验和错误
NUM_LRO[23:16]LRO 包数
LRO_PUSH[25]LRO 推送
LRO_ENTER[26]LRO 进入
LRO_INTR[27]LRO 中断
FLUSH[28]Flush 标志
DECRY_PKT[29]解密包
BP_EN[30]BP 使能
RXDONE[31]收包完成

相关宏定义:

#define RQ_CQE_STATUS_CSUM_ERR_SHIFT 0
#define RQ_CQE_STATUS_NUM_LRO_SHIFT 16
#define RQ_CQE_STATUS_LRO_PUSH_SHIFT 25
#define RQ_CQE_STATUS_LRO_ENTER_SHIFT 26
#define RQ_CQE_STATUS_LRO_INTR_SHIFT 27#define RQ_CQE_STATUS_BP_EN_SHIFT 30
#define RQ_CQE_STATUS_RXDONE_SHIFT 31
#define RQ_CQE_STATUS_DECRY_PKT_SHIFT 29
#define RQ_CQE_STATUS_FLUSH_SHIFT 28#define RQ_CQE_STATUS_CSUM_ERR_MASK 0xFFFFU
#define RQ_CQE_STATUS_NUM_LRO_MASK 0xFFU
#define RQ_CQE_STATUS_LRO_PUSH_MASK 0X1U
#define RQ_CQE_STATUS_LRO_ENTER_MASK 0X1U
#define RQ_CQE_STATUS_LRO_INTR_MASK 0X1U
#define RQ_CQE_STATUS_BP_EN_MASK 0X1U
#define RQ_CQE_STATUS_RXDONE_MASK 0x1U
#define RQ_CQE_STATUS_FLUSH_MASK 0x1U
#define RQ_CQE_STATUS_DECRY_PKT_MASK 0x1U
4. pkt_info 字段
  • 超级 CQE、包数、首包/尾包长度等。

相关宏定义:

#define RQ_CQE_SUPER_CQE_EN_MASK 0x1
#define RQ_CQE_PKT_NUM_MASK 0x1FU
#define RQ_CQE_PKT_FIRST_LEN_MASK 0x1FFFU
#define RQ_CQE_PKT_LAST_LEN_MASK 0x1FFFU
5. decrypt_info 字段
  • 解密状态、ESP next header。

相关宏定义:

#define RQ_CQE_DECRY_INFO_DECRY_STATUS_SHIFT 8
#define RQ_CQE_DECRY_INFO_ESP_NEXT_HEAD_SHIFT 0#define RQ_CQE_DECRY_INFO_DECRY_STATUS_MASK 0xFFU
#define RQ_CQE_DECRY_INFO_ESP_NEXT_HEAD_MASK 0xFFU

6.4 RQ CQE 字段解析流程示例

static inline u32 hinic3_get_pkt_len_for_super_cqe(const struct hinic3_rq_cqe *cqe, bool last)
{u32 pkt_len = hinic3_hw_cpu32(cqe->pkt_info);if (!last)return RQ_CQE_PKT_LEN_GET(pkt_len, FIRST_LEN);elsereturn RQ_CQE_PKT_LEN_GET(pkt_len, LAST_LEN);
}

http://www.lryc.cn/news/2405053.html

相关文章:

  • go的工具库:github.com/expr-lang/expr
  • 力扣HOT100之二分查找:4. 寻找两个正序数组的中位数
  • PyTorch——损失函数与反向传播(8)
  • macOS 升级 bash 到最新版本
  • Linux下如何查看一个端口被什么进程占用? 该进程又打开了哪些文件?
  • 力扣面试150题--课程表
  • 用通俗的话解释下MCP是个啥?
  • LeetCode 高频 SQL 50 题(基础版)之 【子查询】· 上
  • Spark流水线+Gravitino+Marquez数据血缘采集
  • 一个完整的时间序列异常检测系统,使用Flask作为后端框架,实现了AE(自编码器)、TimesNet和LSTM三种模型,并提供可视化展示
  • 深度学习在非线性场景中的核心应用领域及向量/张量数据处理案例,结合工业、金融等领域的实际落地场景分析
  • 基于微信小程序的车位共享平台的设计与实现源码数据库文档
  • 多模态大语言模型arxiv论文略读(111)
  • 网页端 VUE+C#/FastAPI获取客户端IP和hostname
  • 一个自动反汇编脚本
  • 函数与数列的交汇融合
  • 怎么让自己ip显示外省?一文说清操作
  • 【Docker】容器安全之非root用户运行
  • 汽车车载软件平台化项目规模颗粒度选择的一些探讨
  • 【八股消消乐】构建微服务架构体系—服务注册与发现
  • 大数据+智能零售:数字化变革下的“智慧新零售”密码
  • C++_核心编程_菱形继承
  • 掌握Git核心:版本控制、分支管理与远程操作
  • c#,Powershell,mmsys.cpl,使用Win32 API展示音频设备属性对话框
  • STM标准库-TIM旋转编码器
  • 深入解析JVM工作原理:从字节码到机器指令的全过程
  • MCP通信方式之Streamable HTTP
  • 第七十三篇 从电影院售票到停车场计数:生活场景解析Java原子类精髓
  • 【原创】基于视觉模型+FFmpeg+MoviePy实现短视频自动化二次编辑+多赛道
  • C++----剖析list