What can I help you with?
NVIDIA DPDK Documentation MLNX_DPDK_22.11_2310.5.1 LTS

Meter Sharing Between Ports Inside a Single switchdev

Copy
Copied!
            

testpmd> add port meter profile srtcm_rfc2697 0 21 155189248 19398656 0 0 testpmd> add port meter policy 0 37 g_actions jump group 2 / end y_actions end r_actions drop / end testpmd> create port meter 0 102 21 37 yes 0xffff 1 0 testpmd> flow create 0 ingress transfer group 1 pattern eth / end actions meter mtr_id 102 / end testpmd> flow create 0 ingress transfer group 1 pattern eth / port_id id is 1 / end actions meter mtr_id 102 / end

Meter is created on PF Rep (port 0) which is used to match the traffic on VF Rep1 (port 1) and redirect the matching items to VF Rep2 (port 2).

Copy
Copied!
            

static struct rte_flow_item pattern[] = {   [L2] = { /* ETH type is set since we always start from ETH. */ .type = RTE_FLOW_ITEM_TYPE_ETH, .spec = NULL, .mask = NULL, .last = NULL },   [L3] = { .type = RTE_FLOW_ITEM_TYPE_VOID, .spec = NULL, .mask = NULL, .last = NULL },   [L4] = { .type = RTE_FLOW_ITEM_TYPE_VOID, .spec = NULL, .mask = NULL, .last = NULL },   [TUNNEL] = { .type = RTE_FLOW_ITEM_TYPE_VOID, .spec = NULL, .mask = NULL, .last = NULL },   [L2_INNER] = { .type = RTE_FLOW_ITEM_TYPE_VOID, .spec = NULL, .mask = NULL, .last = NULL },   [L3_INNER] = { .type = RTE_FLOW_ITEM_TYPE_VOID, .spec = NULL, .mask = NULL, .last = NULL },   [L4_INNER] = { .type = RTE_FLOW_ITEM_TYPE_VOID, .spec = NULL, .mask = NULL, .last = NULL },   [END] = { .type = RTE_FLOW_ITEM_TYPE_END, .spec = NULL, .mask = NULL, .last = NULL },   };    static int add_meter_profile(uint16_t port_id, uint32_t profile_id, struct rte_mtr_error *error)   {   struct rte_mtr_meter_profile profile;   memset(&profile, 0, sizeof(profile)); profile.alg = RTE_MTR_SRTCM_RFC2697; /* the one supported. */ profile.srtcm_rfc2697.cir = 1*1024*1024; /* 1MBps. */ profile.srtcm_rfc2697.cbs = 64*1024; /* allow burst in 64KB. */ profile.srtcm_rfc2697.ebs = 0; /* ignored. */ profile.packet_mode = 0;   return rte_mtr_meter_profile_add(port_id, profile_id, &profile, error);   }   static int add_meter_policy(uint16_t port_id, uint32_t policy_id, struct rte_mtr_error *error)   {   struct rte_mtr_meter_policy_params policy = {0}; const struct rte_flow_action end = {RTE_FLOW_ACTION_TYPE_DROP, NULL};   policy.actions[RTE_COLOR_GREEN] = NULL; policy.actions[RTE_COLOR_YELLOW] = NULL; policy.actions[RTE_COLOR_RED] = &end;   return rte_mtr_meter_policy_add(port_id,  policy_id, &policy, error);   }   static int create_meter(uint16_t port_id, uint32_t mtr_id, uint32_t profile_id, uint32_t policy_id, int shared, struct rte_mtr_error *error)   {   struct rte_mtr_params params;   memset(params, 0, sizeof(params)); params.meter_enable = 1; params.use_prev_mtr_color = 0; params.meter_policy_id = policy_id; params.meter_profile_id = profile_id; params.dscp_table = NULL; /* no input color. */   /* Enable all stats. */   params.stats_mask = RTE_MTR_STATS_N_BYTES_GREEN | RTE_MTR_STATS_N_BYTES_YELLOW | RTE_MTR_STATS_N_BYTES_RED | RTE_MTR_STATS_N_BYTES_DROPPED | RTE_MTR_STATS_N_PKTS_GREEN | RTE_MTR_STATS_N_PKTS_YELLOW | RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_PKTS_DROPPED;   return rte_mtr_create(port_id, mtr_id, ms, shared, error);   }     /*   * create flow with meter. port 0-2 is PF, VF1, VF2 * meter create on port_id, and match port_id + 1 traffic, * redirect to port + 2 if matching */   int create_flow_with_meter(uint16_t port_id) {   int ret; struct rte_mtr_error mtr_error; uint32_t profile_id = 0; uint32_t policy_id = 0; uint32_t mtr_id = 0;   int shared = 1; /* mtr is shared. */   ret = add_meter_profile(port_id, profile_id, &mtr_error); if (ret) { printf("cannot add meter profile, error: %s\n", mtr_error.message);   return ret; }   ret = add_meter_policy(port_id, policy_id, &mtr_error); if (ret) { printf("cannot add meter policy, error: %s\n", mtr_error.message); return ret;   }   ret = create_meter(port_id, mtr_id, profile_id, policy_id, shared, &mtr_error); if (ret) { printf("cannot create meter: %u with profile: %u, error: %s\n", mtr_id, 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 = 0, /* set the rule on the main group. */ .ingress = 1,/* rx flow. */ .transfer = 1, .priority = 1, }; /* add priority to rule to give the decap rule higher priority since it is more specific */ struct rte_flow_item_port_id port_mask = { .id = 0xffffffff,   };   struct rte_flow_item_port_id port_spec = { .id = port_id + 1,   };   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[L4].type = RTE_FLOW_ITEM_TYPE_PORT_ID; pattern[L4].spec = &port_spec; pattern[L4].mask = &port_mask; pattern[TUNNEL].type = RTE_FLOW_ITEM_TYPE_END;   struct rte_flow_action_meter meter = {.mtr_id = mtr_id}; struct rte_flow_action_port_id port_conf = {.id = port_id + 2}; struct rte_flow_action actions[] = {   [0] = { /* meter action. */ .type = RTE_FLOW_ACTION_TYPE_METER, .conf = &meter},   [1] = { /* the queue action to be used. */ .type = RTE_FLOW_ACTION_TYPE_PORT_ID, .conf = &port_conf },   [2] = { /* 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, mtr profile: %u on port: %u, error: %s\n", mtr_id, profile_id, port_id, error.message); return -1;   }   return 0;   }

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