This DPDK API examples illustrates how to set up a meter to perform traffic policing and how to apply the meter in a flow rule as well as how to read the statistics.
Setting up a meter object
struct rte_flow_action action[] = { [0] = { .type = RTE_FLOW_ACTION_TYPE_END }}; struct rte_flow_action drop_action[] = { [0] = { .type = RTE_FLOW_ACTION_TYPE_DROP }, [1] = { .type = RTE_FLOW_ACTION_TYPE_END }}; struct rte_mtr_meter_profile profile = { .alg = RTE_MTR_TRTCM_RFC2698, .trtcm_rfc2698 = { .cir = MAX_RATE, .cbs = BUCKET_SIZE, .pir = MAX_RATE, .pbs = BUCKET_SIZE }, .packet_mode = 1 }; struct rte_mtr_meter_policy_params policy = { .actions = { [RTE_COLOR_GREEN] = action, [RTE_COLOR_YELLOW] = drop_action, [RTE_COLOR_RED] = drop_action }}; struct rte_mtr_params params = { .meter_profile_id = PROFILE_ID, .meter_enable = 1, .stats_mask = RTE_MTR_STATS_N_PKTS_GREEN | RTE_MTR_STATS_N_BYTES_GREEN, .meter_policy_id = POLICY_ID }; struct rte_mtr_error error; if (rte_mtr_meter_profile_add(PORT_ID, PROFILE_ID, &profile, &error)) { /* Error handling */ } if (rte_mtr_meter_policy_add(PORT_ID, POLICY_ID, &policy, &error)) { /* Error handling */ } if (rte_mtr_create(PORT_ID, METER_ID, ¶ms, 1, &error)) { /* Error handling */ }
Two actions are defined: one contains only an end action, indicating no action should be taken, and another that drops the frame. These actions are used in the meter policy definition.
The metering profile specifies how to meter the traffic. It uses two-rate three-color marker algorithm (as defined in RFC 2698) with specified committed information rate (CIR) / peak information rate (PIR) and committed burst size (CBS) / peak burst size (PBS) values.
The meter policy specifies how to handle the traffic based on its metering results. In this example, the policy maps the three possible colors (green, yellow and red) to different actions. Green traffic is mapped to the action array, which indicates that no action should be applied. Yellow and red traffic is mapped to the drop_action array, which indicates that the frame should be dropped.
The meter object combines the meter profile and policy to perform traffic policing on the specified port. The meter_enable flag enables the metering functionality on the port, and the stats_mask parameter specifies which statistics to collect.
Applying a meter in a flow rule
/* Create group 1 exact match 5-tuple to retransmit offloaded IPv4 UDP packets. */ struct rte_flow_attr attr = { .group = 1, .ingress = 1 }; struct rte_flow_item_ipv4 ipv4 = { .hdr = { .src_addr = RTE_BE32(RTE_IPV4(20, 10, 10, 2)), .dst_addr = RTE_BE32(RTE_IPV4(20, 10, 11, 23)) }}; struct rte_flow_item_udp udp = { .hdr = { .src_port = RTE_BE16(0x1000), .dst_port = RTE_BE16(0x1001) }}; struct rte_flow_item pattern[] = { [0] = { .type = RTE_FLOW_ITEM_TYPE_IPV4, .spec = &ipv4, .mask = &rte_flow_item_ipv4_mask }, [1] = { .type = RTE_FLOW_ITEM_TYPE_UDP, .spec = &udp, .mask = &rte_flow_item_udp_mask }}; struct rte_flow_action_meter meter = { .mtr_id = METER_ID }; struct rte_flow_action_port_id port_id = { .id = 1 }; struct rte_flow_action action[] = { [0] = { .type = RTE_FLOW_ACTION_TYPE_METER, .conf = &meter }, [1] = { .type = RTE_FLOW_ACTION_TYPE_PORT_ID, .conf = &port_id }, [2] = { .type = RTE_FLOW_ACTION_TYPE_END }}; struct rte_flow_error error; struct rte_flow *flow = rte_flow_create(PORT_ID, &attr, pattern, action, &error); if (!flow) { /* Error handling */ }The flow rule is defined with a group ID of 1. It matches IPv4 frames with specific source and destination IP addresses, as well as with specific source and destination UDP port numbers. The flow rule applies a meter with the specified meter ID and forwards matching traffic to a specific port.
Reading usage counters
uint64_t stats_mask = 0; struct rte_mtr_stats stats = {}; struct rte_mtr_error error; if (rte_mtr_stats_read(PORT_ID, METER_ID, &stats, &stats_mask, 0, &error)) { /* ERROR */ } /* Result in stats.n_pkts[RTE_COLOR_GREEN] */ /* Result in stats.n_bytes[RTE_COLOR_GREEN] */
The rte_mtr_stats_read function is called with the specified port ID and meter object ID, as well as a pointer to a rte_mtr_stats structure and a mask indicating which statistics should be read.
If the statistics are successfully read, the resulting values of the n_pkts and n_bytes fields of the rte_mtr_stats structure for the RTE_COLOR_GREEN packet color are retrieved. These fields contain the number of packets and bytes that have been processed by the meter and classified as green.
It is also possible to read metering statistics in a callback function. See API: Reading Metering Statistics.
Running a user application with the DPDK virtio PMD
NTCONNECT: ERR: Error: Meter ID 655999 out of range. Max value is 559240.This error message occurs because the meter object ID has exceeded the limit. This issue can be resolved by compiling the application with the -Dmax_ethports option.
max_id = flow_mtr_meter_policy_n_max() / (RTE_MAX_ETHPORTS - 2); id = ((vport - 4) * max_id) + id;To increase the maximum meter object ID, the simplest approach is to reduce RTE_MAX_ETHPORTS, which represents the maximum number of physical ports that DPDK can support on a system. By default, RTE_MAX_ETHPORTS is set to 32. RTE_MAX_ETHPORTS can be modified using the -Dmax_ethports parameter during compilation.