net/cnxk: get flow operations
[dpdk.git] / drivers / net / cnxk / cnxk_rte_flow.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 #include <cnxk_rte_flow.h>
5
6 const struct cnxk_rte_flow_term_info term[] = {
7         [RTE_FLOW_ITEM_TYPE_ETH] = {ROC_NPC_ITEM_TYPE_ETH,
8                                     sizeof(struct rte_flow_item_eth)},
9         [RTE_FLOW_ITEM_TYPE_VLAN] = {ROC_NPC_ITEM_TYPE_VLAN,
10                                      sizeof(struct rte_flow_item_vlan)},
11         [RTE_FLOW_ITEM_TYPE_E_TAG] = {ROC_NPC_ITEM_TYPE_E_TAG,
12                                       sizeof(struct rte_flow_item_e_tag)},
13         [RTE_FLOW_ITEM_TYPE_IPV4] = {ROC_NPC_ITEM_TYPE_IPV4,
14                                      sizeof(struct rte_flow_item_ipv4)},
15         [RTE_FLOW_ITEM_TYPE_IPV6] = {ROC_NPC_ITEM_TYPE_IPV6,
16                                      sizeof(struct rte_flow_item_ipv6)},
17         [RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4] = {
18                 ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4,
19                 sizeof(struct rte_flow_item_arp_eth_ipv4)},
20         [RTE_FLOW_ITEM_TYPE_MPLS] = {ROC_NPC_ITEM_TYPE_MPLS,
21                                      sizeof(struct rte_flow_item_mpls)},
22         [RTE_FLOW_ITEM_TYPE_ICMP] = {ROC_NPC_ITEM_TYPE_ICMP,
23                                      sizeof(struct rte_flow_item_icmp)},
24         [RTE_FLOW_ITEM_TYPE_UDP] = {ROC_NPC_ITEM_TYPE_UDP,
25                                     sizeof(struct rte_flow_item_udp)},
26         [RTE_FLOW_ITEM_TYPE_TCP] = {ROC_NPC_ITEM_TYPE_TCP,
27                                     sizeof(struct rte_flow_item_tcp)},
28         [RTE_FLOW_ITEM_TYPE_SCTP] = {ROC_NPC_ITEM_TYPE_SCTP,
29                                      sizeof(struct rte_flow_item_sctp)},
30         [RTE_FLOW_ITEM_TYPE_ESP] = {ROC_NPC_ITEM_TYPE_ESP,
31                                     sizeof(struct rte_flow_item_esp)},
32         [RTE_FLOW_ITEM_TYPE_GRE] = {ROC_NPC_ITEM_TYPE_GRE,
33                                     sizeof(struct rte_flow_item_gre)},
34         [RTE_FLOW_ITEM_TYPE_NVGRE] = {ROC_NPC_ITEM_TYPE_NVGRE,
35                                       sizeof(struct rte_flow_item_nvgre)},
36         [RTE_FLOW_ITEM_TYPE_VXLAN] = {ROC_NPC_ITEM_TYPE_VXLAN,
37                                       sizeof(struct rte_flow_item_vxlan)},
38         [RTE_FLOW_ITEM_TYPE_GTPC] = {ROC_NPC_ITEM_TYPE_GTPC,
39                                      sizeof(struct rte_flow_item_gtp)},
40         [RTE_FLOW_ITEM_TYPE_GTPU] = {ROC_NPC_ITEM_TYPE_GTPU,
41                                      sizeof(struct rte_flow_item_gtp)},
42         [RTE_FLOW_ITEM_TYPE_GENEVE] = {ROC_NPC_ITEM_TYPE_GENEVE,
43                                        sizeof(struct rte_flow_item_geneve)},
44         [RTE_FLOW_ITEM_TYPE_VXLAN_GPE] = {
45                         ROC_NPC_ITEM_TYPE_VXLAN_GPE,
46                         sizeof(struct rte_flow_item_vxlan_gpe)},
47         [RTE_FLOW_ITEM_TYPE_IPV6_EXT] = {ROC_NPC_ITEM_TYPE_IPV6_EXT,
48                                          sizeof(struct rte_flow_item_ipv6_ext)},
49         [RTE_FLOW_ITEM_TYPE_VOID] = {ROC_NPC_ITEM_TYPE_VOID, 0},
50         [RTE_FLOW_ITEM_TYPE_ANY] = {ROC_NPC_ITEM_TYPE_ANY, 0},
51         [RTE_FLOW_ITEM_TYPE_GRE_KEY] = {ROC_NPC_ITEM_TYPE_GRE_KEY,
52                                         sizeof(uint32_t)},
53         [RTE_FLOW_ITEM_TYPE_HIGIG2] = {
54                 ROC_NPC_ITEM_TYPE_HIGIG2,
55                 sizeof(struct rte_flow_item_higig2_hdr)}
56 };
57
58 static int
59 cnxk_map_actions(struct rte_eth_dev *eth_dev,
60                  const struct rte_flow_action actions[],
61                  struct roc_npc_action in_actions[])
62 {
63         const struct rte_flow_action_count *act_count;
64         const struct rte_flow_action_queue *act_q;
65         int rq;
66         int i = 0;
67
68         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
69                 switch (actions->type) {
70                 case RTE_FLOW_ACTION_TYPE_VOID:
71                         in_actions[i].type = ROC_NPC_ACTION_TYPE_VOID;
72                         break;
73
74                 case RTE_FLOW_ACTION_TYPE_MARK:
75                         in_actions[i].type = ROC_NPC_ACTION_TYPE_MARK;
76                         in_actions[i].conf = actions->conf;
77                         break;
78
79                 case RTE_FLOW_ACTION_TYPE_FLAG:
80                         in_actions[i].type = ROC_NPC_ACTION_TYPE_FLAG;
81                         break;
82
83                 case RTE_FLOW_ACTION_TYPE_COUNT:
84                         act_count = (const struct rte_flow_action_count *)
85                                             actions->conf;
86
87                         if (act_count->shared == 1) {
88                                 plt_npc_dbg("Shared counter is not supported");
89                                 goto err_exit;
90                         }
91                         in_actions[i].type = ROC_NPC_ACTION_TYPE_COUNT;
92                         break;
93
94                 case RTE_FLOW_ACTION_TYPE_DROP:
95                         in_actions[i].type = ROC_NPC_ACTION_TYPE_DROP;
96                         break;
97
98                 case RTE_FLOW_ACTION_TYPE_PF:
99                         in_actions[i].type = ROC_NPC_ACTION_TYPE_PF;
100                         break;
101
102                 case RTE_FLOW_ACTION_TYPE_VF:
103                         in_actions[i].type = ROC_NPC_ACTION_TYPE_VF;
104                         in_actions[i].conf = actions->conf;
105                         break;
106
107                 case RTE_FLOW_ACTION_TYPE_QUEUE:
108                         act_q = (const struct rte_flow_action_queue *)
109                                         actions->conf;
110                         rq = act_q->index;
111                         if (rq >= eth_dev->data->nb_rx_queues) {
112                                 plt_npc_dbg("Invalid queue index");
113                                 goto err_exit;
114                         }
115                         in_actions[i].type = ROC_NPC_ACTION_TYPE_QUEUE;
116                         in_actions[i].conf = actions->conf;
117                         break;
118
119                 case RTE_FLOW_ACTION_TYPE_RSS:
120                         in_actions[i].type = ROC_NPC_ACTION_TYPE_RSS;
121                         break;
122
123                 case RTE_FLOW_ACTION_TYPE_SECURITY:
124                         in_actions[i].type = ROC_NPC_ACTION_TYPE_SEC;
125                         break;
126                 default:
127                         plt_npc_dbg("Action is not supported = %d",
128                                     actions->type);
129                         goto err_exit;
130                 }
131                 i++;
132         }
133         in_actions[i].type = ROC_NPC_ACTION_TYPE_END;
134         return 0;
135
136 err_exit:
137         return -EINVAL;
138 }
139
140 static int
141 cnxk_map_flow_data(struct rte_eth_dev *eth_dev,
142                    const struct rte_flow_attr *attr,
143                    const struct rte_flow_item pattern[],
144                    const struct rte_flow_action actions[],
145                    struct roc_npc_attr *in_attr,
146                    struct roc_npc_item_info in_pattern[],
147                    struct roc_npc_action in_actions[])
148 {
149         int i = 0;
150
151         in_attr->priority = attr->priority;
152         in_attr->ingress = attr->ingress;
153         in_attr->egress = attr->egress;
154
155         while (pattern->type != RTE_FLOW_ITEM_TYPE_END) {
156                 in_pattern[i].spec = pattern->spec;
157                 in_pattern[i].last = pattern->last;
158                 in_pattern[i].mask = pattern->mask;
159                 in_pattern[i].type = term[pattern->type].item_type;
160                 in_pattern[i].size = term[pattern->type].item_size;
161                 pattern++;
162                 i++;
163         }
164         in_pattern[i].type = ROC_NPC_ITEM_TYPE_END;
165
166         return cnxk_map_actions(eth_dev, actions, in_actions);
167 }
168
169 static int
170 cnxk_flow_validate(struct rte_eth_dev *eth_dev,
171                    const struct rte_flow_attr *attr,
172                    const struct rte_flow_item pattern[],
173                    const struct rte_flow_action actions[],
174                    struct rte_flow_error *error)
175 {
176         struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
177         struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
178         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
179         struct roc_npc *npc = &dev->npc;
180         struct roc_npc_attr in_attr;
181         struct roc_npc_flow flow;
182         int rc;
183
184         memset(&flow, 0, sizeof(flow));
185
186         rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr,
187                                 in_pattern, in_actions);
188         if (rc) {
189                 rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM,
190                                    NULL, "Failed to map flow data");
191                 return rc;
192         }
193
194         return roc_npc_flow_parse(npc, &in_attr, in_pattern, in_actions, &flow);
195 }
196
197 struct roc_npc_flow *
198 cnxk_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
199                  const struct rte_flow_item pattern[],
200                  const struct rte_flow_action actions[],
201                  struct rte_flow_error *error)
202 {
203         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
204         struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
205         struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
206         struct roc_npc *npc = &dev->npc;
207         struct roc_npc_attr in_attr;
208         struct roc_npc_flow *flow;
209         int errcode;
210         int rc;
211
212         rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr,
213                                 in_pattern, in_actions);
214         if (rc) {
215                 rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM,
216                                    NULL, "Failed to map flow data");
217                 return NULL;
218         }
219
220         flow = roc_npc_flow_create(npc, &in_attr, in_pattern, in_actions,
221                                    &errcode);
222         if (errcode != 0) {
223                 rte_flow_error_set(error, errcode, errcode, NULL,
224                                    roc_error_msg_get(errcode));
225                 return NULL;
226         }
227
228         return flow;
229 }
230
231 int
232 cnxk_flow_destroy(struct rte_eth_dev *eth_dev, struct roc_npc_flow *flow,
233                   struct rte_flow_error *error)
234 {
235         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
236         struct roc_npc *npc = &dev->npc;
237         int rc;
238
239         rc = roc_npc_flow_destroy(npc, flow);
240         if (rc)
241                 rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
242                                    NULL, "Flow Destroy failed");
243         return rc;
244 }
245
246 static int
247 cnxk_flow_flush(struct rte_eth_dev *eth_dev, struct rte_flow_error *error)
248 {
249         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
250         struct roc_npc *npc = &dev->npc;
251         int rc;
252
253         rc = roc_npc_mcam_free_all_resources(npc);
254         if (rc) {
255                 rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
256                                    NULL, "Failed to flush filter");
257                 return -rte_errno;
258         }
259
260         return 0;
261 }
262
263 static int
264 cnxk_flow_query(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
265                 const struct rte_flow_action *action, void *data,
266                 struct rte_flow_error *error)
267 {
268         struct roc_npc_flow *in_flow = (struct roc_npc_flow *)flow;
269         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
270         struct roc_npc *npc = &dev->npc;
271         struct rte_flow_query_count *query = data;
272         const char *errmsg = NULL;
273         int errcode = ENOTSUP;
274         int rc;
275
276         if (action->type != RTE_FLOW_ACTION_TYPE_COUNT) {
277                 errmsg = "Only COUNT is supported in query";
278                 goto err_exit;
279         }
280
281         if (in_flow->ctr_id == NPC_COUNTER_NONE) {
282                 errmsg = "Counter is not available";
283                 goto err_exit;
284         }
285
286         rc = roc_npc_mcam_read_counter(npc, in_flow->ctr_id, &query->hits);
287         if (rc != 0) {
288                 errcode = EIO;
289                 errmsg = "Error reading flow counter";
290                 goto err_exit;
291         }
292         query->hits_set = 1;
293         query->bytes_set = 0;
294
295         if (query->reset)
296                 rc = roc_npc_mcam_clear_counter(npc, in_flow->ctr_id);
297         if (rc != 0) {
298                 errcode = EIO;
299                 errmsg = "Error clearing flow counter";
300                 goto err_exit;
301         }
302
303         return 0;
304
305 err_exit:
306         rte_flow_error_set(error, errcode, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
307                            NULL, errmsg);
308         return -rte_errno;
309 }
310
311 static int
312 cnxk_flow_isolate(struct rte_eth_dev *eth_dev __rte_unused,
313                   int enable __rte_unused, struct rte_flow_error *error)
314 {
315         /* If we support, we need to un-install the default mcam
316          * entry for this port.
317          */
318
319         rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
320                            NULL, "Flow isolation not supported");
321
322         return -rte_errno;
323 }
324
325 static int
326 cnxk_flow_dev_dump(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
327                    FILE *file, struct rte_flow_error *error)
328 {
329         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
330         struct roc_npc *npc = &dev->npc;
331
332         if (file == NULL) {
333                 rte_flow_error_set(error, EINVAL,
334                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
335                                    "Invalid file");
336                 return -rte_errno;
337         }
338
339         if (flow != NULL) {
340                 rte_flow_error_set(error, EINVAL,
341                                    RTE_FLOW_ERROR_TYPE_HANDLE,
342                                    NULL,
343                                    "Invalid argument");
344                 return -EINVAL;
345         }
346
347         roc_npc_flow_dump(file, npc);
348
349         return 0;
350 }
351
352 struct rte_flow_ops cnxk_flow_ops = {
353         .validate = cnxk_flow_validate,
354         .flush = cnxk_flow_flush,
355         .query = cnxk_flow_query,
356         .isolate = cnxk_flow_isolate,
357         .dev_dump = cnxk_flow_dev_dump,
358 };