+ /* parse action */
+ index = 0;
+
+ /**
+ * n-tuple only supports count and Mark,
+ * check if the first not void action is COUNT or MARK.
+ */
+ memset(&action, 0, sizeof(action));
+ NEXT_ITEM_OF_ACTION(act, actions, index);
+ switch (act->type) {
+ case RTE_FLOW_ACTION_TYPE_COUNT:
+ action.action_mask |= 1LLU << RTE_FLOW_ACTION_TYPE_COUNT;
+ count = act->conf;
+ memcpy(&action.act.counter, count, sizeof(action.act.counter));
+ break;
+ case RTE_FLOW_ACTION_TYPE_MARK:
+ action.action_mask |= 1LLU << RTE_FLOW_ACTION_TYPE_MARK;
+ mark_spec = act->conf;
+ memcpy(&action.act.mark, mark_spec, sizeof(action.act.mark));
+ break;
+ default:
+ memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, act,
+ "Invalid action.");
+ return -EINVAL;
+ }
+
+ /* check if the next not void item is MARK or COUNT or END */
+ index++;
+ NEXT_ITEM_OF_ACTION(act, actions, index);
+ switch (act->type) {
+ case RTE_FLOW_ACTION_TYPE_COUNT:
+ action.action_mask |= 1LLU << RTE_FLOW_ACTION_TYPE_COUNT;
+ count = act->conf;
+ memcpy(&action.act.counter, count, sizeof(action.act.counter));
+ break;
+ case RTE_FLOW_ACTION_TYPE_MARK:
+ action.action_mask |= 1LLU << RTE_FLOW_ACTION_TYPE_MARK;
+ mark_spec = act->conf;
+ memcpy(&action.act.mark, mark_spec, sizeof(action.act.mark));
+ break;
+ case RTE_FLOW_ACTION_TYPE_END:
+ return 0;
+ default:
+ memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, act,
+ "Invalid action.");
+ return -EINVAL;
+ }
+
+ /* check if the next not void item is END */
+ index++;
+ NEXT_ITEM_OF_ACTION(act, actions, index);
+ if (act->type != RTE_FLOW_ACTION_TYPE_END) {
+ memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, act,
+ "Invalid action.");
+ return -EINVAL;
+ }
+