1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2020 Marvell.
5 #include "cn10k_flow.h"
6 #include "cn10k_ethdev.h"
10 cn10k_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t mtr_id)
12 return nix_mtr_connect(eth_dev, mtr_id);
16 cn10k_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id)
18 struct rte_mtr_error mtr_error;
20 return nix_mtr_destroy(eth_dev, mtr_id, &mtr_error);
24 cn10k_mtr_configure(struct rte_eth_dev *eth_dev,
25 const struct rte_flow_action actions[])
27 uint32_t mtr_id = 0xffff, prev_mtr_id = 0xffff, next_mtr_id = 0xffff;
28 const struct rte_flow_action_meter *mtr_conf;
29 const struct rte_flow_action_queue *q_conf;
30 const struct rte_flow_action_rss *rss_conf;
31 struct cnxk_mtr_policy_node *policy;
32 bool is_mtr_act = false;
36 for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
37 if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER) {
38 mtr_conf = (const struct rte_flow_action_meter
40 mtr_id = mtr_conf->mtr_id;
43 if (actions[i].type == RTE_FLOW_ACTION_TYPE_QUEUE) {
44 q_conf = (const struct rte_flow_action_queue
47 nix_mtr_rq_update(eth_dev, mtr_id, 1,
50 if (actions[i].type == RTE_FLOW_ACTION_TYPE_RSS) {
51 rss_conf = (const struct rte_flow_action_rss
54 nix_mtr_rq_update(eth_dev, mtr_id,
65 while (next_mtr_id != 0xffff) {
66 rc = nix_mtr_validate(eth_dev, next_mtr_id);
70 rc = nix_mtr_policy_act_get(eth_dev, next_mtr_id, &policy);
74 rc = nix_mtr_color_action_validate(eth_dev, mtr_id,
75 &prev_mtr_id, &next_mtr_id,
81 return nix_mtr_configure(eth_dev, mtr_id);
85 cn10k_rss_action_validate(struct rte_eth_dev *eth_dev,
86 const struct rte_flow_attr *attr,
87 const struct rte_flow_action *act)
89 const struct rte_flow_action_rss *rss;
94 rss = (const struct rte_flow_action_rss *)act->conf;
97 plt_err("No support of RSS in egress");
101 if (eth_dev->data->dev_conf.rxmode.mq_mode != RTE_ETH_MQ_RX_RSS) {
102 plt_err("multi-queue mode is disabled");
106 if (!rss || !rss->queue_num) {
107 plt_err("no valid queues");
111 if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
112 plt_err("non-default RSS hash functions are not supported");
116 if (rss->key_len && rss->key_len > ROC_NIX_RSS_KEY_LEN) {
117 plt_err("RSS hash key too large");
125 cn10k_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
126 const struct rte_flow_item pattern[],
127 const struct rte_flow_action actions[],
128 struct rte_flow_error *error)
130 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
131 const struct rte_flow_action *action_rss = NULL;
132 const struct rte_flow_action_meter *mtr = NULL;
133 const struct rte_flow_action *act_q = NULL;
134 struct roc_npc *npc = &dev->npc;
135 struct roc_npc_flow *flow;
136 int vtag_actions = 0;
137 uint32_t req_act = 0;
140 for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
141 if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER)
142 req_act |= ROC_NPC_ACTION_TYPE_METER;
144 if (actions[i].type == RTE_FLOW_ACTION_TYPE_QUEUE) {
145 req_act |= ROC_NPC_ACTION_TYPE_QUEUE;
148 if (actions[i].type == RTE_FLOW_ACTION_TYPE_RSS) {
149 req_act |= ROC_NPC_ACTION_TYPE_RSS;
150 action_rss = &actions[i];
154 if (req_act & ROC_NPC_ACTION_TYPE_METER) {
155 if ((req_act & ROC_NPC_ACTION_TYPE_RSS) &&
156 ((req_act & ROC_NPC_ACTION_TYPE_QUEUE))) {
159 if (req_act & ROC_NPC_ACTION_TYPE_RSS) {
160 rc = cn10k_rss_action_validate(eth_dev, attr,
164 } else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) {
165 const struct rte_flow_action_queue *act_queue;
166 act_queue = (const struct rte_flow_action_queue *)
168 if (act_queue->index > eth_dev->data->nb_rx_queues)
174 for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
175 if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER) {
176 mtr = (const struct rte_flow_action_meter *)actions[i]
178 rc = cn10k_mtr_configure(eth_dev, actions);
180 rte_flow_error_set(error, rc,
181 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
182 "Failed to configure mtr ");
189 flow = cnxk_flow_create(eth_dev, attr, pattern, actions, error);
192 nix_mtr_chain_reset(eth_dev, mtr->mtr_id);
197 cn10k_mtr_connect(eth_dev, mtr->mtr_id);
200 vtag_actions = roc_npc_vtag_actions_get(npc);
203 dev->rx_offload_flags |= NIX_RX_OFFLOAD_VLAN_STRIP_F;
204 cn10k_eth_set_rx_function(eth_dev);
207 return (struct rte_flow *)flow;
211 cn10k_flow_destroy(struct rte_eth_dev *eth_dev, struct rte_flow *rte_flow,
212 struct rte_flow_error *error)
214 struct roc_npc_flow *flow = (struct roc_npc_flow *)rte_flow;
215 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
216 struct roc_npc *npc = &dev->npc;
217 int vtag_actions = 0;
221 vtag_actions = roc_npc_vtag_actions_get(npc);
223 if (flow->nix_intf == ROC_NPC_INTF_RX) {
224 vtag_actions = roc_npc_vtag_actions_sub_return(npc, 1);
225 if (vtag_actions == 0) {
226 dev->rx_offload_flags &=
227 ~NIX_RX_OFFLOAD_VLAN_STRIP_F;
228 cn10k_eth_set_rx_function(eth_dev);
233 mtr_id = flow->mtr_id;
234 rc = cnxk_flow_destroy(eth_dev, flow, error);
235 if (!rc && mtr_id != ROC_NIX_MTR_ID_INVALID) {
236 rc = cn10k_mtr_destroy(eth_dev, mtr_id);
238 rte_flow_error_set(error, ENXIO,
239 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
240 "Meter attached to this flow does not exist");