从0开始学PCIE 6.3 - Transaction Layer_4

2.2.6 事务描述符(Transaction Descriptor)

2.2.6.1 概述

事务描述符是一种在**请求者(Requester)完成者(Completer)**之间传递事务相关信息的机制。事务描述符由三个字段构成:

  • 事务ID(Transaction ID):用于标识尚未完成的挂起事务
  • 属性字段(Attributes field):规定事务的各项特征
  • 流量类别字段(Traffic Class (TC) field):将事务与所需要的服务类型进行关联

图2-33展示了事务描述符的各个字段。注意:图中将这些字段放在一起展示,是为了凸显它们作为同一个逻辑实体的关联关系;这些字段在TLP报文头部物理上并不是连续排布的

事务描述符

字段排布逻辑(逻辑视图,非报文实际DW连续布局):

  • 事务ID:由【请求者ID Requester ID[15:0]】 + 【标签Tag[13:0]】拼接
  • Attributes:[2:0]位域
  • Traffic Class(TC):[2:0]位域

2.2.6.2 事务描述符 — 事务ID字段

事务ID字段由两大子字段组成:请求者ID(Requester ID)标签(Tag),参见图2(768‑48=720)34。

图2(768‑48=720)34 事务ID

事务ID = Requester ID[15:0] + Tag[13:0]

在部分特定场景(下文定义)下,流量类别TC也会纳入事务ID的组成部分。

事务ID的用途:将完成报文(Completion)和对应的请求报文(Request)进行配对关联。 按照期望返回的完成报文类型,请求/完成报文分为三组,三组的事务ID规则各不相同;每一组拥有独立的命名空间,不同组之间不强制要求事务ID保持唯一性。各组及其高层要求如下:

  • 分组I:Cpl / CplD,适用于非UIO请求
    • 事务ID构成:Requester ID[15:0] + Tag[13:0]
    • 请求者分配Tag值时:本组所有尚未完成的非Posted请求,事务ID必须保证唯一,不受TC或其余字段影响。
  • 分组II:UIOWrCpl,适用于UIO存储器写请求(UIOMWr)
    • 事务ID构成:TC[2:0] + Requester ID[15:0] + Tag[13:0]
    • 请求者允许分配Tag,使得分组II内多个挂起请求可以复用同一个事务ID(参考2.2.9.2节)
  • 分组III:UIORdCpl、UIORdCplD,适用于UIO存储器读请求(UIOMRd)
    • 事务ID构成:TC[2:0] + Requester ID[15:0] + Tag[13:0]
    • 请求者分配Tag值时:本组所有挂起请求,事务ID必须保证唯一。

Tag标签位宽架构定义

协议架构定义4种Tag位宽:14bit、10bit、8bit、5bit。 同一个功能模块,作为请求者和作为完成者时,可以支持不同的Tag位宽。下面为Tag运行相关规则,另参见本节后面“大Tag能力实现注意事项”实现注释:

  1. 14(768‑48=720)bit Tag、10(768‑48=720)bit Tag统称为大标签(larger Tags)
  2. 8(768‑48=720)bit Tag、5(768‑48=720)bit Tag统称为小标签(smaller Tags)
  3. 所有功能模块必须支持8bit Tag完成者能力
    • UIO完成者,必须支持14(768‑48=720)bit Tag
  4. 支持Flit模式的功能模块,必须具备14(768‑48=720)bit Tag完成者能力,自动兼容10(768‑48=720)bit Tag完成者能力。
  5. 工作速率16.0GT/s及以上速率的功能模块(包含交换机内部功能),必须支持10(768‑48=720)bit Tag完成者能力
  6. 功能模块不能仅开启14bit Tag请求者能力,必须同时具备14bit Tag完成者能力;同理,10bit Tag请求者能力依赖本机10bit Tag完成者能力。
  7. 非Flit模式下:Tag[8]、Tag[9]在TLP头部不和Tag其余比特连续;这两个比特在10bit Tag出现之前是保留位。 非Flit模式下,如果请求者不支持10bit Tag请求能力,必须将Tag[9:8]强制写为00b
  8. 根复合体RC内部,如果硬件标明支持14(768‑48=720)bit Tag完成者 /10(768‑48=720)bit Tag完成者,那么RC必须能够正确处理对应位宽Tag的请求报文;目标包括PIO访问的全部寄存器、RCiEP的MMIO、主机内存(DMA访问):
    • 每个支持该能力的RP(根端口),入端口收到的请求必须能正确处理,包括经过交换机内部路径转发过来的报文。
    • 如果RC包含RCiEP,并且RCiEP声明支持14/10bit Tag请求能力,RC需要正确处理来自RCiEP发往RC内部目标(主机内存、RCiEP的MMIO寄存器)的请求。
  9. 接收端/完成者行为规则
    • 无论扩展Tag字段使能位(7.5.3.4节)是什么状态,接收/完成者必须能够正确解析8bit Tag值;PCIe转PCI(768‑48=720)X桥的细节见桥接规范。
    • 如果完成者硬件支持14(768‑48=720)bit /10(768‑48=720)bit Tag完成能力,无论本端Tag请求使能位的设置,收到的对应大Tag报文都必须正确解析。
  10. PCIe(768‑48=720)to(768‑48=720)PCI/PCI(768‑48=720)X桥不支持14bit/10bit大Tag能力;桥不要求实现大Tag的请求者/完成者能力。
  11. 当一个端点的大Tag请求者使能位被置位,遵循下面规则:
    • 端点同时置位14bit(768‑48=720)Tag请求使能、10bit(768‑48=720)Tag请求使能:访问主机内存的请求允许使用14bit Tag。硬件实现层面可以做限制,把报文降级使用10bit或者更小Tag;除非主机侧完成端支持14bit Tag完成能力,否则通用软件/固件不要置位14(768‑48=720)bit Tag请求使能位
    • 如果端点要向**其他端点(非主机内存)**发请求:只有硬件确认对端端点具备对应大Tag完成者能力,才允许发送大Tag请求。部分实现可以完全不向别的端点发送大Tag报文。更复杂策略不在本协议规范范围内。
    • 对于PIO请求者具备大Tag请求能力:何时选用大Tag、何时小Tag,规范不做强制。典型方案:PIO访问用小Tag;内部DMA数据搬运硬件使用大Tag,复用同一个Requester ID;P2P请求也可以采用类似方案。
    • 非UIO请求/完成报文,14(768‑48=720)bit Tag有效值规则: 协议历史版本存在歧义,推荐行为:除0000b之外,Tag[13:10]全部合法;14bit请求者不要生成Tag[13:10]=0000b。这样收到完成报文时,就可以识别Tag非法;为兼容旧设备,硬件允许生成Tag[13:8]不等于000000b的值。UIO请求/完成报文的Tag[13:0]全部取值都允许。
    • 10(768‑48=720)bit Tag取值约束Tag[9:8] !=00b才是合法Tag;请求者禁止发出Tag[9:8]=00b。收到完成报文,如果出现该值,代表对端完成者不支持10bit Tag。
    • 请求者向不支持对应大Tag完成能力的Completer发送大Tag请求:返回的Completion报文中Tag非法。该完成报文被视作意外完成报文(Unexpected Completion),默认属于建议性非致命错误,请求者按标准PCIe错误流程处理。
    • 请求者收到Tag非法的Completion,原本对应的请求会报完成超时(Completion Timeout);如果硬件有机制规避数据损坏,请求者可以屏蔽标准协议的完成超时上报,硬件自行处理。
    • 请求者同时向多类完成者发报文:一部分用大Tag,一部分用小Tag;
      • 发小Tag的请求,必须遵守对端扩展Tag字段使能位:该位清零,则Tag仅低5bit可非零;该位置1,则Tag低8bit可以非零。
      • 关键约束:当部分大Tag请求发给不支持大Tag的完成者,返回Completion时,必须保证:已经发出的大Tag编号,绝对不能和仍然挂起的小Tag编号发生别名重叠(alias),参考本节后面实现注释。
    • 扩展Tag字段使能位的硬件默认值由实现自定义;14(768‑48=720)bit Tag请求使能位、10(768‑48=720)bit Tag请求使能位上电默认值均0b

当同一个Requester发出多条非UIO(768‑48=720)Memory(768‑48=720)Write未完成请求,事务ID不唯一,此时接收/完成者行为属于未定义。 在Flit模式FM中,完成者硬件必须能够处理来自不同层级、事务ID重复的并发未完成请求;依靠报文携带的段编号(Segment numbers)区分。

  • 如果使用**幻影功能号(Phantom Function Numbers)**来提升并发挂起请求数量: 对于同一个请求者,凡是需要返回Completion的挂起请求,幻影功能号 + Tag组合必须全局唯一,与TC以及其它字段无关。
  • 如果使用**影子功能号(Shadow Functions)**扩展并发请求数量: 同一个请求者所有需要Completion的挂起请求,影子功能号 + Tag必须全局唯一,不受TC等其他字段影响。

表2(768‑48=720)11 非UIO事务:Tag使能位、Tag位宽与合法Tag取值范围

14(768‑48=720)bit Tag
请求使能
10(768‑48=720)bit Tag
请求使能
扩展Tag
字段使能
最大请求Tag位宽8bit Tag完成端
允许Tag范围
10(768‑48=720)bit Tag完成端
允许Tag范围
14(768‑48=720)bit Tag完成端
允许Tag范围
0005 bits0(768‑48=720)310(768‑48=720)310(768‑48=720)31
0018 bits0(768‑48=720)2550(768‑48=720)2550(768‑48=720)255
01010 bits0(768‑48=720)31256(768‑48=720)1023256(768‑48=720)1023
01110 bits0(768‑48=720)255256(768‑48=720)1023256(768‑48=720)1023
10014 bits0(768‑48=720)310(768‑48=720)311024(768‑48=720)16383
10114 bits0(768‑48=720)2550(768‑48=720)2551024(768‑48=720)16383
11014 bits0(768‑48=720)31256(768‑48=720)10231024(768‑48=720)16383
11114 bits0(768‑48=720)255256(768‑48=720)10231024(768‑48=720)16383

表注释

  1. 5(768‑48=720)bit Tag完成端Tag取值永远0(768‑48=720)31,本表不再单独列出一列。
  2. “X(768‑48=720)bit Tag完成端”:代表完成者和整条报文转发路径上所有路由器件共同支持的最大公共Tag位宽。路由器件本身不是目标完成者,但检测到不可纠正错误时,路由器件可以代替完成者返回完成报文。
  3. 请求者同时向不同能力完成者发大小混合Tag报文:当大Tag请求发给不支持大Tag的完成者返回完成报文,必须保证大Tag编号不会与还没完成的小Tag发生别名冲突。

Posted请求的Tag字段规则

  • 非Flit模式:Posted请求Tag[13:8]保留字段Flit模式:Posted请求Tag[13:0]为保留字段;

    例外:[MCTP(768‑48=720)VDM]文档中定义的特殊用法不受该约束。

  • 非Flit模式下Posted请求,TH(Tag Hint)位置1Tag[7:0]字段被复用为ST[7:0]字段,详见2.2.7.1.1节。
  • 非Flit模式下Posted请求,TH位清零Tag[7:0]无定义,硬件可以是任意值;部分厂商自定义消息例外,见F(768‑48=720)1表。
    • TH=0的Posted请求,Tag[7:0]的值不能影响接收端对报文处理
    • TH=1的Posted请求,ST[7:0]会影响完成者处理报文逻辑,参考2.2.7.1.1节。

事务ID通用规则

  1. 在同一个层级(Hierarchy)内部,每一个挂起事务的事务ID必须唯一
  2. 所有请求报文、完成报文,都必须携带事务ID
  3. 请求者ID(Requester ID):16bit数值;同一个层级中,每个PCIe功能模块的Requester ID是唯一的。
  4. 功能模块必须捕获来自Type 0配置写请求中的总线号、设备号。 不使用影子功能的情况下,该总线号/设备号会填入本端发起所有请求报文的Requester ID字段。 影子功能如何修改Requester ID见7.9.25节。建议只针对成功完成的配置写请求才捕获Bus/Dev编号

    例外:根复合体内部下游端口设备的Bus/Dev分配,实现方式可以自定义。 总线号、设备号支持运行时动态修改;设备每收到一次Type0配置写,就需要重新捕获Bus、Device编号。 访问不存在的未实现Function的Type0配置写,严禁改写已经实现功能所保存捕获的Bus/Device编号。

  5. 交换机为本机产生报文(例如上报错误):必须使用该端口桥主侧对应的Requester ID;参考7.1.1节。
  6. 在收到第一次有效的配置写之前:功能模块禁止发起Non(768‑48=720)Posted请求(生成Completion报文必须要有合法Requester ID)。
    • 例外:根复合体内部组件,系统启动访问引导设备时,软件还未完成配置阶段,允许提前发起请求;符合传统PCI系统初始化模型。
  7. 设备的每个Function,必须可以响应唯一Function Number对应的配置访问;非ARI设备最多8个Function;ARI设备最多256个Function。
  8. 交换机转发报文,禁止修改事务ID;只有一种例外:FM入端口报文转发到NMF出端口,如果报文Tag[13:10]非零:出端口硬件处理方式:阻断该TLP,上报TLP Translation Egress Blocked错误(Posted报文),或者给Non(768‑48=720)Posted请求返回错误完成报文。NMF模式报文头部无法承载这部分高位Tag
  9. PCIe(768‑48=720)to(768‑48=720)PCI/PCI(768‑48=720)X桥转发来自PCI/PCI(768‑48=720)X总线的请求时,桥需要自行生成事务ID。
  10. Flit模式
    • 功能模块必须捕获Type 0配置写报文中携带的目标段号Destination Segment。设备可以选择:所有Function共用Function0捕获得到的Segment值,或者每个Function独立捕获。
    • 交换机内部全部功能共用同一个Segment值,该值由上游端口捕获;同时捕获DSV位(段捕获比特,7.7.9.4节描述)。
    • Segment可以视作Requester ID的扩展域,逻辑上是独立字段,不要和非Flit模式下事务ID概念混淆
    • 多Segment系统:每一个层级(Hierarchy)绑定唯一Segment;允许多个逻辑层级归属同一个Segment。
    • Flit模式部分场景下,TLP报文中会显式携带捕获得到的Segment号,保证跨层级之间事务ID不会冲突。

实现注释:使用幻影功能/影子功能提升并发挂起请求数量

【IMPLEMENTATION NOTE: INCREASING THE NUMBER OF OUTSTANDING REQUESTS USING PHANTOM FUNCTIONS OR SHADOW FUNCTIONS】

单纯依靠Tag比特位不够用的时候,如果开启幻影功能使能位(7.5.3.4节)或者影子功能使能位(7.9.25.3节),设备就可以使用那些没有分配给真实硬件Function的Function编号,逻辑上扩展Tag标识的空间。对于单设备,该方法可以显著提高并发Non(768‑48=720)Posted请求上限。

开启幻影功能使能位后,这些未占用的Function编号叫做幻影功能号(Phantom Function Numbers)

幻影功能存在架构层面限制:ARI设备、开启VF虚拟化后的PF/VF虚拟功能不支持幻影功能;ATS地址翻译服务、ID序IDO也无法识别幻影功能。

影子功能限制更少。因此绝大多数实现,优先使用大Tag + 影子功能,来提高并发未完成Non(768‑48=720)Posted请求数量。

实现注释:大Tag能力实现考量

【IMPLEMENTATION NOTE: CONSIDERATIONS FOR IMPLEMENTING LARGER(768‑48=720)TAG CAPABILITIES】

使用大Tag(10bit /14bit),请求者可以大幅提升并发Non(768‑48=720)Posted请求(NPR)数量。高吞吐、大往返时延RTT场景下,避免Tag资源成为带宽瓶颈。 带宽经验公式: $$BW = S * N / RTT$$

  • BW:有效载荷带宽
  • S:单次事务有效载荷大小
  • N:并发未完成NPR请求数量
  • RTT:事务往返时间

一般只有高速链路、单次事务载荷比较小的请求者,开启更大并发NPR收益明显;高RTT链路下,该特性也可以维持性能。

当请求者支持大Tag,但要访问多个不同完成者:只能向确实具备大Tag完成能力的对端发送大Tag请求。如果全部完成者都支持大Tag,软件配置会简单很多。

强烈建议所有Function尽量支持大Tag完成者能力。新设计完成者,就算本机不会发起大量并发NPR,内部也可以简单保存返回大Tag,硬件增量开销很小。

如果完成者本身需要同时处理大量并发NPR,就需要更多硬件资源;只有完成端硬件真正支持高并发,大Tag的性能收益才能完全发挥。

根复合体RC平台支持大Tag完成能力:强烈建议固件/系统软件,自动开启端点内部对应的大Tag请求使能位;主要面向访问主机内存的DMA读请求。

如何判断RCiEP(集成端点)对应的RC是否支持大Tag完成能力:普通端点查看根端口RP寄存器;RCiEP没有对应的RP端口,除非RC全局支持,否则不允许置位大Tag请求使能;软件不需要对RCiEP做单独查询。

非Flit模式交换机,即便不支持10bit Tag完成能力,依然可以正确转发携带10bit Tag的报文:10bit新增Tag位在TLP头部原本属于保留位。 但是如果交换机检测携带10bit Tag的报文出错,交换机代替完成者返回Completion报文时,返回Completion中的Tag会变成非法值。 所以:使用10bit Tag器件之间的交换机,强烈建议支持10bit Tag完成能力。速率16.0GT/s以上交换机强制必须支持10bit Tag完成能力

如果请求者一部分目标支持大Tag,一部分目标不支持,协议不规定请求者内部如何选择哪些请求分配大Tag、哪些分配小Tag,该策略属于实现自定义范畴。

实现注释:大Tag、小Tag并发混用

【IMPLEMENTATION NOTE: USING LARGER TAGS AND SMALLER TAGS CONCURRENTLY】

前文规则重申:请求者同时向两类完成者发请求(一部分支持大Tag、一部分只支持小Tag);如果有大Tag请求发给不支持大Tag的完成者,返回Completion,绝对不能让已经分配出去的大Tag编号,与还处于挂起状态小Tag发生编号别名冲突

10(768‑48=720)bit Tag硬件实现思路

请求者把原本8bit Tag空间划分两块区域:

  1. 区域A:仅用于小Tag(5bit /8bit)
  2. 区域B:仅用于10bit Tag的低8bit

代价:小Tag可用数量减少,10bit Tag总数量同步缩减。 举例:划分低4bit给小Tag。

  • 小Tag最多并发:$2^4 = 16$个。
  • 10bit Tag损失 $3*16=48$ 个Tag编号;原本10bit总共有768个可用,剩余 $768(768‑48=720)48=720$ 个并发。

通用公式:预留N个给小Tag,10bit Tag空间减少3*N;总并发 = 768\(768‑48=720\)2*N

同理14(768‑48=720)bit Tag也可以采用分区策略。 当系统需要同时混合支持14bit、10bit、8/5bit多种Tag位宽,分区思路依然成立,但是硬件复杂度会显著上升。


关键名词释义汇总

英文缩写中文释义
Requester ID请求者ID,16bit:Bus Number(8bit) + Device(5bit) + Function(3bit)
Tag标签,事务标记,用于配对Request(768‑48=720)Completion;位宽:5/8/10/14bit
TC Traffic Class流量类别,QoS服务等级,3bit
UIOUntrusted IO,非可信IO事务,部分事务ID需要纳入TC参与哈希/唯一性判定
Posted投递事务,不需要返回Completion报文(存储器写、消息)
Non(768‑48=720)Posted非投递事务,请求之后必须返回Completion报文(存储器读、配置读写、IO读写)
Flit Mode /FM包片模式 PCIe6新报文封装模式;Non(768‑48=720)Flit Mode/NFM传统TLP模式
Phantom Function幻影功能号,旧方案扩展并发请求,现在不推荐
Shadow Function影子功能号,扩展并发请求数量
Alias(Tag alias)Tag别名冲突:不同挂起事务复用完全一样Tag编号,引发Completion报文错匹配
Unexpected Completion意外完成报文:收到一个本地没有对应挂起请求的Completion报文,报错误日志
Completion Timeout完成超时:发出Non(768‑48=720)Posted请求,超过阈值没有收到Completion

2.2.6.3 事务描述符 — 属性字段

属性字段用于提供附加信息,用来修改事务的默认处理行为。这些修改会作用于系统内事务处理的不同方面,例如:

  • 排序规则
  • 硬件一致性管理(窥探snoop)

属性属于提示(hints):它允许对报文处理做优化,但不强制要求必须实现该优化。优化支持程度取决于PCIe外设与平台模块的目标应用场景。 在Flit模式下,属性字段在TLP头部内是连续比特位。 在非Flit模式下,属性第2比特有时标记为A2,该位与bit1、bit0在报文中不相邻(参见图2‑36、图2‑37)。


图2‑35 事务描述符的属性字段

(图:ID‑Based Ordering、Relaxed Ordering、No Snoop三个子位域)

2.2.6.4 宽松排序与基于ID排序属性

表2‑12定义了宽松排序(Relaxed Ordering)与基于ID排序(ID‑Based Ordering,IDO)属性字段取值。2.4节会详细讨论这些属性。注意:宽松排序、ID‑Based Ordering属性在报文中比特位置并不相邻(见图2‑5)。

表2‑12 排序属性

属性Bit[2]属性Bit[1]排序类型排序模型
00默认排序PCI强排序模型
01宽松排序PCI‑X宽松排序模型
10基于ID排序(IDO)基于请求者/完成者ID的独立排序
11宽松排序 + 基于ID排序宽松排序与IDO逻辑“或”生效

属性Bit[1]不适用于:配置请求、IO请求、作为消息信号中断的存储器请求、消息请求;除非规范明确允许,上述报文该位必须置0(Clear)。

属性Bit[2]:对配置请求、IO请求为保留位。 IDO不做保留,可用于全部存储器请求(包括MSI/MSI‑X)。除非明确禁止,IDO也可用于消息请求。 请求者只有在设备控制2寄存器中的IDO Request Enable位为1时,才允许置位IDO比特。

接收设备在判断TLP是否属于畸形报文(Malformed Packet)时,不能拿IDO比特的值作为判据

完成者(Completer)只有在设备控制2寄存器IDO Completion Enable置1时,才允许在完成报文里设置IDO位。 完成者没有强制要求必须把请求报文里的IDO值原样复制到对应完成报文。 如果完成者已开启IDO使能,建议对所有完成报文设置IDO,除非存在特殊理由不这么做(见附录E)。

支持根端口之间P2P报文转发的根复合体,不需要保证报文从入端口转发到出端口过程中保留IDO比特。

2.2.6.5 No Snoop(无窥探)属性

表2‑13定义了No Snoop属性字段取值。

注意:No Snoop属性不会改变事务的排序规则

表2‑13 缓存一致性管理属性

No Snoop属性比特缓存一致性管理类型一致性模型
0默认预期执行硬件强制缓存窥探一致性
1No Snoop(无窥探)不要求硬件执行缓存窥探一致性

该属性不适用于:配置请求、IO请求、作为消息信号中断的存储器请求、消息请求;除非规范明确允许,上述报文该位必须清零。

2.2.6.6 事务描述符 — 流量类别(Traffic Class)字段

流量类别(TC)是3比特位域,可以把事务划分为8种流量类别。

TC与PCIe虚通道(Virtual Channel,VC)机制配合,是实现差分流量服务的核心基础。 每一个PCIe TLP都携带TC作为不变标签,该标签在整个PCIe互联架构中端到端传递。报文经过每一条链路、每一个交换芯片时,都会依据TC标签决定报文调度服务。核心机制:根据TC标签把报文路由到对应的虚通道,2.5节详细描述VC机制。

表2‑14 TC字段编码定义

TC字段二进制值定义
000TC0:尽力而为服务(通用IO)
(默认TC,所有PCIe设备必须支持TC0
001 ~ 111TC1~TC7:差分服务类别
(可基于加权轮询WRR、优先级做流量区分)

由系统软件负责设置TC标签、完成TC‑VC映射,以此实现满足平台需求的差分服务。

流量类别概念仅作用于PCIe内部互联。如何将PCIe TC服务策略映射到非PCIe外部互联,不属于本规范定义范围。


关键歧义点注释(协议原文容易踩坑)

  1. Attributes是Hint提示,不是强制命令:外设可以忽略No Snoop / Relaxed Ordering / IDO,硬件不强制必须遵从。
  2. Non‑Flit模式坑点:属性比特不连续排布;Flit模式才把所有属性比特收拢成连续位域。
  3. IDO完成报文不强制拷贝请求IDO:很多验证容易犯的错误:断言Completion必须镜像Request的IDO位,协议明确不做强制。RC转发P2P还允许直接丢掉IDO。
  4. No‑Snoop只控制缓存窥探,不影响TLP排序:打开No Snoop不会改变报文ordering规则。
  5. TC0强制必选,TC1‑TC7设备可以不实现,靠系统软件TC‑VC映射做QoS。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值