+/** Parse RSS action. */
+static int
+parse_vc_action_rss(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ union action_rss_data *action_rss_data;
+ unsigned int i;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Set up default configuration. */
+ action_rss_data = ctx->object;
+ *action_rss_data = (union action_rss_data){
+ .conf = (struct rte_flow_action_rss){
+ .rss_conf = &action_rss_data->s.rss_conf,
+ .num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
+ },
+ };
+ action_rss_data->s.rss_conf = (struct rte_eth_rss_conf){
+ .rss_key = action_rss_data->s.rss_key,
+ .rss_key_len = sizeof(action_rss_data->s.rss_key),
+ .rss_hf = rss_hf,
+ };
+ strncpy((void *)action_rss_data->s.rss_key,
+ "testpmd's default RSS hash key",
+ sizeof(action_rss_data->s.rss_key));
+ for (i = 0; i < action_rss_data->conf.num; ++i)
+ action_rss_data->conf.queue[i] = i;
+ if (!port_id_is_invalid(ctx->port, DISABLED_WARN) &&
+ ctx->port != (portid_t)RTE_PORT_ALL) {
+ struct rte_eth_dev_info info;
+
+ rte_eth_dev_info_get(ctx->port, &info);
+ action_rss_data->s.rss_conf.rss_key_len =
+ RTE_MIN(sizeof(action_rss_data->s.rss_key),
+ info.hash_key_size);
+ }
+ action->conf = &action_rss_data->conf;
+ return ret;
+}
+