ethdev: add encap level to RSS flow API action
RSS hash types (ETH_RSS_* macros defined in rte_ethdev.h) describe the
protocol header fields of a packet that must be taken into account while
computing RSS.
When facing encapsulated (e.g. tunneled) packets, there is an ambiguity as
to whether these should apply to inner or outer packets. Applications need
the ability to tell exactly "where" RSS must be performed.
This is addressed by adding encapsulation level information to the RSS flow
action. Its default value is 0 and stands for the usual unspecified
behavior. Other values provide a specific encapsulation level.
Contrary to the change announced by commit 676b605182
("doc: announce
ethdev API change for RSS configuration"), this patch does not affect
struct rte_eth_rss_conf but struct rte_flow_action_rss as the former is not
used anymore by the RSS flow action. ABI impact is therefore limited to
rte_flow.
This breaks ABI compatibility for the following public functions:
- rte_flow_copy()
- rte_flow_create()
- rte_flow_query()
- rte_flow_validate()
Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
Acked-by: Andrew Rybchenko <arybchenko@solarflare.com>
This commit is contained in:
parent
929e331934
commit
18aee2861a
@ -167,6 +167,7 @@ enum index {
|
||||
ACTION_COUNT,
|
||||
ACTION_RSS,
|
||||
ACTION_RSS_FUNC,
|
||||
ACTION_RSS_LEVEL,
|
||||
ACTION_RSS_FUNC_DEFAULT,
|
||||
ACTION_RSS_FUNC_TOEPLITZ,
|
||||
ACTION_RSS_FUNC_SIMPLE_XOR,
|
||||
@ -638,6 +639,7 @@ static const enum index action_queue[] = {
|
||||
|
||||
static const enum index action_rss[] = {
|
||||
ACTION_RSS_FUNC,
|
||||
ACTION_RSS_LEVEL,
|
||||
ACTION_RSS_TYPES,
|
||||
ACTION_RSS_KEY,
|
||||
ACTION_RSS_KEY_LEN,
|
||||
@ -1616,6 +1618,16 @@ static const struct token token_list[] = {
|
||||
.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",
|
||||
@ -2107,6 +2119,7 @@ parse_vc_action_rss(struct context *ctx, const struct token *token,
|
||||
*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),
|
||||
|
@ -1118,6 +1118,7 @@ flow_action_conf_copy(void *buf, const struct rte_flow_action *action)
|
||||
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,
|
||||
|
@ -1311,6 +1311,28 @@ Note: RSS hash result is stored in the ``hash.rss`` mbuf field which
|
||||
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
|
||||
@ -1320,6 +1342,8 @@ field only, both can be requested simultaneously.
|
||||
+===============+=============================================+
|
||||
| ``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 |
|
||||
|
@ -59,10 +59,6 @@ Deprecation Notices
|
||||
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
|
||||
|
@ -276,7 +276,8 @@ API Changes
|
||||
``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
|
||||
|
@ -3425,6 +3425,8 @@ This section lists supported actions and their attributes, if any.
|
||||
- ``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"
|
||||
|
@ -1314,6 +1314,10 @@ igb_parse_rss_filter(struct rte_eth_dev *dev,
|
||||
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,
|
||||
|
@ -2906,6 +2906,7 @@ igb_rss_conf_init(struct igb_rte_flow_rss_conf *out,
|
||||
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,
|
||||
@ -2921,6 +2922,7 @@ igb_action_rss_same(const struct rte_flow_action_rss *comp,
|
||||
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 &&
|
||||
|
@ -12191,6 +12191,7 @@ i40e_rss_conf_init(struct i40e_rte_flow_rss_conf *out,
|
||||
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,
|
||||
@ -12206,6 +12207,7 @@ i40e_action_rss_same(const struct rte_flow_action_rss *comp,
|
||||
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 &&
|
||||
|
@ -4380,6 +4380,10 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
|
||||
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,
|
||||
|
@ -2783,6 +2783,10 @@ ixgbe_parse_rss_filter(struct rte_eth_dev *dev,
|
||||
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,
|
||||
|
@ -5684,6 +5684,7 @@ ixgbe_rss_conf_init(struct ixgbe_rte_flow_rss_conf *out,
|
||||
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,
|
||||
@ -5699,6 +5700,7 @@ ixgbe_action_rss_same(const struct rte_flow_action_rss *comp,
|
||||
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 &&
|
||||
|
@ -796,6 +796,11 @@ mlx4_flow_prepare(struct priv *priv,
|
||||
" 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) {
|
||||
@ -1290,6 +1295,7 @@ mlx4_flow_internal(struct priv *priv, struct rte_flow_error *error)
|
||||
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,
|
||||
|
@ -652,6 +652,14 @@ mlx5_flow_convert_actions(struct rte_eth_dev *dev,
|
||||
" 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,
|
||||
@ -702,6 +710,7 @@ mlx5_flow_convert_actions(struct rte_eth_dev *dev,
|
||||
}
|
||||
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,
|
||||
@ -1937,6 +1946,7 @@ mlx5_flow_list_create(struct rte_eth_dev *dev,
|
||||
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,
|
||||
@ -2452,6 +2462,7 @@ mlx5_ctrl_flow_vlan(struct rte_eth_dev *dev,
|
||||
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,
|
||||
|
@ -1269,6 +1269,9 @@ sfc_flow_parse_rss(struct sfc_adapter *sa,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (rss->level)
|
||||
return -EINVAL;
|
||||
|
||||
if ((rss->types & ~SFC_RSS_OFFLOADS) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -2055,11 +2055,15 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd,
|
||||
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);
|
||||
|
@ -331,6 +331,7 @@ flow_action_conf_copy(void *buf, const struct rte_flow_action *action)
|
||||
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,
|
||||
|
@ -1046,6 +1046,32 @@ struct rte_flow_query_count {
|
||||
*/
|
||||
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. */
|
||||
|
Loading…
Reference in New Issue
Block a user