Skip to main content

zenith_linux/
descriptor.rs

1//! AF_XDP 描述符模块
2//!
3//! 实现与内核 AF_XDP ABI 兼容的描述符体系:
4//! - XdpDesc: 内核 xdp_desc 结构的 Rust 表示(addr/len/options 三字段)
5//! - Descriptor: 带所有权元数据的高层描述符(在 XdpDesc 基础上扩展 owner/generation)
6//! - DescriptorEngine: 描述符分配/释放/守恒校验引擎
7//!
8//! # 内核 ABI 对齐
9//!
10//! Linux 内核 `xdp_desc` 结构(include/uapi/linux/bpf.h):
11//! ```c
12//! struct xdp_desc {
13//!     __u64 addr;      // UMEM 中的偏移地址
14//!     __u32 len;      // 数据长度(字节)
15//!     __u32 options;  // 选项标志(如 XDP_TX_META_DATA)
16//! };
17//! ```
18//!
19//! # 高层扩展
20//!
21//! Zenith 在 `XdpDesc` 基础上扩展了所有权元数据:
22//! - owner: 描述符所有者(队列/Worker ID)
23//! - generation: 代际号(防止 ABA 问题)
24
25use crate::error::{DescriptorError, Result};
26use std::sync::atomic::{AtomicU64, Ordering};
27
28/// 描述符类型(高层语义)
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum DescriptorType {
31    /// 数据帧描述符
32    DataFrame,
33    /// 控制消息描述符
34    ControlMessage,
35    /// 保留描述符
36    Reserved,
37}
38
39/// AF_XDP 内核 xdp_desc 结构的 Rust 表示
40///
41/// 严格对应内核 ABI,size = 16 bytes。
42#[repr(C, align(8))]
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub struct XdpDesc {
45    /// UMEM 中的偏移地址(帧起始地址 = umem_base + addr)
46    pub addr: u64,
47    /// 数据长度(字节)
48    pub len: u32,
49    /// 选项标志(XDP_TX_META_DATA 等)
50    pub options: u32,
51}
52
53// 编译期布局断言:XdpDesc 必须与内核 xdp_desc(include/uapi/linux/bpf.h)
54// 同为 16 字节,否则与内核 ring 共享内存的描述符读写整体错位。
55const _: () = assert!(
56    core::mem::size_of::<XdpDesc>() == 16,
57    "XdpDesc 必须与内核 xdp_desc 同为 16 字节"
58);
59
60impl XdpDesc {
61    /// 创建零值描述符
62    #[inline]
63    pub const fn zero() -> Self {
64        Self {
65            addr: 0,
66            len: 0,
67            options: 0,
68        }
69    }
70
71    /// 是否为零描述符(所有字段均为零值,内核 ring 中的空槽标记)
72    ///
73    /// 注意:addr=0 是合法的 UMEM 偏移(帧索引 0),
74    /// 只有 addr、len、options 全为零时才表示无效描述符。
75    #[inline]
76    pub fn is_zero(&self) -> bool {
77        self.addr == 0 && self.len == 0 && self.options == 0
78    }
79
80    /// 转换为 u64 数组(用于内核 ring 操作)
81    #[inline]
82    pub fn as_u64_slice(&self) -> [u64; 2] {
83        // xdp_desc 为 16 字节:addr (u64) + len (u32) + options (u32)
84        // 在 ring 中实际存储为 u64[2] 数组
85        [self.addr, (self.len as u64) | ((self.options as u64) << 32)]
86    }
87
88    /// 从 u64 数组创建
89    #[inline]
90    pub fn from_u64_slice(raw: [u64; 2]) -> Self {
91        Self {
92            addr: raw[0],
93            len: (raw[1] as u32),
94            options: (raw[1] >> 32) as u32,
95        }
96    }
97}
98
99impl Default for XdpDesc {
100    fn default() -> Self {
101        Self::zero()
102    }
103}
104
105/// 高层描述符
106///
107/// 封装 XdpDesc 并添加所有权元数据。
108/// - index: 帧索引(通过 addr 计算)
109/// - generation: 代际号(ABA 防护)
110/// - owner: 所有者 ID(队列/Worker)
111/// - desc_type: 语义类型
112#[derive(Debug, Clone, Copy, PartialEq, Eq)]
113pub struct Descriptor {
114    /// 内核描述符(addr/len/options)
115    xdp: XdpDesc,
116    /// 帧索引(从 addr 派生)
117    index: u32,
118    /// 代际号
119    generation: u16,
120    /// 所有者 ID
121    owner: u16,
122    /// 语义类型
123    desc_type: DescriptorType,
124}
125
126/// 最大合法 frame index(20-bit 帧索引域上界 2^20 - 1,AGENT.md §5.1)
127///
128/// 描述符范围检查必须在 frame index 域进行,禁止用 raw 64-bit addr 值;
129/// 超出该域的 `addr >> frame_shift` 说明 raw addr 非法(高位信息会在
130/// `as u32` 截断中静默丢失并指向错误帧),必须 fail-closed。
131pub const MAX_FRAME_INDEX: u64 = (1 << 20) - 1;
132
133impl Descriptor {
134    /// 创建新的描述符
135    #[inline]
136    pub fn new(
137        xdp: XdpDesc,
138        index: u32,
139        owner: u16,
140        generation: u16,
141        desc_type: DescriptorType,
142    ) -> Self {
143        Self {
144            xdp,
145            index,
146            owner,
147            generation,
148            desc_type,
149        }
150    }
151
152    /// 从内核描述符创建(自动派生 index,fail-closed)
153    ///
154    /// `xdp.addr >> frame_shift` 必须落入 20-bit frame index 域(≤ [`MAX_FRAME_INDEX`])。
155    /// `frame_shift` 由调用方从 [`DescriptorEngine::frame_shift`] 获取,
156    /// 保证与引擎实际帧移位一致,杜绝硬编码 `>> 12` 在非 4096 帧大小下的索引坍塌。
157    ///
158    /// # 返回
159    /// * `Ok(Self)` - 帧索引合法的描述符
160    /// * `Err(DescriptorError::OutOfRange)` - `addr >> frame_shift` 超出 20-bit 帧索引域;
161    ///   静默 `as u32` 截断会丢弃高 32 位并指向错误帧(甚至回绕到帧 0),
162    ///   故构造期拒绝(fail-closed,参照 [`DescriptorEngine::allocate`] 的对称语义)
163    #[inline]
164    pub fn from_xdp(xdp: XdpDesc, owner: u16, generation: u16, frame_shift: u32) -> Result<Self> {
165        let raw_index = xdp.addr >> frame_shift;
166        if raw_index > MAX_FRAME_INDEX {
167            return Err(DescriptorError::OutOfRange {
168                descriptor: xdp.addr,
169                max_valid: MAX_FRAME_INDEX,
170            }
171            .into());
172        }
173        // 上界校验后该转换必不丢失信息;仍以 try_from 形式化杜绝 `as u32` 截断语义
174        let index = u32::try_from(raw_index).map_err(|_| DescriptorError::OutOfRange {
175            descriptor: xdp.addr,
176            max_valid: MAX_FRAME_INDEX,
177        })?;
178        Ok(Self {
179            xdp,
180            index,
181            owner,
182            generation,
183            desc_type: DescriptorType::DataFrame,
184        })
185    }
186
187    /// 获取内核描述符
188    #[inline]
189    pub fn xdp_desc(&self) -> &XdpDesc {
190        &self.xdp
191    }
192
193    /// 获取 addr
194    #[inline]
195    pub fn addr(&self) -> u64 {
196        self.xdp.addr
197    }
198
199    /// 获取 len
200    #[inline]
201    pub fn len(&self) -> u32 {
202        self.xdp.len
203    }
204
205    /// 判断描述符的 len 是否为 0
206    #[inline]
207    pub fn is_empty(&self) -> bool {
208        self.xdp.len == 0
209    }
210
211    /// 获取 options
212    #[inline]
213    pub fn options(&self) -> u32 {
214        self.xdp.options
215    }
216
217    /// 获取帧索引
218    #[inline]
219    pub fn index(&self) -> u32 {
220        self.index
221    }
222
223    /// 获取所有者 ID
224    #[inline]
225    pub fn owner(&self) -> u16 {
226        self.owner
227    }
228
229    /// 获取代际号
230    #[inline]
231    pub fn generation(&self) -> u16 {
232        self.generation
233    }
234
235    /// 获取描述符类型
236    #[inline]
237    pub fn descriptor_type(&self) -> DescriptorType {
238        self.desc_type
239    }
240
241    /// 设置所有者
242    #[inline]
243    pub fn set_owner(&mut self, new_owner: u16) {
244        self.owner = new_owner;
245    }
246
247    /// 设置代际号
248    #[inline]
249    pub fn set_generation(&mut self, new_generation: u16) {
250        self.generation = new_generation;
251    }
252
253    /// 是否为零描述符
254    #[inline]
255    pub fn is_zero(&self) -> bool {
256        self.xdp.is_zero()
257    }
258
259    /// 转换为原始 ring 数据(两个 u64)
260    #[inline]
261    pub fn to_raw(&self) -> [u64; 2] {
262        self.xdp.as_u64_slice()
263    }
264}
265
266impl Default for Descriptor {
267    fn default() -> Self {
268        Self {
269            xdp: XdpDesc::zero(),
270            index: 0,
271            generation: 0,
272            owner: 0,
273            desc_type: DescriptorType::Reserved,
274        }
275    }
276}
277
278/// 描述符校验引擎
279///
280/// 提供完整的描述符校验、所有权管理和守恒等式校验。
281/// 单线程无锁设计:内部状态通过原子类型以 `&self` 变更
282/// (单 Owner 持有 `XskSocket`,生命周期内不跨线程共享)。
283///
284/// # Ordering 论证
285/// 本引擎由单个 `XskSocket` 独占持有,生命周期内不跨线程共享(单 Owner
286/// 顺序访问,无并发发布场景)。原子类型仅用于以 `&self` 变更内部状态,
287/// 因此全部使用 `Ordering::Relaxed`:不存在跨线程 happens-before 需求。
288/// 若未来引入跨线程共享(如 `Arc<DescriptorEngine>`),必须重审本论证。
289pub struct DescriptorEngine {
290    /// 最大有效帧索引
291    max_frame_index: u64,
292    /// 帧地址移位(log2(frame_size),默认 12 = 4096 字节帧)
293    frame_shift: u32,
294    /// 当前代际号
295    current_generation: AtomicU64,
296    /// 已分配描述符计数
297    allocated_count: AtomicU64,
298    /// 已释放描述符计数
299    freed_count: AtomicU64,
300    /// 活跃描述符位图(每个 bit 表示一个描述符是否活跃)
301    active_bitmap: Vec<AtomicU64>,
302}
303
304impl std::fmt::Debug for DescriptorEngine {
305    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
306        f.debug_struct("DescriptorEngine")
307            .field("max_frame_index", &self.max_frame_index)
308            .field("current_generation", &self.current_generation)
309            .field("allocated_count", &self.allocated_count)
310            .field("freed_count", &self.freed_count)
311            .finish()
312    }
313}
314
315impl DescriptorEngine {
316    /// 创建描述符校验引擎(默认 4096 字节帧,shift = 12,fail-closed)
317    ///
318    /// # 参数
319    /// * `max_frames` - 最大帧数量(必须 ≤ 2^20,即 20-bit 帧索引域)
320    ///
321    /// # 返回
322    /// * `Ok(Self)` - 引擎实例
323    /// * `Err(DescriptorError::InvalidCapacity)` - `max_frames > 2^20`,
324    ///   拒绝构造:超域帧索引与 [`MAX_FRAME_INDEX`] 契约冲突
325    pub fn new(max_frames: u64) -> Result<Self> {
326        // shift = 12 静态合法(位于 11..=15 区间)
327        Self::with_frame_shift(max_frames, 12)
328    }
329
330    /// 创建描述符校验引擎(显式帧移位,fail-closed)
331    ///
332    /// # 参数
333    /// * `max_frames` - 最大帧数量(必须 ≤ 2^20,即 20-bit 帧索引域)
334    /// * `frame_shift` - log2(frame_size),合法区间 11..=15
335    ///   (帧大小 2048..=32768 字节)
336    ///
337    /// # 返回
338    /// * `Ok(Self)` - 引擎实例
339    /// * `Err(DescriptorError::InvalidFrameShift)` - `frame_shift` 非法,
340    ///   拒绝构造:防止 `frame_index << frame_shift` 在 debug shift-overflow
341    ///   panic / release 移位掩码静默错误地址
342    /// * `Err(DescriptorError::InvalidCapacity)` - `max_frames > 2^20`,
343    ///   拒绝构造:20-bit frame index 域容量上限为 2^20([`MAX_FRAME_INDEX`] + 1),
344    ///   超域帧索引会与 `Descriptor::from_xdp` 的越界拒绝语义冲突
345    pub fn with_frame_shift(max_frames: u64, frame_shift: u32) -> Result<Self> {
346        if !(11..=15).contains(&frame_shift) {
347            return Err(DescriptorError::InvalidFrameShift(frame_shift).into());
348        }
349        if max_frames > MAX_FRAME_INDEX + 1 {
350            return Err(DescriptorError::InvalidCapacity(max_frames).into());
351        }
352        Ok(Self::new_unchecked(max_frames, frame_shift))
353    }
354
355    /// 内部免检构造:仅由 `new`(shift=12 静态合法)与
356    /// `with_frame_shift`(已通过 11..=15 校验)调用
357    fn new_unchecked(max_frames: u64, frame_shift: u32) -> Self {
358        let bitmap_words = max_frames.div_ceil(64);
359        let active_bitmap = (0..bitmap_words)
360            .map(|_| AtomicU64::new(0))
361            .collect();
362
363        Self {
364            max_frame_index: max_frames.saturating_sub(1),
365            frame_shift,
366            current_generation: AtomicU64::new(1),
367            allocated_count: AtomicU64::new(0),
368            freed_count: AtomicU64::new(0),
369            active_bitmap,
370        }
371    }
372
373    /// 获取帧移位(log2(frame_size))
374    #[inline]
375    pub fn frame_shift(&self) -> u32 {
376        self.frame_shift
377    }
378
379    /// 分配描述符(从帧索引创建)
380    ///
381    /// # 参数
382    /// * `frame_index` - 帧索引
383    /// * `owner` - 所有者 ID
384    ///
385    /// # 返回
386    /// * `Result<Descriptor>` - 新描述符
387    pub fn allocate(&self, frame_index: u32, owner: u16) -> Result<Descriptor> {
388        // 范围检查与 verify 对称:越界帧索引 fail-closed(此前仅 verify 检查,
389        // allocate 静默接受并在 set_bitmap 中丢弃越界位,语义不对称)
390        if u64::from(frame_index) > self.max_frame_index {
391            return Err(DescriptorError::OutOfRange {
392                descriptor: u64::from(frame_index) << self.frame_shift,
393                max_valid: self.max_frame_index,
394            }
395            .into());
396        }
397
398        // 位图已置位 = 帧已分配:fail-closed 拒绝重复分配(此前静默放行,
399        // 位图重幂等置位 + allocated_count 递增 → 双计数破坏守恒等式)
400        if self.get_bitmap(frame_index) {
401            return Err(DescriptorError::AlreadyAllocated(u64::from(frame_index)).into());
402        }
403
404        let generation = self.current_generation.load(Ordering::Relaxed) as u16;
405
406        // 设置位图位
407        self.set_bitmap(frame_index, true);
408
409        self.allocated_count.fetch_add(1, Ordering::Relaxed);
410
411        // 构建 XdpDesc:addr = frame_index << frame_shift(按配置帧大小)
412        let xdp = XdpDesc {
413            addr: u64::from(frame_index) << self.frame_shift,
414            len: 0,
415            options: 0,
416        };
417
418        Ok(Descriptor::new(
419            xdp,
420            frame_index,
421            owner,
422            generation,
423            DescriptorType::DataFrame,
424        ))
425    }
426
427    /// 释放描述符
428    ///
429    /// # 参数
430    /// * `desc` - 要释放的描述符
431    ///
432    /// # 返回
433    /// * `Result<()>` - 成功或错误
434    pub fn release(&self, desc: &Descriptor) -> Result<()> {
435        let index = desc.index();
436        if !self.get_bitmap(index) {
437            return Err(DescriptorError::AlreadyFreed(desc.addr()).into());
438        }
439
440        self.set_bitmap(index, false);
441        self.freed_count.fetch_add(1, Ordering::Relaxed);
442
443        Ok(())
444    }
445
446    /// 回滚 allocate(清除位图 + 递减计数,不生成描述符)
447    ///
448    /// 用于 `fill_descriptors` 等"先批量 allocate 再 enqueue"场景:
449    /// enqueue 失败时帧已位图置位但未入环,形成孤立帧;
450    /// 通过位图为权威回滚,恢复 allocated == freed + active 守恒等式。
451    ///
452    /// # 参数
453    /// * `frame_index` - 要回滚的帧索引
454    ///
455    /// # 返回
456    /// * `true` - 位图存在且已清除;`false` - 帧索引越界或位图未置位(fail-closed 不 panic)
457    pub fn rollback_allocate(&self, frame_index: u32) -> bool {
458        if u64::from(frame_index) > self.max_frame_index {
459            return false;
460        }
461        if !self.get_bitmap(frame_index) {
462            return false;
463        }
464        self.set_bitmap(frame_index, false);
465        // sub 饱和兜底:若 INVARIANT 破坏(allocated_count == 0),不 panic
466        let _ = self.allocated_count.fetch_sub(1, Ordering::Relaxed);
467        true
468    }
469
470    /// 校验描述符有效性
471    ///
472    /// 基于位图的权威校验:检查帧索引范围、活跃状态和所有权。
473    /// 位图是描述符有效性的唯一权威来源,不依赖描述符字段值。
474    ///
475    /// # 参数
476    /// * `desc` - 要校验的描述符
477    /// * `expected_owner` - 期望的所有者
478    ///
479    /// # 返回
480    /// * `Result<()>` - 成功或错误
481    pub fn verify(&self, desc: &Descriptor, expected_owner: u16) -> Result<()> {
482        let index = desc.index();
483        if (index as u64) > self.max_frame_index {
484            return Err(DescriptorError::OutOfRange {
485                descriptor: desc.addr(),
486                max_valid: self.max_frame_index,
487            }
488            .into());
489        }
490
491        // 位图是有效性的权威来源
492        if !self.get_bitmap(index) {
493            return Err(DescriptorError::AlreadyFreed(desc.addr()).into());
494        }
495
496        if desc.owner() != expected_owner {
497            return Err(DescriptorError::OwnershipMismatch {
498                expected: expected_owner as u32,
499                actual: desc.owner() as u32,
500            }
501            .into());
502        }
503
504        Ok(())
505    }
506
507    /// 事务化所有权迁移
508    ///
509    /// 原子性地将描述符的所有者从 old_owner 迁移到 new_owner。
510    ///
511    /// # 参数
512    /// * `desc` - 描述符引用
513    /// * `old_owner` - 旧所有者
514    /// * `new_owner` - 新所有者
515    ///
516    /// # 返回
517    /// * `Result<Descriptor>` - 新的描述符(已迁移所有者)
518    pub fn transfer_ownership(
519        &self,
520        desc: &Descriptor,
521        old_owner: u16,
522        new_owner: u16,
523    ) -> Result<Descriptor> {
524        self.verify(desc, old_owner)?;
525
526        // 代际号计算:先在 u64 域完成 fetch_add + 1(杜绝 `as u16 + 1` 的
527        // 截断后溢出 panic),再校验范围落入 u16;超出范围 Fail-Closed 返回错误。
528        let next = self.current_generation.fetch_add(1, Ordering::Relaxed).wrapping_add(1);
529        let new_generation = u16::try_from(next).map_err(|_| {
530            DescriptorError::TransactionFailed(format!("代际号 {next} 超出 u16 范围"))
531        })?;
532        let mut new_desc = *desc;
533        new_desc.set_owner(new_owner);
534        new_desc.set_generation(new_generation);
535
536        Ok(new_desc)
537    }
538
539    /// 查询帧是否已被引擎分配(位图是否置位)
540    ///
541    /// 供 Fill Ring 预填/补填路径判定「帧是否已登记」:与 `allocate` 的
542    /// `AlreadyAllocated` fail-closed 配套,避免从 0 重复登记已分配帧。
543    #[inline]
544    pub fn is_allocated(&self, index: u32) -> bool {
545        self.get_bitmap(index)
546    }
547
548    /// 增加全局代际号(fail-closed:与 `transfer_ownership` 同域约束)
549    ///
550    /// 代际域为 u16(`Descriptor.generation: u16`);原实现可无限增长,
551    /// 与 `transfer_ownership`「超 u16::MAX 拒绝」语义不一致——调用方若把
552    /// 返回值截断成 u16 会静默回绕。超域时返回错误而非截断。
553    ///
554    /// # 返回
555    /// * `Ok(u64)` - 递增后的新代际号(≤ u16::MAX)
556    /// * `Err(DescriptorError::TransactionFailed)` - 代际号超出 u16 范围
557    #[inline]
558    pub fn bump_generation(&self) -> Result<u64> {
559        let next = self
560            .current_generation
561            .fetch_add(1, Ordering::Relaxed)
562            .wrapping_add(1);
563        if next > u64::from(u16::MAX) {
564            return Err(DescriptorError::TransactionFailed(format!(
565                "代际号 {next} 超出 u16 范围"
566            ))
567            .into());
568        }
569        Ok(next)
570    }
571
572    /// 获取守恒统计
573    #[inline]
574    pub fn conservation_stats(&self) -> (u64, u64) {
575        (
576            self.allocated_count.load(Ordering::Relaxed),
577            self.freed_count.load(Ordering::Relaxed),
578        )
579    }
580
581    /// 检查守恒等式:allocated == freed + active
582    pub fn verify_conservation(&self) -> bool {
583        let (allocated, freed) = self.conservation_stats();
584        let active = self.count_active();
585        allocated == freed + active
586    }
587
588    /// 统计活跃描述符数量
589    fn count_active(&self) -> u64 {
590        let mut count = 0u64;
591        for word in &self.active_bitmap {
592            count += word.load(Ordering::Relaxed).count_ones() as u64;
593        }
594        count
595    }
596
597    /// 设置位图位
598    fn set_bitmap(&self, index: u32, value: bool) {
599        let word_idx = (index / 64) as usize;
600        let bit_idx = index % 64;
601        if word_idx < self.active_bitmap.len() {
602            if value {
603                self.active_bitmap[word_idx].fetch_or(1u64 << bit_idx, Ordering::Relaxed);
604            } else {
605                self.active_bitmap[word_idx].fetch_and(!(1u64 << bit_idx), Ordering::Relaxed);
606            }
607        }
608    }
609
610    /// 获取位图位
611    fn get_bitmap(&self, index: u32) -> bool {
612        let word_idx = (index / 64) as usize;
613        let bit_idx = index % 64;
614        if word_idx < self.active_bitmap.len() {
615            (self.active_bitmap[word_idx].load(Ordering::Relaxed) >> bit_idx) & 1 == 1
616        } else {
617            false
618        }
619    }
620}
621
622#[cfg(test)]
623mod tests {
624    use super::*;
625    use crate::error::LinuxError;
626
627    #[test]
628    fn test_xdp_desc_zero() {
629        let desc = XdpDesc::zero();
630        assert!(desc.is_zero());
631        assert_eq!(desc.addr, 0);
632        assert_eq!(desc.len, 0);
633        assert_eq!(desc.options, 0);
634    }
635
636    #[test]
637    fn test_xdp_desc_roundtrip() {
638        let desc = XdpDesc {
639            addr: 0x1000,
640            len: 1500,
641            options: 0x42,
642        };
643        let raw = desc.as_u64_slice();
644        let recovered = XdpDesc::from_u64_slice(raw);
645        assert_eq!(recovered, desc);
646    }
647
648    #[test]
649    fn test_descriptor_creation() {
650        let xdp = XdpDesc {
651            addr: 4096,
652            len: 1500,
653            options: 0,
654        };
655        let desc = Descriptor::new(xdp, 1, 1, 1, DescriptorType::DataFrame);
656        assert_eq!(desc.index(), 1);
657        assert_eq!(desc.addr(), 4096);
658        assert_eq!(desc.len(), 1500);
659        assert_eq!(desc.owner(), 1);
660        assert_eq!(desc.generation(), 1);
661        assert_eq!(desc.descriptor_type(), DescriptorType::DataFrame);
662    }
663
664    #[test]
665    fn test_descriptor_modify() {
666        let xdp = XdpDesc::zero();
667        let mut desc = Descriptor::new(xdp, 0, 1, 1, DescriptorType::DataFrame);
668        desc.set_owner(2);
669        assert_eq!(desc.owner(), 2);
670        desc.set_generation(5);
671        assert_eq!(desc.generation(), 5);
672    }
673
674    #[test]
675    fn test_descriptor_from_xdp() {
676        let xdp = XdpDesc {
677            addr: 8192, // frame index = 8192 >> 12 = 2
678            len: 64,
679            options: 0,
680        };
681        let desc = Descriptor::from_xdp(xdp, 3, 42, 12).unwrap();
682        assert_eq!(desc.index(), 2);
683        assert_eq!(desc.addr(), 8192);
684        assert_eq!(desc.owner(), 3);
685        assert_eq!(desc.generation(), 42);
686    }
687
688    #[test]
689    fn test_descriptor_from_xdp_out_of_range_rejected() {
690        // addr >> 12 = 2^20,恰好越出 20-bit frame index 域 → fail-closed(AGENT.md §5.1)
691        let xdp = XdpDesc {
692            addr: (1u64 << 20) << 12,
693            len: 64,
694            options: 0,
695        };
696        let result = Descriptor::from_xdp(xdp, 1, 1, 12);
697        assert!(matches!(
698            result,
699            Err(LinuxError::Descriptor(DescriptorError::OutOfRange { .. }))
700        ));
701    }
702
703    #[test]
704    fn test_descriptor_from_xdp_high_bits_truncation_rejected() {
705        // addr >> 12 = 2^32:`as u32` 会静默截断为 0 并指向帧 0 → 必须构造期拒绝
706        let xdp = XdpDesc {
707            addr: (1u64 << 32) << 12,
708            len: 0,
709            options: 0,
710        };
711        assert!(Descriptor::from_xdp(xdp, 1, 1, 12).is_err());
712    }
713
714    #[test]
715    fn test_descriptor_from_xdp_max_valid_index() {
716        // addr >> 12 = 2^20 - 1(20-bit 域最大合法值)→ 接受
717        let xdp = XdpDesc {
718            addr: MAX_FRAME_INDEX << 12,
719            len: 0,
720            options: 0,
721        };
722        let desc = Descriptor::from_xdp(xdp, 1, 1, 12).unwrap();
723        assert_eq!(desc.index() as u64, MAX_FRAME_INDEX);
724    }
725
726    #[test]
727    fn test_descriptor_from_xdp_non_default_frame_shift() {
728        // frame_shift=11(帧大小 2048):addr=4096 >> 11 = 2,与 shift=12 的 addr=8192 >> 12 = 2 等价
729        let xdp = XdpDesc {
730            addr: 4096, // 4096 >> 11 = 2
731            len: 64,
732            options: 0,
733        };
734        let desc = Descriptor::from_xdp(xdp, 1, 1, 11).unwrap();
735        assert_eq!(desc.index(), 2);
736
737        // shift=15(帧大小 32768):addr=65536 >> 15 = 2
738        let xdp2 = XdpDesc {
739            addr: 65536,
740            len: 64,
741            options: 0,
742        };
743        let desc2 = Descriptor::from_xdp(xdp2, 1, 1, 15).unwrap();
744        assert_eq!(desc2.index(), 2);
745    }
746
747    #[test]
748    fn test_descriptor_engine_allocate_release() {
749        let engine = DescriptorEngine::new(1024).unwrap();
750
751        let desc = engine.allocate(0, 1).unwrap();
752        assert_eq!(desc.index(), 0);
753        assert_eq!(desc.owner(), 1);
754        assert_eq!(desc.addr(), 0);
755
756        engine.verify(&desc, 1).unwrap();
757        engine.release(&desc).unwrap();
758
759        let result = engine.verify(&desc, 1);
760        assert!(result.is_err());
761    }
762
763    #[test]
764    fn test_descriptor_engine_zero_rejected() {
765        let engine = DescriptorEngine::new(1024).unwrap();
766        let zero = Descriptor::default();
767        let result = engine.verify(&zero, 1);
768        assert!(result.is_err());
769    }
770
771    #[test]
772    fn test_descriptor_ownership_transfer() {
773        let engine = DescriptorEngine::new(1024).unwrap();
774        let desc = engine.allocate(0, 1).unwrap();
775        let new_desc = engine.transfer_ownership(&desc, 1, 2).unwrap();
776        assert_eq!(new_desc.owner(), 2);
777        assert_eq!(new_desc.index(), 0);
778    }
779
780    #[test]
781    fn test_descriptor_conservation() {
782        let engine = DescriptorEngine::new(1024).unwrap();
783        let desc1 = engine.allocate(0, 1).unwrap();
784        let _desc2 = engine.allocate(1, 1).unwrap();
785        engine.release(&desc1).unwrap();
786        assert!(engine.verify_conservation());
787        let (allocated, freed) = engine.conservation_stats();
788        assert_eq!(allocated, 2);
789        assert_eq!(freed, 1);
790    }
791
792    #[test]
793    fn test_descriptor_out_of_range() {
794        let engine = DescriptorEngine::new(100).unwrap();
795        let xdp = XdpDesc {
796            addr: (2000u64) << 12,
797            len: 0,
798            options: 0,
799        };
800        let desc = Descriptor::new(xdp, 2000, 1, 1, DescriptorType::DataFrame);
801        let result = engine.verify(&desc, 1);
802        assert!(result.is_err());
803    }
804
805    #[test]
806    fn test_already_freed_rejected() {
807        let engine = DescriptorEngine::new(1024).unwrap();
808        let desc = engine.allocate(5, 1).unwrap();
809        engine.release(&desc).unwrap();
810        let result = engine.release(&desc);
811        assert!(result.is_err());
812    }
813
814    #[test]
815    fn test_ownership_mismatch() {
816        let engine = DescriptorEngine::new(1024).unwrap();
817        let desc = engine.allocate(10, 2).unwrap();
818        let result = engine.verify(&desc, 1);
819        assert!(result.is_err());
820    }
821
822    #[test]
823    fn test_frame_index_boundary_zero() {
824        let engine = DescriptorEngine::new(1024).unwrap();
825        let desc = engine.allocate(0, 1).unwrap();
826        assert_eq!(desc.index(), 0);
827        assert_eq!(desc.addr(), 0);
828        engine.verify(&desc, 1).unwrap();
829    }
830
831    #[test]
832    fn test_frame_index_boundary_one() {
833        let engine = DescriptorEngine::new(1024).unwrap();
834        let desc = engine.allocate(1, 1).unwrap();
835        assert_eq!(desc.index(), 1);
836        assert_eq!(desc.addr(), 4096);
837        engine.verify(&desc, 1).unwrap();
838    }
839
840    #[test]
841    fn test_frame_index_20bit_max() {
842        let max_frames = 0x100000u64; // 2^20 = 1,048,576
843        let engine = DescriptorEngine::new(max_frames).unwrap();
844
845        let max_index = (max_frames - 1) as u32;
846        let desc = engine.allocate(max_index, 1).unwrap();
847        assert_eq!(desc.index(), max_index);
848        assert_eq!(desc.addr(), (max_index as u64) << 12);
849        engine.verify(&desc, 1).unwrap();
850    }
851
852    #[test]
853    fn test_frame_index_out_of_range() {
854        let engine = DescriptorEngine::new(100).unwrap();
855        let xdp = XdpDesc {
856            addr: (200u64) << 12,
857            len: 0,
858            options: 0,
859        };
860        let desc = Descriptor::new(xdp, 200, 1, 1, DescriptorType::DataFrame);
861        let result = engine.verify(&desc, 1);
862        assert!(result.is_err());
863    }
864
865    #[test]
866    fn test_descriptor_default_is_zero() {
867        let desc = Descriptor::default();
868        assert!(desc.is_zero());
869        assert_eq!(desc.index(), 0);
870        assert_eq!(desc.owner(), 0);
871        assert_eq!(desc.generation(), 0);
872        assert_eq!(desc.descriptor_type(), DescriptorType::Reserved);
873    }
874
875    #[test]
876    fn test_xdp_desc_default_is_zero() {
877        let desc = XdpDesc::default();
878        assert!(desc.is_zero());
879        assert_eq!(desc.addr, 0);
880        assert_eq!(desc.len, 0);
881        assert_eq!(desc.options, 0);
882    }
883
884    #[test]
885    fn test_xdp_desc_not_zero_with_addr_only() {
886        let desc = XdpDesc {
887            addr: 4096,
888            len: 0,
889            options: 0,
890        };
891        assert!(!desc.is_zero());
892    }
893
894    #[test]
895    fn test_xdp_desc_not_zero_with_len_only() {
896        let desc = XdpDesc {
897            addr: 0,
898            len: 100,
899            options: 0,
900        };
901        assert!(!desc.is_zero());
902    }
903
904    #[test]
905    fn test_xdp_desc_not_zero_with_options_only() {
906        let desc = XdpDesc {
907            addr: 0,
908            len: 0,
909            options: 1,
910        };
911        assert!(!desc.is_zero());
912    }
913
914    #[test]
915    fn test_descriptor_to_raw_roundtrip() {
916        let xdp = XdpDesc {
917            addr: 0x12345678,
918            len: 1500,
919            options: 0xDEAD,
920        };
921        let desc = Descriptor::new(xdp, 0, 1, 2, DescriptorType::DataFrame);
922        let raw = desc.to_raw();
923        let recovered = XdpDesc::from_u64_slice(raw);
924        assert_eq!(recovered, xdp);
925    }
926
927    #[test]
928    fn test_generation_bump() {
929        let engine = DescriptorEngine::new(1024).unwrap();
930        let initial = engine.bump_generation().unwrap();
931        assert!(initial > 1);
932
933        let next = engine.bump_generation().unwrap();
934        assert_eq!(next, initial + 1);
935    }
936
937    #[test]
938    fn test_generation_bump_overflow_fail_closed() {
939        // Fail-Closed:bump_generation 与 transfer_ownership 同域约束,
940        // 代际号超出 u16::MAX 必须返回错误而非静默超域/截断回绕
941        let engine = DescriptorEngine::new(1024).unwrap();
942        engine
943            .current_generation
944            .store(u64::from(u16::MAX), Ordering::Relaxed);
945        let result = engine.bump_generation();
946        assert!(result.is_err(), "代际号越界必须 Fail-Closed");
947    }
948
949    #[test]
950    fn test_transfer_ownership_increments_generation() {
951        let engine = DescriptorEngine::new(1024).unwrap();
952        let desc = engine.allocate(0, 1).unwrap();
953        let original_gen = desc.generation();
954
955        let new_desc = engine.transfer_ownership(&desc, 1, 2).unwrap();
956        assert_eq!(new_desc.owner(), 2);
957        assert_eq!(new_desc.index(), 0);
958        assert!(new_desc.generation() > original_gen);
959    }
960
961    #[test]
962    fn test_transfer_ownership_wrong_old_owner_fails() {
963        let engine = DescriptorEngine::new(1024).unwrap();
964        let desc = engine.allocate(0, 1).unwrap();
965        let result = engine.transfer_ownership(&desc, 99, 2);
966        assert!(result.is_err());
967    }
968
969    #[test]
970    fn test_transfer_ownership_generation_overflow_fails() {
971        // Fail-Closed:代际号超出 u16 范围时返回错误,而非截断/溢出 panic
972        let engine = DescriptorEngine::new(1024).unwrap();
973        let desc = engine.allocate(0, 1).unwrap();
974        // 将全局代际计数器推到 u16 上限(下一次 +1 即越界)
975        engine.current_generation.store(u64::from(u16::MAX), Ordering::Relaxed);
976        let result = engine.transfer_ownership(&desc, 1, 2);
977        assert!(result.is_err(), "代际号越界必须 Fail-Closed");
978    }
979
980    #[test]
981    fn test_multiple_allocations_and_releases() {
982        let engine = DescriptorEngine::new(1024).unwrap();
983        let mut descs = Vec::new();
984
985        for i in 0..100 {
986            let desc = engine.allocate(i, (i % 10) as u16).unwrap();
987            descs.push(desc);
988        }
989
990        assert!(engine.verify_conservation());
991        let (allocated, freed) = engine.conservation_stats();
992        assert_eq!(allocated, 100);
993        assert_eq!(freed, 0);
994
995        for desc in &descs[..50] {
996            engine.release(desc).unwrap();
997        }
998
999        assert!(engine.verify_conservation());
1000        let (allocated, freed) = engine.conservation_stats();
1001        assert_eq!(allocated, 100);
1002        assert_eq!(freed, 50);
1003
1004        for desc in &descs[50..] {
1005            engine.release(desc).unwrap();
1006        }
1007
1008        assert!(engine.verify_conservation());
1009        let (allocated, freed) = engine.conservation_stats();
1010        assert_eq!(allocated, 100);
1011        assert_eq!(freed, 100);
1012    }
1013
1014    #[test]
1015    fn test_already_in_use_check() {
1016        // Fail-Closed:重复分配位图已置位的帧必须返回 AlreadyAllocated,
1017        // 而非幂等置位 + allocated_count 递增的双计数(破坏守恒等式)
1018        let engine = DescriptorEngine::new(1024).unwrap();
1019        let desc = engine.allocate(42, 1).unwrap();
1020        engine.verify(&desc, 1).unwrap();
1021        assert!(engine.is_allocated(42));
1022
1023        let result = engine.allocate(42, 2);
1024        assert!(
1025            matches!(
1026                result,
1027                Err(LinuxError::Descriptor(DescriptorError::AlreadyAllocated(42)))
1028            ),
1029            "已分配帧重复分配必须返回 AlreadyAllocated,实际 {result:?}"
1030        );
1031        // 失败分配不得改变守恒统计(allocated == freed + active 仍恒等)
1032        let (allocated, freed) = engine.conservation_stats();
1033        assert_eq!(allocated, 1);
1034        assert_eq!(freed, 0);
1035        assert!(engine.verify_conservation());
1036    }
1037
1038    #[test]
1039    fn test_engine_capacity_fail_closed_over_20bit() {
1040        // Fail-Closed:20-bit 帧索引域容量上限为 2^20,超域拒绝构造
1041        assert!(DescriptorEngine::new((1u64 << 20) + 1).is_err());
1042        assert!(DescriptorEngine::new(u64::MAX).is_err());
1043        assert!(DescriptorEngine::with_frame_shift((1u64 << 20) + 1, 12).is_err());
1044        // 边界:恰好 2^20 合法;越界帧移位仍按原语义拒绝
1045        assert!(DescriptorEngine::new(1u64 << 20).is_ok());
1046        assert!(DescriptorEngine::with_frame_shift(1024, 16).is_err());
1047    }
1048
1049    #[test]
1050    fn test_descriptor_engine_debug_format() {
1051        let engine = DescriptorEngine::new(256).unwrap();
1052        let debug = format!("{:?}", engine);
1053        assert!(debug.contains("DescriptorEngine"));
1054        assert!(debug.contains("max_frame_index"));
1055        assert!(debug.contains("current_generation"));
1056    }
1057
1058    #[test]
1059    fn test_descriptor_type_variants() {
1060        let types = vec![
1061            DescriptorType::DataFrame,
1062            DescriptorType::ControlMessage,
1063            DescriptorType::Reserved,
1064        ];
1065        for desc_type in types {
1066            let xdp = XdpDesc::zero();
1067            let desc = Descriptor::new(xdp, 0, 0, 0, desc_type);
1068            assert_eq!(desc.descriptor_type(), desc_type);
1069        }
1070    }
1071
1072    #[test]
1073    fn test_large_descriptor_engine() {
1074        let engine = DescriptorEngine::new(65536).unwrap();
1075        let desc = engine.allocate(65535, 1).unwrap();
1076        assert_eq!(desc.index(), 65535);
1077        engine.verify(&desc, 1).unwrap();
1078        engine.release(&desc).unwrap();
1079        assert!(engine.verify_conservation());
1080    }
1081}