Use the common attr and action parsing infrastructure in flow director filters (both tunnel and normal). As a result, some checks have become more stringent, in particular group attribute is now explicitly rejected instead of being ignored.
Signed-off-by: Anatoly Burakov <[email protected]> --- drivers/net/intel/ixgbe/ixgbe_flow.c | 290 ++++++++++++--------------- 1 file changed, 128 insertions(+), 162 deletions(-) diff --git a/drivers/net/intel/ixgbe/ixgbe_flow.c b/drivers/net/intel/ixgbe/ixgbe_flow.c index 38a8002611..c857eb0227 100644 --- a/drivers/net/intel/ixgbe/ixgbe_flow.c +++ b/drivers/net/intel/ixgbe/ixgbe_flow.c @@ -1182,111 +1182,6 @@ ixgbe_parse_l2_tn_filter(struct rte_eth_dev *dev, return ret; } -/* Parse to get the attr and action info of flow director rule. */ -static int -ixgbe_parse_fdir_act_attr(const struct rte_flow_attr *attr, - const struct rte_flow_action actions[], - struct ixgbe_fdir_rule *rule, - struct rte_flow_error *error) -{ - const struct rte_flow_action *act; - const struct rte_flow_action_queue *act_q; - const struct rte_flow_action_mark *mark; - - /* parse attr */ - /* must be input direction */ - if (!attr->ingress) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, - attr, "Only support ingress."); - return -rte_errno; - } - - /* not supported */ - if (attr->egress) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, - attr, "Not support egress."); - return -rte_errno; - } - - /* not supported */ - if (attr->transfer) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, - attr, "No support for transfer."); - return -rte_errno; - } - - /* not supported */ - if (attr->priority) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, - attr, "Not support priority."); - return -rte_errno; - } - - /* check if the first not void action is QUEUE or DROP. */ - act = next_no_void_action(actions, NULL); - if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE && - act->type != RTE_FLOW_ACTION_TYPE_DROP) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, - act, "Not supported action."); - return -rte_errno; - } - - if (act->type == RTE_FLOW_ACTION_TYPE_QUEUE) { - act_q = (const struct rte_flow_action_queue *)act->conf; - rule->queue = act_q->index; - } else { /* drop */ - /* signature mode does not support drop action. */ - if (rule->mode == RTE_FDIR_MODE_SIGNATURE) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, - act, "Not supported action."); - return -rte_errno; - } - rule->fdirflags = IXGBE_FDIRCMD_DROP; - } - - /* check if the next not void item is MARK */ - act = next_no_void_action(actions, act); - if ((act->type != RTE_FLOW_ACTION_TYPE_MARK) && - (act->type != RTE_FLOW_ACTION_TYPE_END)) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, - act, "Not supported action."); - return -rte_errno; - } - - rule->soft_id = 0; - - if (act->type == RTE_FLOW_ACTION_TYPE_MARK) { - mark = (const struct rte_flow_action_mark *)act->conf; - rule->soft_id = mark->id; - act = next_no_void_action(actions, act); - } - - /* check if the next not void item is END */ - if (act->type != RTE_FLOW_ACTION_TYPE_END) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, - act, "Not supported action."); - return -rte_errno; - } - - return 0; -} - /* search next no void pattern and skip fuzzy */ static inline const struct rte_flow_item *next_no_fuzzy_pattern( @@ -1393,9 +1288,8 @@ static inline uint8_t signature_match(const struct rte_flow_item pattern[]) */ static int ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, const struct rte_flow_item pattern[], - const struct rte_flow_action actions[], + const struct ci_flow_actions *parsed_actions, struct ixgbe_fdir_rule *rule, struct rte_flow_error *error) { @@ -1416,29 +1310,39 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev, const struct rte_flow_item_vlan *vlan_mask; const struct rte_flow_item_raw *raw_mask; const struct rte_flow_item_raw *raw_spec; + const struct rte_flow_action *fwd_action, *aux_action; + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint8_t j; - struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + fwd_action = parsed_actions->actions[0]; + /* can be NULL */ + aux_action = parsed_actions->actions[1]; - if (!pattern) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM_NUM, - NULL, "NULL pattern."); - return -rte_errno; - } + /* check if this is a signature match */ + if (signature_match(pattern)) + rule->mode = RTE_FDIR_MODE_SIGNATURE; + else + rule->mode = RTE_FDIR_MODE_PERFECT; - if (!actions) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION_NUM, - NULL, "NULL action."); - return -rte_errno; + /* set up action */ + if (fwd_action->type == RTE_FLOW_ACTION_TYPE_QUEUE) { + const struct rte_flow_action_queue *q_act = fwd_action->conf; + rule->queue = q_act->index; + } else { + /* signature mode does not support drop action. */ + if (rule->mode == RTE_FDIR_MODE_SIGNATURE) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, fwd_action, + "Signature mode does not support drop action."); + return -rte_errno; + } + rule->fdirflags = IXGBE_FDIRCMD_DROP; } - if (!attr) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ATTR, - NULL, "NULL attribute."); - return -rte_errno; + /* set up mark action */ + if (aux_action != NULL && aux_action->type == RTE_FLOW_ACTION_TYPE_MARK) { + const struct rte_flow_action_mark *m_act = aux_action->conf; + rule->soft_id = m_act->id; } /** @@ -1470,11 +1374,6 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev, return -rte_errno; } - if (signature_match(pattern)) - rule->mode = RTE_FDIR_MODE_SIGNATURE; - else - rule->mode = RTE_FDIR_MODE_PERFECT; - /*Not supported last point for range*/ if (item->last) { rte_flow_error_set(error, EINVAL, @@ -2063,7 +1962,7 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev, } } - return ixgbe_parse_fdir_act_attr(attr, actions, rule, error); + return 0; } #define NVGRE_PROTOCOL 0x6558 @@ -2106,9 +2005,8 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev, * item->last should be NULL. */ static int -ixgbe_parse_fdir_filter_tunnel(const struct rte_flow_attr *attr, - const struct rte_flow_item pattern[], - const struct rte_flow_action actions[], +ixgbe_parse_fdir_filter_tunnel(const struct rte_flow_item pattern[], + const struct ci_flow_actions *parsed_actions, struct ixgbe_fdir_rule *rule, struct rte_flow_error *error) { @@ -2121,27 +2019,25 @@ ixgbe_parse_fdir_filter_tunnel(const struct rte_flow_attr *attr, const struct rte_flow_item_eth *eth_mask; const struct rte_flow_item_vlan *vlan_spec; const struct rte_flow_item_vlan *vlan_mask; + const struct rte_flow_action *fwd_action, *aux_action; uint32_t j; - if (!pattern) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM_NUM, - NULL, "NULL pattern."); - return -rte_errno; - } + fwd_action = parsed_actions->actions[0]; + /* can be NULL */ + aux_action = parsed_actions->actions[1]; - if (!actions) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION_NUM, - NULL, "NULL action."); - return -rte_errno; + /* set up queue/drop action */ + if (fwd_action->type == RTE_FLOW_ACTION_TYPE_QUEUE) { + const struct rte_flow_action_queue *q_act = fwd_action->conf; + rule->queue = q_act->index; + } else { + rule->fdirflags = IXGBE_FDIRCMD_DROP; } - if (!attr) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ATTR, - NULL, "NULL attribute."); - return -rte_errno; + /* set up mark action */ + if (aux_action != NULL && aux_action->type == RTE_FLOW_ACTION_TYPE_MARK) { + const struct rte_flow_action_mark *mark = aux_action->conf; + rule->soft_id = mark->id; } /** @@ -2552,7 +2448,56 @@ ixgbe_parse_fdir_filter_tunnel(const struct rte_flow_attr *attr, * Do nothing. */ - return ixgbe_parse_fdir_act_attr(attr, actions, rule, error); + return 0; +} + +/* + * Check flow director actions + */ +static int +ixgbe_fdir_actions_check(const struct ci_flow_actions *parsed_actions, + const struct ci_flow_actions_check_param *param __rte_unused, + struct rte_flow_error *error) +{ + const enum rte_flow_action_type fwd_actions[] = { + RTE_FLOW_ACTION_TYPE_QUEUE, + RTE_FLOW_ACTION_TYPE_DROP, + RTE_FLOW_ACTION_TYPE_END + }; + const struct rte_flow_action *action, *drop_action = NULL; + + /* do the generic checks first */ + int ret = ixgbe_flow_actions_check(parsed_actions, param, error); + if (ret) + return ret; + + /* first action must be a forwarding action */ + action = parsed_actions->actions[0]; + if (!ci_flow_action_type_in_list(action->type, fwd_actions)) { + return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, + action, "First action must be QUEUE or DROP"); + } + /* remember if we have a drop action */ + if (action->type == RTE_FLOW_ACTION_TYPE_DROP) { + drop_action = action; + } + + /* second action, if specified, must not be a forwarding action */ + action = parsed_actions->actions[1]; + if (action != NULL && ci_flow_action_type_in_list(action->type, fwd_actions)) { + return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, + action, "Conflicting actions"); + } + /* if we didn't have a drop action before but now we do, remember that */ + if (drop_action == NULL && action != NULL && action->type == RTE_FLOW_ACTION_TYPE_DROP) { + drop_action = action; + } + /* drop must be the only action */ + if (drop_action != NULL && action != NULL) { + return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, + action, "Conflicting actions"); + } + return 0; } static int @@ -2566,24 +2511,45 @@ ixgbe_parse_fdir_filter(struct rte_eth_dev *dev, int ret; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_fdir_conf *fdir_conf = IXGBE_DEV_FDIR_CONF(dev); + struct ci_flow_actions parsed_actions; + struct ci_flow_actions_check_param ap_param = { + .allowed_types = (const enum rte_flow_action_type[]){ + /* queue/mark/drop allowed here */ + RTE_FLOW_ACTION_TYPE_QUEUE, + RTE_FLOW_ACTION_TYPE_DROP, + RTE_FLOW_ACTION_TYPE_MARK, + RTE_FLOW_ACTION_TYPE_END + }, + .driver_ctx = dev, + .check = ixgbe_fdir_actions_check + }; + + if (hw->mac.type != ixgbe_mac_82599EB && + hw->mac.type != ixgbe_mac_X540 && + hw->mac.type != ixgbe_mac_X550 && + hw->mac.type != ixgbe_mac_X550EM_x && + hw->mac.type != ixgbe_mac_X550EM_a && + hw->mac.type != ixgbe_mac_E610) + return -ENOTSUP; + + /* validate attributes */ + ret = ci_flow_check_attr(attr, NULL, error); + if (ret) + return ret; + + /* parse requested actions */ + ret = ci_flow_check_actions(actions, &ap_param, &parsed_actions, error); + if (ret) + return ret; + fdir_conf->drop_queue = IXGBE_FDIR_DROP_QUEUE; - if (hw->mac.type != ixgbe_mac_82599EB && - hw->mac.type != ixgbe_mac_X540 && - hw->mac.type != ixgbe_mac_X550 && - hw->mac.type != ixgbe_mac_X550EM_x && - hw->mac.type != ixgbe_mac_X550EM_a && - hw->mac.type != ixgbe_mac_E610) - return -ENOTSUP; - - ret = ixgbe_parse_fdir_filter_normal(dev, attr, pattern, - actions, rule, error); + ret = ixgbe_parse_fdir_filter_normal(dev, pattern, &parsed_actions, rule, error); if (!ret) goto step_next; - ret = ixgbe_parse_fdir_filter_tunnel(attr, pattern, - actions, rule, error); + ret = ixgbe_parse_fdir_filter_tunnel(pattern, &parsed_actions, rule, error); if (ret) return ret; -- 2.47.3

