* Protocol-independent flow API support
*/
static int
-sfc_flow_parse_attr(const struct rte_flow_attr *attr,
+sfc_flow_parse_attr(struct sfc_adapter *sa,
+ const struct rte_flow_attr *attr,
struct rte_flow *flow,
struct rte_flow_error *error)
{
struct sfc_flow_spec *spec = &flow->spec;
struct sfc_flow_spec_filter *spec_filter = &spec->filter;
+ struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+ struct sfc_mae *mae = &sa->mae;
if (attr == NULL) {
rte_flow_error_set(error, EINVAL,
spec_filter->template.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
spec_filter->template.efs_priority = EFX_FILTER_PRI_MANUAL;
} else {
- rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, attr,
- "Transfer is not supported");
- return -rte_errno;
+ if (mae->status != SFC_MAE_STATUS_SUPPORTED) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
+ attr, "Transfer is not supported");
+ return -rte_errno;
+ }
+ if (attr->priority > mae->nb_action_rule_prios_max) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
+ attr, "Unsupported priority level");
+ return -rte_errno;
+ }
+ spec->type = SFC_FLOW_SPEC_MAE;
+ spec_mae->priority = attr->priority;
}
return 0;
struct rte_flow *flow,
struct rte_flow_error *error)
{
+ struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
const struct sfc_flow_ops_by_spec *ops;
int rc;
- rc = sfc_flow_parse_attr(attr, flow, error);
+ rc = sfc_flow_parse_attr(sa, attr, flow, error);
if (rc != 0)
return rc;
/* Flow engines supported by the implementation */
enum sfc_flow_spec_type {
SFC_FLOW_SPEC_FILTER = 0,
+ SFC_FLOW_SPEC_MAE,
SFC_FLOW_SPEC_NTYPES
};
struct sfc_flow_rss rss_conf;
};
+/* MAE-specific flow specification */
+struct sfc_flow_spec_mae {
+ /* Desired priority level */
+ unsigned int priority;
+};
+
/* Flow specification */
struct sfc_flow_spec {
/* Flow specification type (engine-based) */
union {
/* Filter-based (VNIC level flows) specification */
struct sfc_flow_spec_filter filter;
+ /* MAE-based (lower-level HW switch flows) specification */
+ struct sfc_flow_spec_mae mae;
};
};
{
const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
struct sfc_mae *mae = &sa->mae;
+ efx_mae_limits_t limits;
int rc;
sfc_log_init(sa, "entry");
if (rc != 0)
goto fail_mae_init;
+ sfc_log_init(sa, "get MAE limits");
+ rc = efx_mae_get_limits(sa->nic, &limits);
+ if (rc != 0)
+ goto fail_mae_get_limits;
+
mae->status = SFC_MAE_STATUS_SUPPORTED;
+ mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
sfc_log_init(sa, "done");
return 0;
+fail_mae_get_limits:
+ efx_mae_fini(sa->nic);
+
fail_mae_init:
sfc_log_init(sa, "failed %d", rc);
sfc_log_init(sa, "entry");
+ mae->nb_action_rule_prios_max = 0;
mae->status = SFC_MAE_STATUS_UNKNOWN;
if (status_prev != SFC_MAE_STATUS_SUPPORTED)