NVIDIA DPDK Documentation MLNX_DPDK_22.11_2310.5.1 LTS

Updating Flow Rule

The new rte_flow_update() API allows users to update the action list in the already existing rule. Flow rules can be updated now without the need to destroy the rule first and create a new one instead.

Note

The update of the rule can have a different actions list.​

Copy
Copied!
            

# Create a template table with two templates. flow pattern_template 0 create pattern_template_id 1 ingress template eth / end flow actions_template 0 create actions_template_id 1 template queue / end mask queue / end flow actions_template 0 create actions_template_id 2 template count / queue / end mask count / queue / end flow template_table 0 create table_id 1 group 1 priority 0 ingress rules_number 64 pattern_template 1 actions_template 1 actions_template 2 # Create a flow with the counter to test the path. flow queue 0 create 0 template_table 1 pattern_template 0 actions_template 1 postpone no pattern eth / end actions count / queue index 1 / end # Remove counter by updating the rule once the path is tested. flow queue 0 update 0 rule 1 actions_template 0 postpone no pattern end actions queue index 3 / end

Copy
Copied!
            

struct rte_flow_pattern_template * create_pattern_template(uint16_t port_id, struct rte_flow_error *error) { struct rte_flow_item pattern[] = { { .type = RTE_FLOW_ITEM_TYPE_ETH, }, { .type = RTE_FLOW_ITEM_TYPE_END, }, }; const struct rte_flow_pattern_template_attr pt_attr = { .relaxed_matching = 0, .ingress = 1, };   return rte_flow_pattern_template_create(port_id, &pt_attr, pattern, &error); }   struct rte_flow_actions_template * create_actions_templates(uint16_t port_id, bool counter, struct rte_flow_error *error) { struct rte_flow_action_count count; struct rte_flow_action_queue queue_v = { .index = 0, }; struct rte_flow_action_queue queue_m = { .index = UINT16_MAX, }; struct rte_flow_action actions[] = { [0] = { /* queue action. */ .type = RTE_FLOW_ACTION_TYPE_QUEUE, .conf = &queue_v, }, [1] = { /* end action mast be the last action. */ .type = RTE_FLOW_ACTION_TYPE_END, }, }; struct rte_flow_action masks[] = { [0] = { /* queue action. */ .type = RTE_FLOW_ACTION_TYPE_QUEUE, .conf = &queue_m, }, [1] = { /* end action mast be the last action. */ .type = RTE_FLOW_ACTION_TYPE_END, }, }; struct rte_flow_action cnt_actions[] = { [0] = { /* counter action. */ .type = RTE_FLOW_ACTION_TYPE_COUNTER, .conf = &count }, [1] = { /* queue action. */ .type = RTE_FLOW_ACTION_TYPE_QUEUE, .conf = &queue_v, }, [2] = { /* end action mast be the last action. */ .type = RTE_FLOW_ACTION_TYPE_END, }, }; struct rte_flow_action cnt_masks[] = { [0] = { /* counter action. */ .type = RTE_FLOW_ACTION_TYPE_COUNTER, .conf = &count }, [1] = { /* queue action. */ .type = RTE_FLOW_ACTION_TYPE_QUEUE, .conf = &queue_m, }, [2] = { /* end action mast be the last action. */ .type = RTE_FLOW_ACTION_TYPE_END, }, }; const struct rte_flow_actions_template_attr at_attr = { .ingress = 1, };   return rte_flow_actions_template_create(port_id, &at_attr, counter ? cnt_action : action, counter ? cnt_masks : masks, error); }   struct rte_flow_template_table * create_table(uint16_t port_id, struct rte_flow_error *error) { struct rte_flow_pattern_template *pt; struct rte_flow_actions_template *at[2]; const struct rte_flow_template_table_attr tbl_attr = { .flow_attr = { .group = 1, .priority = 0, .ingress = 1, }, .nb_flows = 1000, }; ...   pt = create_pattern_template(port_id, error); if (pt == NULL) { printf("Failed to create pattern template: %s (%d) \n", error.message, rte_errno); return NULL; } at[0] = create_actions_template(port_id, false, error); if (at[0] == NULL) { printf("Failed to create actions template: %s (%d)\n", error.message, rte_errno); return NULL; } at[1] = create_actions_template(port_id, true, error); if (at[1] == NULL) { printf("Failed to create actions template: %s (%d)\n", error.message, rte_errno); return NULL; } return rte_flow_template_table_create(port_id, &tbl_attr, &pt, 1, at, 2, error); }   void update_counter_rule(void) { uint32_t idx; uint16_t port_id = PORT_ID; uint32_t queue_id = QUEUE_ID; struct rte_flow_error error = { 0 }; struct rte_flow_op_attr attr = { .postpone = 0 }; struct rte_flow_item pattern[] = { { .type = RTE_FLOW_ITEM_TYPE_ETH, }, { .type = RTE_FLOW_ITEM_TYPE_END, }, }; struct rte_flow_action_count count; struct rte_flow_action_queue queue = { .index = 0 }; struct rte_flow_action cnt_actions[] = { [0] = { /* counter action. */ .type = RTE_FLOW_ACTION_TYPE_COUNTER, .conf = &count, }, [1] = { /* queue action. */ .type = RTE_FLOW_ACTION_TYPE_QUEUE, .conf = &queue, }, [2] = { /* end action mast be the last action. */ .type = RTE_FLOW_ACTION_TYPE_END, }, }; struct rte_flow_action actions[] = { [0] = { /* queue 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_template_table * table; struct rte_flow *flow;   table = create_table(port_id, &error); if (table == NULL) { printf("Failed to create template table: %s (%d)\n", error.message, rte_errno); rte_exit(EXIT_FAILURE, "Exiting"); }   flow = rte_flow_async_create(port_id, queue_id, &attr, table, pattern, 0, cnt_actions, 1, NULL, &error); if (flow == NULL) { printf("Failed to enqueue flow create operation: %s (%d) \n", error.message, rte_errno); rte_exit(EXIT_FAILURE, "Exiting"); }; ... rte_flow_async_update(port_id, queue_id, &attr, flow, actions, 0, NULL, &error); }

© Copyright 2024, NVIDIA. Last updated on Jan 9, 2025.