DPDK的meter库(单速率三色算法)

DPDK提供了丰富的基础库,其中就有利用令牌桶来实现meter功能,可以参考例子中的qos_meter。这篇博客主要就是解读这个例子。令牌桶算法分为单速率三色算法和双速率单色算法,单速率只有一个速率桶C桶以及一个EBS。关注点在于报文的突发尺寸,双速率有两个速率桶C和P,更关注突发的报文速率。

首先来看单速率三色,令牌产生的速率是cir,C桶容量为cbs,当C桶满时,再去添加E桶,E桶也满时,令牌丢弃。

在取令牌时,先取C桶,C桶满足,不管E桶,E桶保持不变,C桶减少相应数量令牌返回绿色。

C桶不满,取E桶令牌,E桶满足,E桶减少相应数量令牌返回黄色。E桶也不够,两个桶的令牌数保持不变。返回红色。

main函数:一大堆初始化,主要看app_configure_flow_table这个函数。

static int
app_configure_flow_table(void)
{
    uint32_t i, j;
    int ret;

    for (i = 0, j = 0; i < APP_FLOWS_MAX;
            i ++, j = (j + 1) % RTE_DIM(PARAMS)) {
        ret = FUNC_CONFIG(&app_flows[i], &PARAMS[j]);
        if (ret)
            return ret;
    }       

    return 0;
}
FUNC_CONFIG对应的函数为
int
rte_meter_srtcm_config(struct rte_meter_srtcm *m, struct rte_meter_srtcm_params *params)
{
	uint64_t hz;

	/* Check input parameters */
	if ((m == NULL) || (params == NULL)) {
		return -1;
	}

	if ((params->cir == 0) || ((params->cbs == 0) && (params->ebs == 0))) {
		return -2;
	}

	/* Initialize srTCM run-time structure */
	hz = rte_get_tsc_hz();
	m->time = rte_get_tsc_cycles();
	m->tc = m->cbs = params->cbs;
	m->te = m->ebs = params->ebs;
	rte_meter_get_tb_params(hz, params->cir, &m->cir_period, &m->cir_bytes_per_period);

	RTE_LOG(INFO, METER, "Low level srTCM config: \n"
		"\tCIR period = %" PRIu64 ", CIR bytes per period = %" PRIu64 "\n",
		m->cir_period, m->cir_bytes_per_period);

	return 0;
}

static void
rte_meter_get_tb_params(uint64_t hz, uint64_t rate, uint64_t *tb_period, uint64_t *tb_bytes_per_period)
{
/*先计算添加一个字节所需的cpu周期数
 *如果计算出的结果值太小,说明添加一个字节所需的cpu周期很短。
 *如果直接用计算结果,会导致精度不准,所以将更新表的周期数设置为RTE_METER_TB_PERIOD_MIN,每次    
 *添加的字节数大于1*/
	double period = ((double) hz) / ((double) rate);  

	if (period >= RTE_METER_TB_PERIOD_MIN) {
		*tb_bytes_per_period = 1;
		*tb_period = (uint64_t) period;
	} else {
		*tb_bytes_per_period = (uint64_t) ceil(RTE_METER_TB_PERIOD_MIN / period);
		*tb_period = (hz * (*tb_bytes_per_period)) / rate;
	}
}

app_flows[]的数据类型是struct rte_meter_srtcm
struct rte_meter_srtcm {
	uint64_t time; /* 最后一次更新C和E桶的时间*/
	uint64_t tc;   /* C桶当前可用令牌数*/
	uint64_t te;   /* E桶当前可用令牌数*/
	uint64_t cbs;  /* cbs数值,C桶的总容量*/
	uint64_t ebs;  /* ebs数值,E桶的总容量*/
	uint64_t cir_period; /* 每隔cir_period*cpu周期,更新C桶*/
	uint64_t cir_bytes_per_period; /*每次更新C桶所需添加的令牌数*/
};

PARAMS:
struct rte_meter_srtcm_params app_srtcm_params[] = {
	{.cir = 1000000 * 46,  .cbs = 2048, .ebs = 2048},
};

#define FUNC_CONFIG   rte_meter_srtcm_config
rte_meter_srtcm_config(struct rte_meter_srtcm *m, struct rte_meter_srtcm_params *params)
这个函数就是对app_flow[]进行赋值

 

关于cir,cbs,ebs,pbs,pir:

CIR(Committed Information Rate,承诺信息速率):每秒可通过的速率,计量单位为Kbps  (以bit 位为单位)。

CBS(Committed Burst Size):承诺突发尺寸突发尺寸,令牌桶的容量,即每次突发所允许的最大的流量尺寸。设置的突发尺寸必须大于最大报文长度。计量单位为byte(字节)。

EBS(Excess Burst Size,超出突发尺寸):即瞬间能够通过的超出突发流量。计量单位为byte(字节)。

初始化完成之后,针对每个包,都会进行颜色判断,色盲模式的判断比较简单,对应的函数如下:

static inline enum rte_meter_color
rte_meter_srtcm_color_blind_check(struct rte_meter_srtcm *m,
	uint64_t time,
	uint32_t pkt_len)
{
	uint64_t time_diff, n_periods, tc, te;

	/* Bucket update */
	time_diff = time - m->time;
	n_periods = time_diff / m->cir_period;
	m->time += n_periods * m->cir_period;//m->time = time。。强行增加阅读难度,更新m->time

	/* 先往C桶添加令牌,C桶添加满之后再往E桶添加令牌 */
	tc = m->tc + n_periods * m->cir_bytes_per_period; //更新当前C桶可用令牌数
	te = m->te;
	if (tc > m->cbs) {
		te += (tc - m->cbs);
		if (te > m->ebs)
			te = m->ebs;
		tc = m->cbs;
	}

	/* Color logic */
//C桶可用令牌足够,返回绿色。
	if (tc >= pkt_len) {
		m->tc = tc - pkt_len;
		m->te = te;
		return e_RTE_METER_GREEN;
	}
//C桶不够,用E桶判断。
	if (te >= pkt_len) {
		m->tc = tc;
		m->te = te - pkt_len;
		return e_RTE_METER_YELLOW;
	}

	m->tc = tc;
	m->te = te;
	return e_RTE_METER_RED;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值