ACTION_COUNT,
ACTION_RSS,
ACTION_RSS_FUNC,
+ ACTION_RSS_LEVEL,
ACTION_RSS_FUNC_DEFAULT,
ACTION_RSS_FUNC_TOEPLITZ,
ACTION_RSS_FUNC_SIMPLE_XOR,
static const enum index action_rss[] = {
ACTION_RSS_FUNC,
+ ACTION_RSS_LEVEL,
ACTION_RSS_TYPES,
ACTION_RSS_KEY,
ACTION_RSS_KEY_LEN,
.help = "simple XOR hash function",
.call = parse_vc_action_rss_func,
},
+ [ACTION_RSS_LEVEL] = {
+ .name = "level",
+ .help = "encapsulation level for \"types\"",
+ .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY_ARB
+ (offsetof(struct action_rss_data, conf) +
+ offsetof(struct rte_flow_action_rss, level),
+ sizeof(((struct rte_flow_action_rss *)0)->
+ level))),
+ },
[ACTION_RSS_TYPES] = {
.name = "types",
.help = "specific RSS hash types",
*action_rss_data = (struct action_rss_data){
.conf = (struct rte_flow_action_rss){
.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
+ .level = 0,
.types = rss_hf,
.key_len = sizeof(action_rss_data->key),
.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
if (dst.rss)
*dst.rss = (struct rte_flow_action_rss){
.func = src.rss->func,
+ .level = src.rss->level,
.types = src.rss->types,
.key_len = src.rss->key_len,
.queue_num = src.rss->queue_num,
overlaps ``hash.fdir.lo``. Since `Action: MARK`_ sets the ``hash.fdir.hi``
field only, both can be requested simultaneously.
+Also, regarding packet encapsulation ``level``:
+
+- ``0`` requests the default behavior. Depending on the packet type, it can
+ mean outermost, innermost, anything in between or even no RSS.
+
+ It basically stands for the innermost encapsulation level RSS can be
+ performed on according to PMD and device capabilities.
+
+- ``1`` requests RSS to be performed on the outermost packet encapsulation
+ level.
+
+- ``2`` and subsequent values request RSS to be performed on the specified
+ inner packet encapsulation level, from outermost to innermost (lower to
+ higher values).
+
+Values other than ``0`` are not necessarily supported.
+
+Requesting a specific RSS level on unrecognized traffic results in undefined
+behavior. For predictable results, it is recommended to make the flow rule
+pattern match packet headers up to the requested encapsulation level so that
+only matching traffic goes through.
+
.. _table_rte_flow_action_rss:
.. table:: RSS
+===============+=============================================+
| ``func`` | RSS hash function to apply |
+---------------+---------------------------------------------+
+ | ``level`` | encapsulation level for ``types`` |
+ +---------------+---------------------------------------------+
| ``types`` | specific RSS hash types (see ``ETH_RSS_*``) |
+---------------+---------------------------------------------+
| ``key_len`` | hash key length in bytes |
Target release for removal of the legacy API will be defined once most
PMDs have switched to rte_flow.
-* ethdev: A new rss level field planned in 18.05.
- The new API add rss_level field to ``rte_eth_rss_conf`` to enable a choice
- of RSS hash calculation on outer or inner header of tunneled packet.
-
* ethdev: A work is being planned for 18.05 to expose VF port representors
as a mean to perform control and data path operation on the different VFs.
As VF representor is an ethdev port, new fields are needed in order to map
``rss_conf->rss_key_len`` => ``key_len``,
``rss_conf->rss_hf`` => ``types``,
``num`` => ``queue_num``), and the addition of missing RSS parameters
- (``func`` for RSS hash function to apply).
+ (``func`` for RSS hash function to apply and ``level`` for the
+ encapsulation level).
ABI Changes
- ``func {hash function}``: RSS hash function to apply, allowed tokens are
the same as `set_hash_global_config`_.
+ - ``level {unsigned}``: encapsulation level for ``types``.
+
- ``types [{RSS hash type} [...]] end``: specific RSS hash types, allowed
tokens are the same as `set_hash_input_set`_, except that an empty list
does not disable RSS but instead requests unspecified "best-effort"
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
"non-default RSS hash functions are not supported");
+ if (rss->level)
+ return rte_flow_error_set
+ (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
+ "a nonzero RSS encapsulation level is not supported");
if (rss->key_len && rss->key_len != RTE_DIM(rss_conf->key))
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
return -EINVAL;
out->conf = (struct rte_flow_action_rss){
.func = in->func,
+ .level = in->level,
.types = in->types,
.key_len = in->key_len,
.queue_num = in->queue_num,
const struct rte_flow_action_rss *with)
{
return (comp->func == with->func &&
+ comp->level == with->level &&
comp->types == with->types &&
comp->key_len == with->key_len &&
comp->queue_num == with->queue_num &&
return -EINVAL;
out->conf = (struct rte_flow_action_rss){
.func = in->func,
+ .level = in->level,
.types = in->types,
.key_len = in->key_len,
.queue_num = in->queue_num,
const struct rte_flow_action_rss *with)
{
return (comp->func == with->func &&
+ comp->level == with->level &&
comp->types == with->types &&
comp->key_len == with->key_len &&
comp->queue_num == with->queue_num &&
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
"non-default RSS hash functions are not supported");
+ if (rss->level)
+ return rte_flow_error_set
+ (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
+ "a nonzero RSS encapsulation level is not supported");
if (rss->key_len && rss->key_len > RTE_DIM(rss_config->key))
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
"non-default RSS hash functions are not supported");
+ if (rss->level)
+ return rte_flow_error_set
+ (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
+ "a nonzero RSS encapsulation level is not supported");
if (rss->key_len && rss->key_len != RTE_DIM(rss_conf->key))
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
return -EINVAL;
out->conf = (struct rte_flow_action_rss){
.func = in->func,
+ .level = in->level,
.types = in->types,
.key_len = in->key_len,
.queue_num = in->queue_num,
const struct rte_flow_action_rss *with)
{
return (comp->func == with->func &&
+ comp->level == with->level &&
comp->types == with->types &&
comp->key_len == with->key_len &&
comp->queue_num == with->queue_num &&
" is Toeplitz";
goto exit_action_not_supported;
}
+ if (rss->level) {
+ msg = "a nonzero RSS encapsulation level is"
+ " not supported";
+ goto exit_action_not_supported;
+ }
rte_errno = 0;
fields = mlx4_conv_rss_types(priv, rss->types);
if (fields == (uint64_t)-1 && rte_errno) {
uint16_t queue[queues];
struct rte_flow_action_rss action_rss = {
.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
+ .level = 0,
.types = -1,
.key_len = MLX4_RSS_HASH_KEY_SIZE,
.queue_num = queues,
" function is Toeplitz");
return -rte_errno;
}
+ if (rss->level) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ actions,
+ "a nonzero RSS encapsulation"
+ " level is not supported");
+ return -rte_errno;
+ }
if (rss->types & MLX5_RSS_HF_MASK) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
}
parser->rss_conf = (struct rte_flow_action_rss){
.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
+ .level = 0,
.types = rss->types,
.key_len = rss_key_len,
.queue_num = rss->queue_num,
flow->queues = (uint16_t (*)[])(flow + 1);
flow->rss_conf = (struct rte_flow_action_rss){
.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
+ .level = 0,
.types = parser.rss_conf.types,
.key_len = parser.rss_conf.key_len,
.queue_num = parser.rss_conf.queue_num,
uint16_t queue[priv->reta_idx_n];
struct rte_flow_action_rss action_rss = {
.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
+ .level = 0,
.types = priv->rss_conf.rss_hf,
.key_len = priv->rss_conf.rss_key_len,
.queue_num = priv->reta_idx_n,
return -EINVAL;
}
+ if (rss->level)
+ return -EINVAL;
+
if ((rss->types & ~SFC_RSS_OFFLOADS) != 0)
return -EINVAL;
struct rss_key rss_entry = { .hash_fields = 0,
.key_size = 0 };
- /* Check supported hash functions */
+ /* Check supported RSS features */
if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT)
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
"non-default RSS hash functions are not supported");
+ if (rss->level)
+ return rte_flow_error_set
+ (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "a nonzero RSS encapsulation level is not supported");
/* Get a new map key for a new RSS rule */
err = bpf_rss_key(KEY_CMD_GET, &flow->key_idx);
if (dst.rss)
*dst.rss = (struct rte_flow_action_rss){
.func = src.rss->func,
+ .level = src.rss->level,
.types = src.rss->types,
.key_len = src.rss->key_len,
.queue_num = src.rss->queue_num,
*/
struct rte_flow_action_rss {
enum rte_eth_hash_function func; /**< RSS hash function to apply. */
+ /**
+ * Packet encapsulation level RSS hash @p types apply to.
+ *
+ * - @p 0 requests the default behavior. Depending on the packet
+ * type, it can mean outermost, innermost, anything in between or
+ * even no RSS.
+ *
+ * It basically stands for the innermost encapsulation level RSS
+ * can be performed on according to PMD and device capabilities.
+ *
+ * - @p 1 requests RSS to be performed on the outermost packet
+ * encapsulation level.
+ *
+ * - @p 2 and subsequent values request RSS to be performed on the
+ * specified inner packet encapsulation level, from outermost to
+ * innermost (lower to higher values).
+ *
+ * Values other than @p 0 are not necessarily supported.
+ *
+ * Requesting a specific RSS level on unrecognized traffic results
+ * in undefined behavior. For predictable results, it is recommended
+ * to make the flow rule pattern match packet headers up to the
+ * requested encapsulation level so that only matching traffic goes
+ * through.
+ */
+ uint32_t level;
uint64_t types; /**< Specific RSS hash types (see ETH_RSS_*). */
uint32_t key_len; /**< Hash key length in bytes. */
uint32_t queue_num; /**< Number of entries in @p queue. */