面向 netlink 用户的通用网络统计¶
统计计数器分组到结构体中
结构体 |
TLV 类型 |
描述 |
---|---|---|
gnet_stats_basic |
TCA_STATS_BASIC |
基本统计信息 |
gnet_stats_rate_est |
TCA_STATS_RATE_EST |
速率估算器 |
gnet_stats_queue |
TCA_STATS_QUEUE |
队列统计信息 |
无 |
TCA_STATS_APP |
应用程序特定 |
收集:¶
声明您需要的统计信息结构体
struct mystruct {
struct gnet_stats_basic bstats;
struct gnet_stats_queue qstats;
...
};
仅在 dequeue() 方法中更新统计信息(在拥有 qdisc->running 时)
mystruct->tstats.packet++;
mystruct->qstats.backlog += skb->pkt_len;
导出到用户空间(Dump):¶
my_dumping_routine(struct sk_buff *skb, ...)
{
struct gnet_dump dump;
if (gnet_stats_start_copy(skb, TCA_STATS2, &mystruct->lock, &dump,
TCA_PAD) < 0)
goto rtattr_failure;
if (gnet_stats_copy_basic(&dump, &mystruct->bstats) < 0 ||
gnet_stats_copy_queue(&dump, &mystruct->qstats) < 0 ||
gnet_stats_copy_app(&dump, &xstats, sizeof(xstats)) < 0)
goto rtattr_failure;
if (gnet_stats_finish_copy(&dump) < 0)
goto rtattr_failure;
...
}
TCA_STATS/TCA_XSTATS 向后兼容性:¶
struct tc_stats 和 xstats 的先前用户可以通过调用兼容性包装器来保持向后兼容性,从而继续提供现有的 TLV 类型
my_dumping_routine(struct sk_buff *skb, ...)
{
if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
TCA_XSTATS, &mystruct->lock, &dump,
TCA_PAD) < 0)
goto rtattr_failure;
...
}
在 gnet_stats_copy_* 调用期间将填充 struct tc_stats 并附加到 skb。如果调用了 gnet_stats_copy_app,则提供 TCA_XSTATS。
锁定:¶
在写入之前获取锁,并在所有统计信息写入后释放锁。如果发生错误,始终会释放锁。您负责确保锁已初始化。
速率估算器:¶
准备一个估算器属性。 这很可能在用户空间中。此 TLV 的值应包含一个 tc_estimator 结构。像往常一样,这样的 TLV 需要 32 位对齐,因此长度需要适当设置等。估算器间隔和 ewma 日志需要转换为适当的值。建议使用 tc_estimator.c::tc_setup_estimator() 作为转换例程。它做了一些巧妙的事情。它需要以微秒为单位的时间间隔,以微秒为单位的时间常数和一个要填充的 struct tc_estimator。返回的 tc_estimator 可以传输到内核。在类型为 TCA_RATE 的 TLV 中将这样的结构传输到内核中的代码。
在内核中设置时
确保您首先设置了基本统计信息和速率统计信息。
确保您已初始化用于设置此类统计信息的统计信息锁。
现在初始化一个新的估算器
int ret = gen_new_estimator(my_basicstats,my_rate_est_stats, mystats_lock, attr_with_tcestimator_struct); if ret == 0 success else failed
从现在开始,每次您转储 my_rate_est_stats 时,它都会包含最新的信息。
完成后,调用 gen_kill_estimator(my_basicstats, my_rate_est_stats)。确保在进行此调用时 my_basicstats 和 my_rate_est_stats 仍然有效(即仍然存在)。