Skip to main content

FramePool

Struct FramePool 

Source
pub struct FramePool { /* private fields */ }
Expand description

Frame 池(极致优化版)

§核心设计

  • Free-List 栈式分配器:使用 Vec<u32> 作为 LIFO 栈,O(1) 分配/回收
  • 连续内存存储Vec<FrameInfo> 连续存储,缓存行友好
  • 单线程持有:无锁设计,每个 Worker 独占一个 FramePool
  • 预分配固定容量:初始化时一次性分配所有帧,运行期禁止扩容

§性能特征

  • 分配:O(1),仅一次 Vec push/pop
  • 回收:O(1),仅一次 Vec push
  • 守恒校验:O(n),但仅在调试/检查时调用
  • 热路径零堆分配、零锁、零系统调用

Implementations§

Source§

impl FramePool

Source

pub fn try_new( name: impl Into<String>, capacity: u32, frame_size: u32, ) -> Result<FramePool, CoreError>

创建新的 Frame 池(fail-closed 版本)

初始化时一次性分配所有数据结构,运行期禁止扩容。

§Arguments
  • name - 池名称
  • capacity - 总容量(帧数)
  • frame_size - 每个 Frame 的大小(字节)
§Returns
  • Ok(FramePool) - 新的 FramePool 实例
§Errors
  • frame_size == 0capacity == 0CoreError::InvalidConfig
  • capacity * frame_size 地址空间溢出 u64 → CoreError::ArithmeticOverflow
Source

pub fn new(name: impl Into<String>, capacity: u32, frame_size: u32) -> FramePool

创建新的 Frame 池(兼容版本,禁止 panic)

参数非法(frame_size == 0 / capacity == 0 / 地址空间溢出)时不 panic, 回退到最小合法配置(capacity=1, frame_size=1),回退前以 tracing::error! 记录完整原因(池名、参数与底层错误),避免静默降级难以排查。

推荐使用 FramePool::try_new:显式返回错误、可在调用方精确处置; 本构造函数仅为不便于传播错误的兼容调用方保留。

§Arguments
  • name - 池名称
  • capacity - 总容量(帧数)
  • frame_size - 每个 Frame 的大小(字节)
§Returns

新的 FramePool 实例

Source

pub fn name(&self) -> &str

获取池名称

Source

pub fn capacity(&self) -> u32

获取总容量

Source

pub fn frame_size(&self) -> u32

获取帧大小

Source

pub fn allocated_count(&self) -> u32

获取已分配数量

Source

pub fn free_count(&self) -> u32

获取空闲数量

Source

pub fn quarantined_count(&self) -> u32

获取隔离区数量

Source

pub fn allocate(&mut self, domain_id: u32) -> Result<FrameToken, CoreError>

分配一个 Frame(O(1),零锁零堆分配)

从 Free-List 栈顶弹出一个空闲帧,标记为已分配。

§Arguments
  • domain_id - 域ID
§Returns
  • Ok(FrameToken) - 成功分配的所有权令牌
  • Err(CoreError::QuotaExceeded) - 资源不足
Source

pub fn release(&mut self, token: FrameToken) -> Result<(), CoreError>

归还 Frame(O(1),零锁零堆分配)

验证令牌所有权后,将帧放回 Free-List 栈。

注意:即使验证失败(返回 Err),token 也会被消费(drop), 对应的帧将永久泄漏。如果需要在失败后保留令牌以便重试或另行处理, 请使用 FramePool::release_recoverable

§Arguments
  • token - 所有权令牌(被消费,即使在错误路径上也会被 drop)
§Returns
  • Ok(()) - 成功归还
  • Err(CoreError::OwnershipViolation) - 所有权违规(token 已被消费)
Source

pub fn release_recoverable( &mut self, token: FrameToken, ) -> Result<(), (FrameToken, CoreError)>

归还 Frame(可恢复版本,O(1))

release 语义一致,但在验证失败时将 token 随错误一起返回(Err((token, error))),调用方可据此重试或另行处理, 避免验证失败时帧被永久泄漏。

§Arguments
  • token - 所有权令牌(成功时被消费,失败时随错误返回)
§Returns
  • Ok(()) - 成功归还(token 被消费)
  • Err((FrameToken, CoreError)) - 验证失败,token 随错误返回供调用方处置
Source

pub fn quarantine( &mut self, token: FrameToken, reason: impl Into<String>, ) -> Result<(), CoreError>

将 Frame 移入隔离区

隔离区帧不会被自动回收,需要手动调用 recover_from_quarantine

§Arguments
  • token - 所有权令牌(被消费)
  • reason - 隔离原因
§Returns
  • Ok(()) - 成功隔离
Source

pub fn recover_from_quarantine( &mut self, frame_id: FrameId, ) -> Result<(), CoreError>

从隔离区回收 Frame

注意:本方法仅凭 frame_id 回收,验证代际(CORE-008)。 仅适用于调用方可确认帧未被回收重新分配的内部安全场景。 数据面路径(持有 frame_id + expected_generation)应使用 recover_from_quarantine_by_id, 以代际验证防止陈旧 FrameId 被复用。

§Arguments
  • frame_id - Frame ID
§Returns
  • Ok(()) - 成功回收
  • Err(CoreError::ResourceNotFound) - Frame 不在隔离区
Source

pub fn recover_from_quarantine_by_id( &mut self, frame_id: FrameId, expected_generation: u64, ) -> Result<(), CoreError>

从隔离区回收 Frame(代际验证版本,CORE-008)

recover_from_quarantine 语义一致, 额外校验期望代际号与当前帧代际一致,防止陈旧 FrameId 被恶意复用到 新帧上(防 ABA)。适用于 Worker 数据面等持有 frame_id + expected_generation 的调用路径。

§Arguments
  • frame_id - Frame ID
  • expected_generation - 期望的代际号(必须匹配当前帧的代际)
§Returns
  • Ok(()) - 成功回收
  • Err(CoreError::ResourceNotFound) - Frame 不在隔离区
  • Err(CoreError::OwnershipViolation) - 代际不匹配
Source

pub fn quarantine_by_id( &mut self, frame_id: FrameId, expected_generation: u64, reason: impl Into<String>, ) -> Result<(), CoreError>

通过 Frame ID 隔离帧(无 Token 场景)

当 FrameToken 已被消费(如通过 Ring 传递给内核)时, 只能通过 Frame ID 来隔离帧。此方法用于 Worker 数据面循环 中的解析错误和准入拒绝场景。

§安全保证

必须传入期望的代际号,用于验证帧未被回收重新分配。 这防止了陈旧 FrameID 被恶意复用到新帧上。

§状态转换

Allocated/Processing/InRxRing/InTxRing/InCompletionRing → Quarantine

§Arguments
  • frame_id - Frame ID
  • expected_generation - 期望的代际号(必须匹配当前帧的代际)
  • reason - 隔离原因
§Returns
  • Ok(()) - 成功隔离
  • Err(CoreError::OwnershipViolation) - 代际不匹配或状态非法
Source

pub fn advance_generation(&mut self) -> u64

推进代际号

代际号用于在热更新期间区分新旧资源,防止跨代际访问。

§溢出说明(CORE-009)

使用 saturating_add:代际为 u64,每次分配/释放/隔离/回收推进一次, 要在实际生命周期内达到 2^64 次推进不可达,故饱和语义不会隐藏真实溢出, 保持既有行为(不改变 -> u64 签名引入错误传播)。

§Returns

新的代际号

Source

pub fn current_generation(&self) -> u64

获取当前代际号

Source

pub fn advance_epoch(&mut self) -> u64

推进 Epoch

Epoch 用于标识配置快照的唯一版本,防止过期操作。

§溢出说明(CORE-009)

saturating_add:与代际同理,u64 在实际生命周期内不可达溢出。

§Returns

新的 Epoch 编号

Source

pub fn current_epoch(&self) -> u64

获取当前 Epoch 编号

Source

pub fn get_frame_info(&self, frame_id: FrameId) -> Option<FrameInfo>

获取 Frame 信息(返回克隆副本)

§Arguments
  • frame_id - Frame ID
§Returns
  • Some(FrameInfo) - Frame 信息副本
  • None - 未找到
Source

pub fn allocate_batch( &mut self, domain_id: u32, count: u32, ) -> Result<Vec<FrameToken>, CoreError>

批量分配 Frame

一次性分配多个 Frame,减少函数调用开销。 返回的令牌需要逐个归还。

§Arguments
  • domain_id - 域ID
  • count - 要分配的数量
§Returns
  • Ok(Vec<FrameToken>) - 成功分配的令牌列表
  • Err(CoreError::QuotaExceeded) - 资源不足(部分分配时已分配帧全部回滚)
Source

pub fn release_batch( &mut self, tokens: Vec<FrameToken>, ) -> Result<(), CoreError>

批量归还 Frame

§Arguments
  • tokens - 所有权令牌列表(全部被消费)
§Returns
  • Ok(()) - 成功归还
  • Err(CoreError) - 某帧归还失败(剩余帧仍尽力归还,返回首个错误)
Source

pub fn verify_conservation(&self) -> Result<(), CoreError>

验证所有权守恒

恒等式:空闲 + 已分配 + 隔离 = 总容量

§Returns
  • Ok(()) - 守恒
  • Err(CoreError::Internal) - 不守恒
Source

pub fn release_by_id( &mut self, frame_id: FrameId, expected_generation: u64, ) -> Result<(), CoreError>

通过 Frame ID 归还 Frame(O(1),用于环形队列回收路径)

此方法用于 AF_XDP 环形队列完成回收路径, 通过帧索引直接归还帧,无需 FrameToken。

§安全保证

必须传入期望的代际号,用于验证帧未被回收重新分配。 同时验证帧必须处于 Allocated 状态。

§安全约束
  • 帧必须处于 Allocated 状态
  • 代际号必须匹配当前帧的代际
  • 调用者必须确保没有其他持有者在使用该帧
§Arguments
  • frame_id - Frame ID
  • expected_generation - 期望的代际号(必须匹配当前帧的代际)
§Returns
  • Ok(()) - 成功归还
  • Err(CoreError::OwnershipViolation) - 帧不在 Allocated 状态或代际不匹配
Source

pub fn frames(&self) -> &[FrameInfo]

获取底层帧信息切片(用于批量操作)

§Returns

帧信息的切片引用

Source

pub fn remaining_free(&self) -> u32

获取 Free-List 栈的剩余容量

§Returns

栈中剩余的空闲帧数

Trait Implementations§

Source§

impl Debug for FramePool

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more