Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2017 6WIND S.A.
3 : : * Copyright 2017 Mellanox Technologies, Ltd
4 : : */
5 : :
6 : : #include <stddef.h>
7 : : #include <string.h>
8 : : #include <sys/queue.h>
9 : :
10 : : #include <rte_errno.h>
11 : : #include <rte_malloc.h>
12 : : #include <rte_tailq.h>
13 : : #include <rte_flow.h>
14 : : #include <rte_flow_driver.h>
15 : :
16 : : #include "failsafe_private.h"
17 : :
18 : : static struct rte_flow *
19 : 0 : fs_flow_allocate(const struct rte_flow_attr *attr,
20 : : const struct rte_flow_item *items,
21 : : const struct rte_flow_action *actions)
22 : : {
23 : : struct rte_flow *flow;
24 : 0 : const struct rte_flow_conv_rule rule = {
25 : : .attr_ro = attr,
26 : : .pattern_ro = items,
27 : : .actions_ro = actions,
28 : : };
29 : : struct rte_flow_error error;
30 : : int ret;
31 : :
32 : 0 : ret = rte_flow_conv(RTE_FLOW_CONV_OP_RULE, NULL, 0, &rule, &error);
33 [ # # ]: 0 : if (ret < 0) {
34 [ # # ]: 0 : ERROR("Unable to process flow rule (%s): %s",
35 : : error.message ? error.message : "unspecified",
36 : : strerror(rte_errno));
37 : 0 : return NULL;
38 : : }
39 : 0 : flow = rte_zmalloc(NULL, offsetof(struct rte_flow, rule) + ret,
40 : : RTE_CACHE_LINE_SIZE);
41 [ # # ]: 0 : if (flow == NULL) {
42 : 0 : ERROR("Could not allocate new flow");
43 : 0 : return NULL;
44 : : }
45 : 0 : ret = rte_flow_conv(RTE_FLOW_CONV_OP_RULE, &flow->rule, ret, &rule,
46 : : &error);
47 [ # # ]: 0 : if (ret < 0) {
48 [ # # ]: 0 : ERROR("Failed to copy flow rule (%s): %s",
49 : : error.message ? error.message : "unspecified",
50 : : strerror(rte_errno));
51 : 0 : rte_free(flow);
52 : 0 : return NULL;
53 : : }
54 : : return flow;
55 : : }
56 : :
57 : : static void
58 : : fs_flow_release(struct rte_flow **flow)
59 : : {
60 : 0 : rte_free(*flow);
61 : : *flow = NULL;
62 : : }
63 : :
64 : : static int
65 : 0 : fs_flow_validate(struct rte_eth_dev *dev,
66 : : const struct rte_flow_attr *attr,
67 : : const struct rte_flow_item patterns[],
68 : : const struct rte_flow_action actions[],
69 : : struct rte_flow_error *error)
70 : : {
71 : : struct sub_device *sdev;
72 : : uint8_t i;
73 : : int ret;
74 : :
75 : 0 : ret = fs_lock(dev, 0);
76 [ # # ]: 0 : if (ret != 0)
77 : : return ret;
78 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
79 : 0 : DEBUG("Calling rte_flow_validate on sub_device %d", i);
80 : 0 : ret = rte_flow_validate(PORT_ID(sdev),
81 : : attr, patterns, actions, error);
82 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
83 : 0 : ERROR("Operation rte_flow_validate failed for sub_device %d"
84 : : " with error %d", i, ret);
85 : 0 : fs_unlock(dev, 0);
86 : 0 : return ret;
87 : : }
88 : : }
89 : 0 : fs_unlock(dev, 0);
90 : 0 : return 0;
91 : : }
92 : :
93 : : static struct rte_flow *
94 : 0 : fs_flow_create(struct rte_eth_dev *dev,
95 : : const struct rte_flow_attr *attr,
96 : : const struct rte_flow_item patterns[],
97 : : const struct rte_flow_action actions[],
98 : : struct rte_flow_error *error)
99 : : {
100 : : struct sub_device *sdev;
101 : : struct rte_flow *flow;
102 : : uint8_t i;
103 : :
104 [ # # ]: 0 : if (fs_lock(dev, 0) != 0)
105 : : return NULL;
106 : 0 : flow = fs_flow_allocate(attr, patterns, actions);
107 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
108 : 0 : flow->flows[i] = rte_flow_create(PORT_ID(sdev),
109 : : attr, patterns, actions, error);
110 [ # # # # : 0 : if (flow->flows[i] == NULL && fs_err(sdev, -rte_errno)) {
# # ]
111 : 0 : ERROR("Failed to create flow on sub_device %d",
112 : : i);
113 [ # # ]: 0 : goto err;
114 : : }
115 : : }
116 : 0 : TAILQ_INSERT_TAIL(&PRIV(dev)->flow_list, flow, next);
117 : 0 : fs_unlock(dev, 0);
118 : 0 : return flow;
119 : : err:
120 [ # # # # ]: 0 : FOREACH_SUBDEV(sdev, i, dev) {
121 [ # # ]: 0 : if (flow->flows[i] != NULL)
122 : 0 : rte_flow_destroy(PORT_ID(sdev),
123 : : flow->flows[i], error);
124 : : }
125 : : fs_flow_release(&flow);
126 : 0 : fs_unlock(dev, 0);
127 : 0 : return NULL;
128 : : }
129 : :
130 : : static int
131 : 0 : fs_flow_destroy(struct rte_eth_dev *dev,
132 : : struct rte_flow *flow,
133 : : struct rte_flow_error *error)
134 : : {
135 : : struct sub_device *sdev;
136 : : uint8_t i;
137 : : int ret;
138 : :
139 [ # # ]: 0 : if (flow == NULL) {
140 : 0 : ERROR("Invalid flow");
141 : 0 : return -EINVAL;
142 : : }
143 : 0 : ret = fs_lock(dev, 0);
144 [ # # ]: 0 : if (ret != 0)
145 : : return ret;
146 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
147 : : int local_ret;
148 : :
149 [ # # ]: 0 : if (flow->flows[i] == NULL)
150 : 0 : continue;
151 : 0 : local_ret = rte_flow_destroy(PORT_ID(sdev),
152 : : flow->flows[i], error);
153 [ # # ]: 0 : if ((local_ret = fs_err(sdev, local_ret))) {
154 : 0 : ERROR("Failed to destroy flow on sub_device %d: %d",
155 : : i, local_ret);
156 [ # # ]: 0 : if (ret == 0)
157 : : ret = local_ret;
158 : : }
159 : : }
160 [ # # ]: 0 : TAILQ_REMOVE(&PRIV(dev)->flow_list, flow, next);
161 : : fs_flow_release(&flow);
162 : 0 : fs_unlock(dev, 0);
163 : 0 : return ret;
164 : : }
165 : :
166 : : static int
167 : 0 : fs_flow_flush(struct rte_eth_dev *dev,
168 : : struct rte_flow_error *error)
169 : : {
170 : : struct sub_device *sdev;
171 : : struct rte_flow *flow;
172 : : void *tmp;
173 : : uint8_t i;
174 : : int ret;
175 : :
176 : 0 : ret = fs_lock(dev, 0);
177 [ # # ]: 0 : if (ret != 0)
178 : : return ret;
179 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
180 : 0 : DEBUG("Calling rte_flow_flush on sub_device %d", i);
181 : 0 : ret = rte_flow_flush(PORT_ID(sdev), error);
182 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
183 : 0 : ERROR("Operation rte_flow_flush failed for sub_device %d"
184 : : " with error %d", i, ret);
185 : 0 : fs_unlock(dev, 0);
186 : 0 : return ret;
187 : : }
188 : : }
189 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(flow, &PRIV(dev)->flow_list, next, tmp) {
190 [ # # ]: 0 : TAILQ_REMOVE(&PRIV(dev)->flow_list, flow, next);
191 : : fs_flow_release(&flow);
192 : : }
193 : 0 : fs_unlock(dev, 0);
194 : 0 : return 0;
195 : : }
196 : :
197 : : static int
198 : 0 : fs_flow_query(struct rte_eth_dev *dev,
199 : : struct rte_flow *flow,
200 : : const struct rte_flow_action *action,
201 : : void *arg,
202 : : struct rte_flow_error *error)
203 : : {
204 : : struct sub_device *sdev;
205 : :
206 [ # # ]: 0 : if (fs_lock(dev, 0) != 0)
207 : : return -1;
208 [ # # # # ]: 0 : sdev = TX_SUBDEV(dev);
209 : : if (sdev != NULL) {
210 : 0 : int ret = rte_flow_query(PORT_ID(sdev),
211 : 0 : flow->flows[SUB_ID(sdev)],
212 : : action, arg, error);
213 : :
214 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
215 : 0 : fs_unlock(dev, 0);
216 : 0 : return ret;
217 : : }
218 : : }
219 : 0 : fs_unlock(dev, 0);
220 : 0 : WARN("No active sub_device to query about its flow");
221 : 0 : return -1;
222 : : }
223 : :
224 : : static int
225 : 0 : fs_flow_isolate(struct rte_eth_dev *dev,
226 : : int set,
227 : : struct rte_flow_error *error)
228 : : {
229 : : struct sub_device *sdev;
230 : : uint8_t i;
231 : : int ret;
232 : :
233 : 0 : ret = fs_lock(dev, 0);
234 [ # # ]: 0 : if (ret != 0)
235 : : return ret;
236 [ # # # # ]: 0 : FOREACH_SUBDEV(sdev, i, dev) {
237 [ # # ]: 0 : if (sdev->state < DEV_PROBED)
238 : 0 : continue;
239 : 0 : DEBUG("Calling rte_flow_isolate on sub_device %d", i);
240 [ # # ]: 0 : if (PRIV(dev)->flow_isolated != sdev->flow_isolated)
241 : 0 : WARN("flow isolation mode of sub_device %d in incoherent state.",
242 : : i);
243 : 0 : ret = rte_flow_isolate(PORT_ID(sdev), set, error);
244 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
245 : 0 : ERROR("Operation rte_flow_isolate failed for sub_device %d"
246 : : " with error %d", i, ret);
247 : 0 : fs_unlock(dev, 0);
248 : 0 : return ret;
249 : : }
250 : 0 : sdev->flow_isolated = set;
251 : : }
252 : 0 : PRIV(dev)->flow_isolated = set;
253 : 0 : fs_unlock(dev, 0);
254 : 0 : return 0;
255 : : }
256 : :
257 : : const struct rte_flow_ops fs_flow_ops = {
258 : : .validate = fs_flow_validate,
259 : : .create = fs_flow_create,
260 : : .destroy = fs_flow_destroy,
261 : : .flush = fs_flow_flush,
262 : : .query = fs_flow_query,
263 : : .isolate = fs_flow_isolate,
264 : : };
|