@@ -1474,6 +1474,101 @@ flow_rule_action_get(struct pmd_internals *softnic,
break;
} /* RTE_FLOW_ACTION_TYPE_COUNT */
+ case RTE_FLOW_ACTION_TYPE_METER:
+ {
+ struct rte_table_action_mtr_tc_params mtr_tc_params;
+ const struct rte_flow_action_meter *conf = action->conf;
+ struct rte_table_action_meter_profile profile;
+ struct softnic_mtr_meter_profile *mp;
+ struct softnic_mtr *m;
+ uint32_t i, meter_profile_id, table_id = UINT32_MAX;
+ int status;
+
+ if (conf == NULL)
+ return rte_flow_error_set(error,
+ EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ action,
+ "METER: Null configuration");
+
+ if ((params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) == 0)
+ return rte_flow_error_set(error,
+ EINVAL,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "METER: table action not supported");
+
+ m = softnic_mtr_find(softnic, conf->mtr_id);
+ if (m == NULL)
+ return -rte_flow_error_set(error,
+ EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+ NULL,
+ "METER: invalid meter id");
+
+ if (m->flow)
+ return -rte_flow_error_set(error,
+ EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+ NULL,
+ "METER: meter already attached to flow");
+
+ if (params->mtr.n_tc != 1)
+ return -rte_flow_error_set(error,
+ EINVAL,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "METER: multiple TCs not supported");
+
+ meter_profile_id = m->params.meter_profile_id;
+ mp = softnic_mtr_meter_profile_find(softnic, meter_profile_id);
+
+ memset(&profile, 0, sizeof(profile));
+ profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
+ profile.trtcm.cir = mp->params.trtcm_rfc2698.cir;
+ profile.trtcm.pir = mp->params.trtcm_rfc2698.pir;
+ profile.trtcm.cbs = mp->params.trtcm_rfc2698.cbs;
+ profile.trtcm.pbs = mp->params.trtcm_rfc2698.pbs;
+
+ /* Identify the pipeline table to add this flow to. */
+ for (i = 0; i < pipeline->n_tables; i++) {
+ if (table == &pipeline->table[i]) {
+ table_id = i;
+ break;
+ }
+ }
+
+ /* Add meter profile to pipeline table */
+ status = softnic_pipeline_table_mtr_profile_add(softnic,
+ pipeline->name,
+ table_id,
+ meter_profile_id,
+ &profile);
+ if (status) {
+ rte_flow_error_set(error,
+ EINVAL,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "Table meter profile add failed");
+ return -1;
+ }
+
+ /* RTE_TABLE_ACTION_METER */
+ mtr_tc_params.meter_profile_id = meter_profile_id;
+ mtr_tc_params.policer[e_RTE_METER_GREEN] =
+ (enum rte_table_action_policer)m->params.action[RTE_MTR_GREEN];
+ mtr_tc_params.policer[e_RTE_METER_YELLOW] =
+ (enum rte_table_action_policer)m->params.action[RTE_MTR_YELLOW];
+ mtr_tc_params.policer[e_RTE_METER_RED] =
+ (enum rte_table_action_policer)m->params.action[RTE_MTR_RED];
+
+ memcpy(&rule_action->mtr.mtr[0], &mtr_tc_params,
+ sizeof(rule_action->mtr.mtr[0]));
+ rule_action->mtr.tc_mask = 1 << 0;
+ rule_action->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
+ break;
+ } /* RTE_FLOW_ACTION_TYPE_METER */
+
default:
return -ENOTSUP;
}
@@ -1577,6 +1672,34 @@ pmd_flow_validate(struct rte_eth_dev *dev,
return 0;
}
+static void set_meter_owner_to_flow(struct pmd_internals *softnic,
+ struct rte_flow *flow,
+ const struct rte_flow_action *action)
+{
+ for ( ; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
+ if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
+ continue;
+
+ if (action->type == RTE_FLOW_ACTION_TYPE_METER) {
+ const struct rte_flow_action_meter *conf = action->conf;
+ struct softnic_mtr_list *ml = &softnic->mtr.mtrs;
+ struct softnic_mtr *m;
+
+ TAILQ_FOREACH(m, ml, node) {
+ if (m->flow == flow) {
+ m->flow = NULL;
+ break;
+ }
+ }
+
+ m = softnic_mtr_find(softnic, conf->mtr_id);
+ m->flow = flow;
+
+ break;
+ }
+ }
+}
+
static struct rte_flow *
pmd_flow_create(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
@@ -1717,6 +1840,8 @@ pmd_flow_create(struct rte_eth_dev *dev,
flow->pipeline = pipeline;
flow->table_id = table_id;
+ set_meter_owner_to_flow(softnic, flow, action);
+
/* Flow add to list. */
if (new_flow)
TAILQ_INSERT_TAIL(&table->flows, flow, node);
@@ -1724,6 +1849,31 @@ pmd_flow_create(struct rte_eth_dev *dev,
return flow;
}
+static void reset_meter_owner(struct pmd_internals *softnic,
+ struct softnic_table *table,
+ struct rte_flow *flow)
+{
+ struct softnic_table_action_profile *profile;
+ struct softnic_table_action_profile_params *params;
+
+ profile = softnic_table_action_profile_find(softnic,
+ table->params.action_profile_name);
+
+ params = &profile->params;
+
+ if ((params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) == 0) {
+ struct softnic_mtr_list *ml = &softnic->mtr.mtrs;
+ struct softnic_mtr *m;
+
+ TAILQ_FOREACH(m, ml, node) {
+ if (m->flow == flow) {
+ m->flow = NULL;
+ break;
+ }
+ }
+ }
+}
+
static int
pmd_flow_destroy(struct rte_eth_dev *dev,
struct rte_flow *flow,
@@ -1759,6 +1909,9 @@ pmd_flow_destroy(struct rte_eth_dev *dev,
TAILQ_REMOVE(&table->flows, flow, node);
free(flow);
+ /* Update dependencies */
+ reset_meter_owner(softnic, table, flow);
+
return 0;
}
Implement flow rules with meter action. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> --- drivers/net/softnic/rte_eth_softnic_flow.c | 153 +++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+)