net/i40e: add flow validate function
[dpdk.git] / drivers / net / i40e / i40e_flow.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) 2016 Intel Corporation. All rights reserved.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in
14  *       the documentation and/or other materials provided with the
15  *       distribution.
16  *     * Neither the name of Intel Corporation nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <sys/queue.h>
34 #include <stdio.h>
35 #include <errno.h>
36 #include <stdint.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <stdarg.h>
40
41 #include <rte_ether.h>
42 #include <rte_ethdev.h>
43 #include <rte_log.h>
44 #include <rte_memzone.h>
45 #include <rte_malloc.h>
46 #include <rte_eth_ctrl.h>
47 #include <rte_tailq.h>
48 #include <rte_flow_driver.h>
49
50 #include "i40e_logs.h"
51 #include "base/i40e_type.h"
52 #include "base/i40e_prototype.h"
53 #include "i40e_ethdev.h"
54
55 static int i40e_flow_validate(struct rte_eth_dev *dev,
56                               const struct rte_flow_attr *attr,
57                               const struct rte_flow_item pattern[],
58                               const struct rte_flow_action actions[],
59                               struct rte_flow_error *error);
60 static int
61 i40e_flow_parse_ethertype_pattern(struct rte_eth_dev *dev,
62                                   const struct rte_flow_item *pattern,
63                                   struct rte_flow_error *error,
64                                   struct rte_eth_ethertype_filter *filter);
65 static int i40e_flow_parse_ethertype_action(struct rte_eth_dev *dev,
66                                     const struct rte_flow_action *actions,
67                                     struct rte_flow_error *error,
68                                     struct rte_eth_ethertype_filter *filter);
69 static int i40e_flow_parse_attr(const struct rte_flow_attr *attr,
70                                 struct rte_flow_error *error);
71 static int i40e_flow_parse_ethertype_filter(struct rte_eth_dev *dev,
72                                     const struct rte_flow_attr *attr,
73                                     const struct rte_flow_item pattern[],
74                                     const struct rte_flow_action actions[],
75                                     struct rte_flow_error *error,
76                                     union i40e_filter_t *filter);
77
78 const struct rte_flow_ops i40e_flow_ops = {
79         .validate = i40e_flow_validate,
80 };
81
82 union i40e_filter_t cons_filter;
83
84 /* Pattern matched ethertype filter */
85 static enum rte_flow_item_type pattern_ethertype[] = {
86         RTE_FLOW_ITEM_TYPE_ETH,
87         RTE_FLOW_ITEM_TYPE_END,
88 };
89
90 static struct i40e_valid_pattern i40e_supported_patterns[] = {
91         /* Ethertype */
92         { pattern_ethertype, i40e_flow_parse_ethertype_filter },
93 };
94
95 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
96         do {                                                            \
97                 act = actions + index;                                  \
98                 while (act->type == RTE_FLOW_ACTION_TYPE_VOID) {        \
99                         index++;                                        \
100                         act = actions + index;                          \
101                 }                                                       \
102         } while (0)
103
104 /* Find the first VOID or non-VOID item pointer */
105 static const struct rte_flow_item *
106 i40e_find_first_item(const struct rte_flow_item *item, bool is_void)
107 {
108         bool is_find;
109
110         while (item->type != RTE_FLOW_ITEM_TYPE_END) {
111                 if (is_void)
112                         is_find = item->type == RTE_FLOW_ITEM_TYPE_VOID;
113                 else
114                         is_find = item->type != RTE_FLOW_ITEM_TYPE_VOID;
115                 if (is_find)
116                         break;
117                 item++;
118         }
119         return item;
120 }
121
122 /* Skip all VOID items of the pattern */
123 static void
124 i40e_pattern_skip_void_item(struct rte_flow_item *items,
125                             const struct rte_flow_item *pattern)
126 {
127         uint32_t cpy_count = 0;
128         const struct rte_flow_item *pb = pattern, *pe = pattern;
129
130         for (;;) {
131                 /* Find a non-void item first */
132                 pb = i40e_find_first_item(pb, false);
133                 if (pb->type == RTE_FLOW_ITEM_TYPE_END) {
134                         pe = pb;
135                         break;
136                 }
137
138                 /* Find a void item */
139                 pe = i40e_find_first_item(pb + 1, true);
140
141                 cpy_count = pe - pb;
142                 rte_memcpy(items, pb, sizeof(struct rte_flow_item) * cpy_count);
143
144                 items += cpy_count;
145
146                 if (pe->type == RTE_FLOW_ITEM_TYPE_END) {
147                         pb = pe;
148                         break;
149                 }
150
151                 pb = pe + 1;
152         }
153         /* Copy the END item. */
154         rte_memcpy(items, pe, sizeof(struct rte_flow_item));
155 }
156
157 /* Check if the pattern matches a supported item type array */
158 static bool
159 i40e_match_pattern(enum rte_flow_item_type *item_array,
160                    struct rte_flow_item *pattern)
161 {
162         struct rte_flow_item *item = pattern;
163
164         while ((*item_array == item->type) &&
165                (*item_array != RTE_FLOW_ITEM_TYPE_END)) {
166                 item_array++;
167                 item++;
168         }
169
170         return (*item_array == RTE_FLOW_ITEM_TYPE_END &&
171                 item->type == RTE_FLOW_ITEM_TYPE_END);
172 }
173
174 /* Find if there's parse filter function matched */
175 static parse_filter_t
176 i40e_find_parse_filter_func(struct rte_flow_item *pattern)
177 {
178         parse_filter_t parse_filter = NULL;
179         uint8_t i = 0;
180
181         for (; i < RTE_DIM(i40e_supported_patterns); i++) {
182                 if (i40e_match_pattern(i40e_supported_patterns[i].items,
183                                         pattern)) {
184                         parse_filter = i40e_supported_patterns[i].parse_filter;
185                         break;
186                 }
187         }
188
189         return parse_filter;
190 }
191
192 /* Parse attributes */
193 static int
194 i40e_flow_parse_attr(const struct rte_flow_attr *attr,
195                      struct rte_flow_error *error)
196 {
197         /* Must be input direction */
198         if (!attr->ingress) {
199                 rte_flow_error_set(error, EINVAL,
200                                    RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
201                                    attr, "Only support ingress.");
202                 return -rte_errno;
203         }
204
205         /* Not supported */
206         if (attr->egress) {
207                 rte_flow_error_set(error, EINVAL,
208                                    RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
209                                    attr, "Not support egress.");
210                 return -rte_errno;
211         }
212
213         /* Not supported */
214         if (attr->priority) {
215                 rte_flow_error_set(error, EINVAL,
216                                    RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
217                                    attr, "Not support priority.");
218                 return -rte_errno;
219         }
220
221         /* Not supported */
222         if (attr->group) {
223                 rte_flow_error_set(error, EINVAL,
224                                    RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
225                                    attr, "Not support group.");
226                 return -rte_errno;
227         }
228
229         return 0;
230 }
231
232 static uint16_t
233 i40e_get_outer_vlan(struct rte_eth_dev *dev)
234 {
235         struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
236         int qinq = dev->data->dev_conf.rxmode.hw_vlan_extend;
237         uint64_t reg_r = 0;
238         uint16_t reg_id;
239         uint16_t tpid;
240
241         if (qinq)
242                 reg_id = 2;
243         else
244                 reg_id = 3;
245
246         i40e_aq_debug_read_register(hw, I40E_GL_SWT_L2TAGCTRL(reg_id),
247                                     &reg_r, NULL);
248
249         tpid = (reg_r >> I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_SHIFT) & 0xFFFF;
250
251         return tpid;
252 }
253
254 /* 1. Last in item should be NULL as range is not supported.
255  * 2. Supported filter types: MAC_ETHTYPE and ETHTYPE.
256  * 3. SRC mac_addr mask should be 00:00:00:00:00:00.
257  * 4. DST mac_addr mask should be 00:00:00:00:00:00 or
258  *    FF:FF:FF:FF:FF:FF
259  * 5. Ether_type mask should be 0xFFFF.
260  */
261 static int
262 i40e_flow_parse_ethertype_pattern(struct rte_eth_dev *dev,
263                                   const struct rte_flow_item *pattern,
264                                   struct rte_flow_error *error,
265                                   struct rte_eth_ethertype_filter *filter)
266 {
267         const struct rte_flow_item *item = pattern;
268         const struct rte_flow_item_eth *eth_spec;
269         const struct rte_flow_item_eth *eth_mask;
270         enum rte_flow_item_type item_type;
271         uint16_t outer_tpid;
272
273         outer_tpid = i40e_get_outer_vlan(dev);
274
275         for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
276                 if (item->last) {
277                         rte_flow_error_set(error, EINVAL,
278                                            RTE_FLOW_ERROR_TYPE_ITEM,
279                                            item,
280                                            "Not support range");
281                         return -rte_errno;
282                 }
283                 item_type = item->type;
284                 switch (item_type) {
285                 case RTE_FLOW_ITEM_TYPE_ETH:
286                         eth_spec = (const struct rte_flow_item_eth *)item->spec;
287                         eth_mask = (const struct rte_flow_item_eth *)item->mask;
288                         /* Get the MAC info. */
289                         if (!eth_spec || !eth_mask) {
290                                 rte_flow_error_set(error, EINVAL,
291                                                    RTE_FLOW_ERROR_TYPE_ITEM,
292                                                    item,
293                                                    "NULL ETH spec/mask");
294                                 return -rte_errno;
295                         }
296
297                         /* Mask bits of source MAC address must be full of 0.
298                          * Mask bits of destination MAC address must be full
299                          * of 1 or full of 0.
300                          */
301                         if (!is_zero_ether_addr(&eth_mask->src) ||
302                             (!is_zero_ether_addr(&eth_mask->dst) &&
303                              !is_broadcast_ether_addr(&eth_mask->dst))) {
304                                 rte_flow_error_set(error, EINVAL,
305                                                    RTE_FLOW_ERROR_TYPE_ITEM,
306                                                    item,
307                                                    "Invalid MAC_addr mask");
308                                 return -rte_errno;
309                         }
310
311                         if ((eth_mask->type & UINT16_MAX) != UINT16_MAX) {
312                                 rte_flow_error_set(error, EINVAL,
313                                                    RTE_FLOW_ERROR_TYPE_ITEM,
314                                                    item,
315                                                    "Invalid ethertype mask");
316                                 return -rte_errno;
317                         }
318
319                         /* If mask bits of destination MAC address
320                          * are full of 1, set RTE_ETHTYPE_FLAGS_MAC.
321                          */
322                         if (is_broadcast_ether_addr(&eth_mask->dst)) {
323                                 filter->mac_addr = eth_spec->dst;
324                                 filter->flags |= RTE_ETHTYPE_FLAGS_MAC;
325                         } else {
326                                 filter->flags &= ~RTE_ETHTYPE_FLAGS_MAC;
327                         }
328                         filter->ether_type = rte_be_to_cpu_16(eth_spec->type);
329
330                         if (filter->ether_type == ETHER_TYPE_IPv4 ||
331                             filter->ether_type == ETHER_TYPE_IPv6 ||
332                             filter->ether_type == outer_tpid) {
333                                 rte_flow_error_set(error, EINVAL,
334                                                    RTE_FLOW_ERROR_TYPE_ITEM,
335                                                    item,
336                                                    "Unsupported ether_type in"
337                                                    " control packet filter.");
338                                 return -rte_errno;
339                         }
340                         break;
341                 default:
342                         break;
343                 }
344         }
345
346         return 0;
347 }
348
349 /* Ethertype action only supports QUEUE or DROP. */
350 static int
351 i40e_flow_parse_ethertype_action(struct rte_eth_dev *dev,
352                                  const struct rte_flow_action *actions,
353                                  struct rte_flow_error *error,
354                                  struct rte_eth_ethertype_filter *filter)
355 {
356         struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
357         const struct rte_flow_action *act;
358         const struct rte_flow_action_queue *act_q;
359         uint32_t index = 0;
360
361         /* Check if the first non-void action is QUEUE or DROP. */
362         NEXT_ITEM_OF_ACTION(act, actions, index);
363         if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE &&
364             act->type != RTE_FLOW_ACTION_TYPE_DROP) {
365                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
366                                    act, "Not supported action.");
367                 return -rte_errno;
368         }
369
370         if (act->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
371                 act_q = (const struct rte_flow_action_queue *)act->conf;
372                 filter->queue = act_q->index;
373                 if (filter->queue >= pf->dev_data->nb_rx_queues) {
374                         rte_flow_error_set(error, EINVAL,
375                                            RTE_FLOW_ERROR_TYPE_ACTION,
376                                            act, "Invalid queue ID for"
377                                            " ethertype_filter.");
378                         return -rte_errno;
379                 }
380         } else {
381                 filter->flags |= RTE_ETHTYPE_FLAGS_DROP;
382         }
383
384         /* Check if the next non-void item is END */
385         index++;
386         NEXT_ITEM_OF_ACTION(act, actions, index);
387         if (act->type != RTE_FLOW_ACTION_TYPE_END) {
388                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
389                                    act, "Not supported action.");
390                 return -rte_errno;
391         }
392
393         return 0;
394 }
395
396 static int
397 i40e_flow_parse_ethertype_filter(struct rte_eth_dev *dev,
398                                  const struct rte_flow_attr *attr,
399                                  const struct rte_flow_item pattern[],
400                                  const struct rte_flow_action actions[],
401                                  struct rte_flow_error *error,
402                                  union i40e_filter_t *filter)
403 {
404         struct rte_eth_ethertype_filter *ethertype_filter =
405                 &filter->ethertype_filter;
406         int ret;
407
408         ret = i40e_flow_parse_ethertype_pattern(dev, pattern, error,
409                                                 ethertype_filter);
410         if (ret)
411                 return ret;
412
413         ret = i40e_flow_parse_ethertype_action(dev, actions, error,
414                                                ethertype_filter);
415         if (ret)
416                 return ret;
417
418         ret = i40e_flow_parse_attr(attr, error);
419         if (ret)
420                 return ret;
421
422         return ret;
423 }
424
425 static int
426 i40e_flow_validate(struct rte_eth_dev *dev,
427                    const struct rte_flow_attr *attr,
428                    const struct rte_flow_item pattern[],
429                    const struct rte_flow_action actions[],
430                    struct rte_flow_error *error)
431 {
432         struct rte_flow_item *items; /* internal pattern w/o VOID items */
433         parse_filter_t parse_filter;
434         uint32_t item_num = 0; /* non-void item number of pattern*/
435         uint32_t i = 0;
436         int ret;
437
438         if (!pattern) {
439                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
440                                    NULL, "NULL pattern.");
441                 return -rte_errno;
442         }
443
444         if (!actions) {
445                 rte_flow_error_set(error, EINVAL,
446                                    RTE_FLOW_ERROR_TYPE_ACTION_NUM,
447                                    NULL, "NULL action.");
448                 return -rte_errno;
449         }
450
451         if (!attr) {
452                 rte_flow_error_set(error, EINVAL,
453                                    RTE_FLOW_ERROR_TYPE_ATTR,
454                                    NULL, "NULL attribute.");
455                 return -rte_errno;
456         }
457
458         memset(&cons_filter, 0, sizeof(cons_filter));
459
460         /* Get the non-void item number of pattern */
461         while ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_END) {
462                 if ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_VOID)
463                         item_num++;
464                 i++;
465         }
466         item_num++;
467
468         items = rte_zmalloc("i40e_pattern",
469                             item_num * sizeof(struct rte_flow_item), 0);
470         if (!items) {
471                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
472                                    NULL, "No memory for PMD internal items.");
473                 return -ENOMEM;
474         }
475
476         i40e_pattern_skip_void_item(items, pattern);
477
478         /* Find if there's matched parse filter function */
479         parse_filter = i40e_find_parse_filter_func(items);
480         if (!parse_filter) {
481                 rte_flow_error_set(error, EINVAL,
482                                    RTE_FLOW_ERROR_TYPE_ITEM,
483                                    pattern, "Unsupported pattern");
484                 return -rte_errno;
485         }
486
487         ret = parse_filter(dev, attr, items, actions, error, &cons_filter);
488
489         rte_free(items);
490
491         return ret;
492 }