net/softnic: support flow validate
[dpdk.git] / drivers / net / softnic / rte_eth_softnic_flow.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Intel Corporation
3  */
4
5 #include "rte_eth_softnic_internals.h"
6 #include "rte_eth_softnic.h"
7
8 int
9 flow_attr_map_set(struct pmd_internals *softnic,
10                 uint32_t group_id,
11                 int ingress,
12                 const char *pipeline_name,
13                 uint32_t table_id)
14 {
15         struct pipeline *pipeline;
16         struct flow_attr_map *map;
17
18         if (group_id >= SOFTNIC_FLOW_MAX_GROUPS ||
19                         pipeline_name == NULL)
20                 return -1;
21
22         pipeline = softnic_pipeline_find(softnic, pipeline_name);
23         if (pipeline == NULL ||
24                         table_id >= pipeline->n_tables)
25                 return -1;
26
27         map = (ingress) ? &softnic->flow.ingress_map[group_id] :
28                 &softnic->flow.egress_map[group_id];
29         strcpy(map->pipeline_name, pipeline_name);
30         map->table_id = table_id;
31         map->valid = 1;
32
33         return 0;
34 }
35
36 struct flow_attr_map *
37 flow_attr_map_get(struct pmd_internals *softnic,
38                 uint32_t group_id,
39                 int ingress)
40 {
41         if (group_id >= SOFTNIC_FLOW_MAX_GROUPS)
42                 return NULL;
43
44         return (ingress) ? &softnic->flow.ingress_map[group_id] :
45                 &softnic->flow.egress_map[group_id];
46 }
47
48 static int
49 flow_pipeline_table_get(struct pmd_internals *softnic,
50                 const struct rte_flow_attr *attr,
51                 const char **pipeline_name,
52                 uint32_t *table_id,
53                 struct rte_flow_error *error)
54 {
55         struct flow_attr_map *map;
56
57         if (attr == NULL)
58                 return rte_flow_error_set(error,
59                                 EINVAL,
60                                 RTE_FLOW_ERROR_TYPE_ATTR,
61                                 NULL,
62                                 "Null attr");
63
64         if (!attr->ingress && !attr->egress)
65                 return rte_flow_error_set(error,
66                                 EINVAL,
67                                 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
68                                 attr,
69                                 "Ingress/egress not specified");
70
71         if (attr->ingress && attr->egress)
72                 return rte_flow_error_set(error,
73                                 EINVAL,
74                                 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
75                                 attr,
76                                 "Setting both ingress and egress is not allowed");
77
78         map = flow_attr_map_get(softnic,
79                         attr->group,
80                         attr->ingress);
81         if (map == NULL ||
82                         map->valid == 0)
83                 return rte_flow_error_set(error,
84                                 EINVAL,
85                                 RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
86                                 attr,
87                                 "Invalid group ID");
88
89         if (pipeline_name)
90                 *pipeline_name = map->pipeline_name;
91
92         if (table_id)
93                 *table_id = map->table_id;
94
95         return 0;
96 }
97
98 static int
99 pmd_flow_validate(struct rte_eth_dev *dev,
100                 const struct rte_flow_attr *attr,
101                 const struct rte_flow_item item[],
102                 const struct rte_flow_action action[],
103                 struct rte_flow_error *error)
104 {
105         struct pmd_internals *softnic = dev->data->dev_private;
106         struct pipeline *pipeline;
107         const char *pipeline_name = NULL;
108         uint32_t table_id = 0;
109         int status;
110
111         /* Check input parameters. */
112         if (attr == NULL)
113                 return rte_flow_error_set(error,
114                                 EINVAL,
115                                 RTE_FLOW_ERROR_TYPE_ATTR,
116                                 NULL, "Null attr");
117
118         if (item == NULL)
119                 return rte_flow_error_set(error,
120                                 EINVAL,
121                                 RTE_FLOW_ERROR_TYPE_ITEM,
122                                 NULL,
123                                 "Null item");
124
125         if (action == NULL)
126                 return rte_flow_error_set(error,
127                                 EINVAL,
128                                 RTE_FLOW_ERROR_TYPE_ACTION,
129                                 NULL,
130                                 "Null action");
131
132         /* Identify the pipeline table to add this flow to. */
133         status = flow_pipeline_table_get(softnic, attr, &pipeline_name,
134                                         &table_id, error);
135         if (status)
136                 return status;
137
138         pipeline = softnic_pipeline_find(softnic, pipeline_name);
139         if (pipeline == NULL)
140                 return rte_flow_error_set(error,
141                                 EINVAL,
142                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
143                                 NULL,
144                                 "Invalid pipeline name");
145
146         if (table_id >= pipeline->n_tables)
147                 return rte_flow_error_set(error,
148                                 EINVAL,
149                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
150                                 NULL,
151                                 "Invalid pipeline table ID");
152
153         return 0;
154 }
155
156 const struct rte_flow_ops pmd_flow_ops = {
157         .validate = pmd_flow_validate,
158 };