const uint8_t *spec;
const uint8_t *mask;
const uint8_t *last;
- uint8_t match;
uint8_t supp;
unsigned int i;
return -rte_errno;
}
- /* Check that mask and spec not asks for more match than supp_mask */
+ /* Check that mask does not ask for more match than supp_mask */
for (i = 0; i < size; i++) {
- match = spec[i] | mask[i];
supp = ((const uint8_t *)supp_mask)[i];
- if ((match | supp) != supp) {
+ if (~supp & mask[i]) {
rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ITEM, item,
"Item's field is not supported");
"Egress is not supported");
return -rte_errno;
}
+ if (attr->transfer != 0) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, attr,
+ "Transfer is not supported");
+ return -rte_errno;
+ }
if (attr->ingress == 0) {
rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, attr,
return 0;
}
-#if EFSYS_OPT_RX_SCALE
static int
sfc_flow_parse_rss(struct sfc_adapter *sa,
- const struct rte_flow_action_rss *rss,
+ const struct rte_flow_action_rss *action_rss,
struct rte_flow *flow)
{
+ struct sfc_rss *rss = &sa->rss;
unsigned int rxq_sw_index;
struct sfc_rxq *rxq;
unsigned int rxq_hw_index_min;
unsigned int rxq_hw_index_max;
+ efx_rx_hash_type_t efx_hash_types;
const uint8_t *rss_key;
struct sfc_flow_rss *sfc_rss_conf = &flow->rss_conf;
unsigned int i;
- if (rss->queue_num == 0)
+ if (action_rss->queue_num == 0)
return -EINVAL;
rxq_sw_index = sa->rxq_count - 1;
rxq_hw_index_min = rxq->hw_index;
rxq_hw_index_max = 0;
- for (i = 0; i < rss->queue_num; ++i) {
- rxq_sw_index = rss->queue[i];
+ for (i = 0; i < action_rss->queue_num; ++i) {
+ rxq_sw_index = action_rss->queue[i];
if (rxq_sw_index >= sa->rxq_count)
return -EINVAL;
rxq_hw_index_max = rxq->hw_index;
}
- switch (rss->func) {
+ switch (action_rss->func) {
case RTE_ETH_HASH_FUNCTION_DEFAULT:
case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
break;
return -EINVAL;
}
- if (rss->level)
+ if (action_rss->level)
return -EINVAL;
- if ((rss->types & ~SFC_RSS_OFFLOADS) != 0)
- return -EINVAL;
+ /*
+ * Dummy RSS action with only one queue and no specific settings
+ * for hash types and key does not require dedicated RSS context
+ * and may be simplified to single queue action.
+ */
+ if (action_rss->queue_num == 1 && action_rss->types == 0 &&
+ action_rss->key_len == 0) {
+ flow->spec.template.efs_dmaq_id = rxq_hw_index_min;
+ return 0;
+ }
- if (rss->key_len) {
- if (rss->key_len != sizeof(sa->rss_key))
+ if (action_rss->types) {
+ int rc;
+
+ rc = sfc_rx_hf_rte_to_efx(sa, action_rss->types,
+ &efx_hash_types);
+ if (rc != 0)
+ return -rc;
+ } else {
+ unsigned int i;
+
+ efx_hash_types = 0;
+ for (i = 0; i < rss->hf_map_nb_entries; ++i)
+ efx_hash_types |= rss->hf_map[i].efx;
+ }
+
+ if (action_rss->key_len) {
+ if (action_rss->key_len != sizeof(rss->key))
return -EINVAL;
- rss_key = rss->key;
+ rss_key = action_rss->key;
} else {
- rss_key = sa->rss_key;
+ rss_key = rss->key;
}
flow->rss = B_TRUE;
sfc_rss_conf->rxq_hw_index_min = rxq_hw_index_min;
sfc_rss_conf->rxq_hw_index_max = rxq_hw_index_max;
- sfc_rss_conf->rss_hash_types = sfc_rte_to_efx_hash_type(rss->types);
- rte_memcpy(sfc_rss_conf->rss_key, rss_key, sizeof(sa->rss_key));
+ sfc_rss_conf->rss_hash_types = efx_hash_types;
+ rte_memcpy(sfc_rss_conf->rss_key, rss_key, sizeof(rss->key));
for (i = 0; i < RTE_DIM(sfc_rss_conf->rss_tbl); ++i) {
- unsigned int rxq_sw_index = rss->queue[i % rss->queue_num];
+ unsigned int nb_queues = action_rss->queue_num;
+ unsigned int rxq_sw_index = action_rss->queue[i % nb_queues];
struct sfc_rxq *rxq = sa->rxq_info[rxq_sw_index].rxq;
sfc_rss_conf->rss_tbl[i] = rxq->hw_index - rxq_hw_index_min;
return 0;
}
-#endif /* EFSYS_OPT_RX_SCALE */
static int
sfc_flow_spec_flush(struct sfc_adapter *sa, struct sfc_flow_spec *spec,
sfc_flow_filter_insert(struct sfc_adapter *sa,
struct rte_flow *flow)
{
-#if EFSYS_OPT_RX_SCALE
- struct sfc_flow_rss *rss = &flow->rss_conf;
+ struct sfc_rss *rss = &sa->rss;
+ struct sfc_flow_rss *flow_rss = &flow->rss_conf;
uint32_t efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
unsigned int i;
int rc = 0;
if (flow->rss) {
- unsigned int rss_spread = MIN(rss->rxq_hw_index_max -
- rss->rxq_hw_index_min + 1,
+ unsigned int rss_spread = MIN(flow_rss->rxq_hw_index_max -
+ flow_rss->rxq_hw_index_min + 1,
EFX_MAXRSS);
rc = efx_rx_scale_context_alloc(sa->nic,
goto fail_scale_context_alloc;
rc = efx_rx_scale_mode_set(sa->nic, efs_rss_context,
- EFX_RX_HASHALG_TOEPLITZ,
- rss->rss_hash_types, B_TRUE);
+ rss->hash_alg,
+ flow_rss->rss_hash_types, B_TRUE);
if (rc != 0)
goto fail_scale_mode_set;
rc = efx_rx_scale_key_set(sa->nic, efs_rss_context,
- rss->rss_key,
- sizeof(sa->rss_key));
+ flow_rss->rss_key,
+ sizeof(rss->key));
if (rc != 0)
goto fail_scale_key_set;
efx_filter_spec_t *spec = &flow->spec.filters[i];
spec->efs_rss_context = efs_rss_context;
- spec->efs_dmaq_id = rss->rxq_hw_index_min;
+ spec->efs_dmaq_id = flow_rss->rxq_hw_index_min;
spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS;
}
}
* the table entries, and the operation will succeed
*/
rc = efx_rx_scale_tbl_set(sa->nic, efs_rss_context,
- rss->rss_tbl, RTE_DIM(rss->rss_tbl));
+ flow_rss->rss_tbl,
+ RTE_DIM(flow_rss->rss_tbl));
if (rc != 0)
goto fail_scale_tbl_set;
}
fail_scale_context_alloc:
return rc;
-#else /* !EFSYS_OPT_RX_SCALE */
- return sfc_flow_spec_insert(sa, &flow->spec);
-#endif /* EFSYS_OPT_RX_SCALE */
}
static int
if (rc != 0)
return rc;
-#if EFSYS_OPT_RX_SCALE
if (flow->rss) {
/*
* All specifications for a given flow rule have the same RSS
rc = efx_rx_scale_context_free(sa->nic, spec->efs_rss_context);
}
-#endif /* EFSYS_OPT_RX_SCALE */
return rc;
}
struct rte_flow_error *error)
{
int rc;
- boolean_t is_specified = B_FALSE;
+ uint32_t actions_set = 0;
+ const uint32_t fate_actions_mask = (1UL << RTE_FLOW_ACTION_TYPE_QUEUE) |
+ (1UL << RTE_FLOW_ACTION_TYPE_RSS) |
+ (1UL << RTE_FLOW_ACTION_TYPE_DROP);
if (actions == NULL) {
rte_flow_error_set(error, EINVAL,
return -rte_errno;
}
+#define SFC_BUILD_SET_OVERFLOW(_action, _set) \
+ RTE_BUILD_BUG_ON(_action >= sizeof(_set) * CHAR_BIT)
+
for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
- /* This one may appear anywhere multiple times. */
- if (actions->type == RTE_FLOW_ACTION_TYPE_VOID)
- continue;
- /* Fate-deciding actions may appear exactly once. */
- if (is_specified) {
- rte_flow_error_set
- (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
- actions,
- "Cannot combine several fate-deciding actions,"
- "choose between QUEUE, RSS or DROP");
- return -rte_errno;
- }
switch (actions->type) {
+ case RTE_FLOW_ACTION_TYPE_VOID:
+ SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VOID,
+ actions_set);
+ break;
+
case RTE_FLOW_ACTION_TYPE_QUEUE:
+ SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_QUEUE,
+ actions_set);
+ if ((actions_set & fate_actions_mask) != 0)
+ goto fail_fate_actions;
+
rc = sfc_flow_parse_queue(sa, actions->conf, flow);
if (rc != 0) {
rte_flow_error_set(error, EINVAL,
"Bad QUEUE action");
return -rte_errno;
}
-
- is_specified = B_TRUE;
break;
-#if EFSYS_OPT_RX_SCALE
case RTE_FLOW_ACTION_TYPE_RSS:
+ SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_RSS,
+ actions_set);
+ if ((actions_set & fate_actions_mask) != 0)
+ goto fail_fate_actions;
+
rc = sfc_flow_parse_rss(sa, actions->conf, flow);
if (rc != 0) {
rte_flow_error_set(error, rc,
"Bad RSS action");
return -rte_errno;
}
-
- is_specified = B_TRUE;
break;
-#endif /* EFSYS_OPT_RX_SCALE */
case RTE_FLOW_ACTION_TYPE_DROP:
+ SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DROP,
+ actions_set);
+ if ((actions_set & fate_actions_mask) != 0)
+ goto fail_fate_actions;
+
flow->spec.template.efs_dmaq_id =
EFX_FILTER_SPEC_RX_DMAQ_ID_DROP;
-
- is_specified = B_TRUE;
break;
default:
"Action is not supported");
return -rte_errno;
}
+
+ actions_set |= (1UL << actions->type);
}
+#undef SFC_BUILD_SET_OVERFLOW
/* When fate is unknown, drop traffic. */
- if (!is_specified) {
+ if ((actions_set & fate_actions_mask) == 0) {
flow->spec.template.efs_dmaq_id =
EFX_FILTER_SPEC_RX_DMAQ_ID_DROP;
}
return 0;
+
+fail_fate_actions:
+ rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, actions,
+ "Cannot combine several fate-deciding actions, "
+ "choose between QUEUE, RSS or DROP");
+ return -rte_errno;
}
/**