Meter Hierarchy
testpmd>add port meter profile srtcm_rfc2697 0
25
1000
1024
0
1
testpmd>add port meter profile srtcm_rfc2697 0
24
65536
1024
0
0
testpmd>add port meter policy 0
1
g_actions queue index 1
end / end y_actions end r_actions drop / end
testpmd>create port meter 0
1
25
1
yes 0xffff
1
0
testpmd>add port meter policy 0
2
g_actions meter mtr_id 1
/ end y_actions end r_actions drop / end
testpmd>create port meter 0
2
24
2
yes 0xffff
1
0
testpmd>flow create 0
priority 3
group 1
ingress pattern eth / end actions meter mtr_id 2
/ end
int
add_port_meter_profile_srtcm(uint16_t port_id, uint32_t profile_id,
uint64_t cir, uint64_t cbs,
uint64_t ebs, int
packet_mode,
struct rte_mtr_error *error)
{
struct rte_mtr_meter_profile mp;
/* Private shaper profile params */
memset(&mp, 0
, sizeof(struct rte_mtr_meter_profile));
mp.alg = RTE_MTR_SRTCM_RFC2697;
mp.srtcm_rfc2697.cir = cir;
mp.srtcm_rfc2697.cbs = cbs;
mp.srtcm_rfc2697.ebs = ebs;
mp.packet_mode = packet_mode;
return
rte_mtr_meter_profile_add(port_id, profile_id, &mp, error);
}
int
port_meter_policy_add(portid_t port_id, uint32_t policy_id,
const
struct rte_flow_action *actions,
struct rte_mtr_error *error)
{
struct rte_mtr_error error;
const
struct rte_flow_action *act = actions;
const
struct rte_flow_action *start;
struct rte_mtr_meter_policy_params policy;
uint32_t i = 0
, act_n;
int
ret;
for
(i = 0
; i < RTE_COLORS; i++) {
for
(act_n = 0
, start = act; act->type != RTE_FLOW_ACTION_TYPE_END; act++)
act_n++;
if
(act_n && act->type == RTE_FLOW_ACTION_TYPE_END)
policy.actions[i] = start;
else
policy.actions[i] = NULL;
act++;
}
return
rte_mtr_meter_policy_add(port_id, policy_id, &policy, error);
}
static
void
create_port_meter(uint16_t port_id, uint32_t mtr_id, uint32_t shared,
uint32_t profile_id, int
use_prev_mtr_color,
int
meter_enable, uint64_t stats_mask,
uint32_t policy_id, struct rte_mtr_error *error)
{
struct rte_mtr_params params;
int
ret;
/* Meter params */
memset(params, 0
, sizeof(struct rte_mtr_params));
params.meter_profile_id = profile_id;
params.use_prev_mtr_color = use_prev_mtr_color;
params.meter_enable = meter_enable;
params.stats_mask = stats_mask;
params.meter_policy_id = policy_id;
return
rte_mtr_create(port_id, mtr_id, params, shared, error);
}
int
create_flow_with_meter_hierarchy(uint16_t port_id)
{
int
ret;
struct rte_mtr_error mtr_error;
uint32_t pps_profile_id = 1
;
uint32_t pps_policy_id = 1
;
uint32_t pps_mtr_id = 1
;
uint32_t bps_profile_id = 2
;
uint32_t bps_policy_id = 2
;
uint32_t bps_mtr_id = 2
;
int
shared = 1
; /* mtr is shared. */
struct rte_flow_action_queue queue = { .index = 1
};
struct rte_flow_action pps_actions[] = {
[0
] = { /* meter action. */
.type = RTE_FLOW_ACTION_TYPE_QUEUE,
.conf = &queue},
[1
] = { /* end action mast be the last action. */
.type = RTE_FLOW_ACTION_TYPE_END,},
};
struct rte_flow_action_meter pps_meter = {.mtr_id = pps_mtr_id};
struct rte_flow_action bps_actions[] = {
[0
] = { /* meter action. */
.type = RTE_FLOW_ACTION_TYPE_METER,
.conf = &pps_meter},
[1
] = { /* end action mast be the last action. */
.type = RTE_FLOW_ACTION_TYPE_END,},
};
/* Create pps meter. */
ret = add_port_meter_profile_srtcm(port_id, pps_profile_id,
1000
, 300
, 0
, 1
, &mtr_error);
if
(ret) {
printf("cannot add meter pps profile, error: %s\n"
,
mtr_error.message);
return
ret;
}
ret = port_meter_policy_add(port_id, pps_policy_id, pps_actions, &mtr_error);
if
(ret) {
printf("cannot add meter pps policy, error: %s\n"
,
mtr_error.message);
return
ret;
}
ret = create_port_meter(port_id, pps_mtr_id, shared, pps_profile_id, 0
, 1
,
0xffff
, pps_policy_id, &mtr_error);
if
(ret) {
printf("cannot create pps meter: %u with profile: %u, error: %s\n"
,
mtr_id, pps_profile_id, mtr_error.message);
return
ret;
}
/* Create bps meter. */
ret = add_port_meter_profile_srtcm(port_id, bps_profile_id,
1
*1024
*1024
, 64
*1024
, 0
, 0
, &mtr_error);
if
(ret) {
printf("cannot add meter bps profile, error: %s\n"
,
mtr_error.message);
return
ret;
}
ret = port_meter_policy_add(port_id, bps_policy_id, bps_actions, &mtr_error);
if
(ret) {
printf("cannot add meter bps policy, error: %s\n"
,
mtr_error.message);
return
ret;
}
ret = create_port_meter(port_id, bps_mtr_id, shared, bps_profile_id, 0
, 1
,
0xffff
, bps_policy_id, &mtr_error);
if
(ret) {
printf("cannot create bps meter: %u with profile: %u, error: %s\n"
,
mtr_id, bps_profile_id, mtr_error.message);
return
ret;
}
struct rte_flow *flow;
struct rte_flow_error error;
struct rte_flow_attr attr = { /* holds the flow attributes. */
.group = 1
, /* set the rule on the main group. */
.ingress = 1
,/* rx flow. */
.transfer = 0
,
.priority = 1
, }; /* add priority to rule
to give the decap rule higher priority since
it is more specific */
struct rte_flow_item_ipv4 ipv4_outer = {
.hdr = {
.src_addr = rte_cpu_to_be_32(0x0D0A0A0A
),
/* match on 13.10.10.10 src address */
}};
struct rte_flow_item_ipv4 ipv4_mask = {
.hdr = {
.src_addr = RTE_BE32(0xffffffff
)}};
pattern[L2].type = RTE_FLOW_ITEM_TYPE_ETH;
pattern[L3].type = RTE_FLOW_ITEM_TYPE_IPV4;
pattern[L3].spec = &ipv4_outer;
pattern[L3].mask = &ipv4_mask;
pattern[TUNNEL].type = RTE_FLOW_ITEM_TYPE_END;
struct rte_flow_action_meter bps_meter = {.mtr_id = bps_mtr_id};
struct rte_flow_action actions[] = {
[0
] = { /* meter action. */
.type = RTE_FLOW_ACTION_TYPE_METER,
.conf = &bps_meter},
[1
] = { /* end action mast be the last action. */
.type = RTE_FLOW_ACTION_TYPE_END,},
};
flow = rte_flow_create(port_id, &attr, pattern, actions, &error);
if
(!flow) {
printf("can't create flow with with mtr id: %u, on port: %u, error: %s\n"
,
bps_mtr_id, port_id, error.message);
return
-1
;
}
return
0
;
}