Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2018 Mellanox Technologies, Ltd
3 : : */
4 : :
5 : : #include <stddef.h>
6 : : #include <string.h>
7 : : #include <sys/queue.h>
8 : :
9 : : #include <rte_errno.h>
10 : : #include <rte_malloc.h>
11 : : #include <rte_tailq.h>
12 : : #include <rte_flow.h>
13 : :
14 : : #include "eth_bond_private.h"
15 : :
16 : : static struct rte_flow *
17 : 0 : bond_flow_alloc(int numa_node, const struct rte_flow_attr *attr,
18 : : const struct rte_flow_item *items,
19 : : const struct rte_flow_action *actions)
20 : : {
21 : : struct rte_flow *flow;
22 : 0 : const struct rte_flow_conv_rule rule = {
23 : : .attr_ro = attr,
24 : : .pattern_ro = items,
25 : : .actions_ro = actions,
26 : : };
27 : : struct rte_flow_error error;
28 : : int ret;
29 : :
30 : 0 : ret = rte_flow_conv(RTE_FLOW_CONV_OP_RULE, NULL, 0, &rule, &error);
31 [ # # ]: 0 : if (ret < 0) {
32 [ # # ]: 0 : RTE_BOND_LOG(ERR, "Unable to process flow rule (%s): %s",
33 : : error.message ? error.message : "unspecified",
34 : : strerror(rte_errno));
35 : 0 : return NULL;
36 : : }
37 : 0 : flow = rte_zmalloc_socket(NULL, offsetof(struct rte_flow, rule) + ret,
38 : : RTE_CACHE_LINE_SIZE, numa_node);
39 [ # # ]: 0 : if (unlikely(flow == NULL)) {
40 : 0 : RTE_BOND_LOG(ERR, "Could not allocate new flow");
41 : 0 : return NULL;
42 : : }
43 : 0 : ret = rte_flow_conv(RTE_FLOW_CONV_OP_RULE, &flow->rule, ret, &rule,
44 : : &error);
45 [ # # ]: 0 : if (ret < 0) {
46 [ # # ]: 0 : RTE_BOND_LOG(ERR, "Failed to copy flow rule (%s): %s",
47 : : error.message ? error.message : "unspecified",
48 : : strerror(rte_errno));
49 : 0 : rte_free(flow);
50 : 0 : return NULL;
51 : : }
52 : : return flow;
53 : : }
54 : :
55 : : static void
56 : : bond_flow_release(struct rte_flow **flow)
57 : : {
58 : 0 : rte_free(*flow);
59 : : *flow = NULL;
60 : : }
61 : :
62 : : static int
63 : 0 : bond_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
64 : : const struct rte_flow_item patterns[],
65 : : const struct rte_flow_action actions[],
66 : : struct rte_flow_error *err)
67 : : {
68 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
69 : : int i;
70 : : int ret;
71 : :
72 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
73 : 0 : ret = rte_flow_validate(internals->members[i].port_id, attr,
74 : : patterns, actions, err);
75 [ # # ]: 0 : if (ret) {
76 : 0 : RTE_BOND_LOG(ERR, "Operation rte_flow_validate failed"
77 : : " for member %d with error %d", i, ret);
78 : 0 : return ret;
79 : : }
80 : : }
81 : : return 0;
82 : : }
83 : :
84 : : static struct rte_flow *
85 : 0 : bond_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
86 : : const struct rte_flow_item patterns[],
87 : : const struct rte_flow_action actions[],
88 : : struct rte_flow_error *err)
89 : : {
90 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
91 : : struct rte_flow *flow;
92 : : int i;
93 : :
94 : 0 : flow = bond_flow_alloc(dev->data->numa_node, attr, patterns, actions);
95 [ # # ]: 0 : if (unlikely(flow == NULL)) {
96 : 0 : rte_flow_error_set(err, ENOMEM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
97 : : NULL, rte_strerror(ENOMEM));
98 : 0 : return NULL;
99 : : }
100 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
101 : 0 : flow->flows[i] = rte_flow_create(internals->members[i].port_id,
102 : : attr, patterns, actions, err);
103 [ # # ]: 0 : if (unlikely(flow->flows[i] == NULL)) {
104 : 0 : RTE_BOND_LOG(ERR, "Failed to create flow on member %d",
105 : : i);
106 : 0 : goto err;
107 : : }
108 : : }
109 : 0 : TAILQ_INSERT_TAIL(&internals->flow_list, flow, next);
110 : 0 : return flow;
111 : : err:
112 : : /* Destroy all members flows. */
113 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
114 [ # # ]: 0 : if (flow->flows[i] != NULL)
115 : 0 : rte_flow_destroy(internals->members[i].port_id,
116 : : flow->flows[i], err);
117 : : }
118 : : bond_flow_release(&flow);
119 : 0 : return NULL;
120 : : }
121 : :
122 : : static int
123 : 0 : bond_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
124 : : struct rte_flow_error *err)
125 : : {
126 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
127 : : int i;
128 : : int ret = 0;
129 : :
130 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
131 : : int lret;
132 : :
133 [ # # ]: 0 : if (unlikely(flow->flows[i] == NULL))
134 : 0 : continue;
135 : 0 : lret = rte_flow_destroy(internals->members[i].port_id,
136 : : flow->flows[i], err);
137 [ # # ]: 0 : if (unlikely(lret != 0)) {
138 : 0 : RTE_BOND_LOG(ERR, "Failed to destroy flow on member %d:"
139 : : " %d", i, lret);
140 : : ret = lret;
141 : : }
142 : : }
143 [ # # ]: 0 : TAILQ_REMOVE(&internals->flow_list, flow, next);
144 : : bond_flow_release(&flow);
145 : 0 : return ret;
146 : : }
147 : :
148 : : static int
149 : 0 : bond_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *err)
150 : : {
151 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
152 : : struct rte_flow *flow;
153 : : void *tmp;
154 : : int ret = 0;
155 : : int lret;
156 : :
157 : : /* Destroy all bond flows from its members instead of flushing them to
158 : : * keep the LACP flow or any other external flows.
159 : : */
160 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(flow, &internals->flow_list, next, tmp) {
161 : 0 : lret = bond_flow_destroy(dev, flow, err);
162 [ # # ]: 0 : if (unlikely(lret != 0))
163 : : ret = lret;
164 : : }
165 [ # # ]: 0 : if (unlikely(ret != 0))
166 : 0 : RTE_BOND_LOG(ERR, "Failed to flush flow in all members");
167 : 0 : return ret;
168 : : }
169 : :
170 : : static int
171 : 0 : bond_flow_query_count(struct rte_eth_dev *dev, struct rte_flow *flow,
172 : : const struct rte_flow_action *action,
173 : : struct rte_flow_query_count *count,
174 : : struct rte_flow_error *err)
175 : : {
176 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
177 : : struct rte_flow_query_count member_count;
178 : : int i;
179 : : int ret;
180 : :
181 : 0 : count->bytes = 0;
182 [ # # ]: 0 : count->hits = 0;
183 : : rte_memcpy(&member_count, count, sizeof(member_count));
184 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
185 : 0 : ret = rte_flow_query(internals->members[i].port_id,
186 : : flow->flows[i], action,
187 : : &member_count, err);
188 [ # # ]: 0 : if (unlikely(ret != 0)) {
189 : 0 : RTE_BOND_LOG(ERR, "Failed to query flow on"
190 : : " member %d: %d", i, ret);
191 : 0 : return ret;
192 : : }
193 : 0 : count->bytes += member_count.bytes;
194 : 0 : count->hits += member_count.hits;
195 : 0 : member_count.bytes = 0;
196 : 0 : member_count.hits = 0;
197 : : }
198 : : return 0;
199 : : }
200 : :
201 : : static int
202 : 0 : bond_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,
203 : : const struct rte_flow_action *action, void *arg,
204 : : struct rte_flow_error *err)
205 : : {
206 [ # # ]: 0 : switch (action->type) {
207 : 0 : case RTE_FLOW_ACTION_TYPE_COUNT:
208 : 0 : return bond_flow_query_count(dev, flow, action, arg, err);
209 : 0 : default:
210 : 0 : return rte_flow_error_set(err, ENOTSUP,
211 : : RTE_FLOW_ERROR_TYPE_ACTION, arg,
212 : : rte_strerror(ENOTSUP));
213 : : }
214 : : }
215 : :
216 : : static int
217 : 0 : bond_flow_isolate(struct rte_eth_dev *dev, int set,
218 : : struct rte_flow_error *err)
219 : : {
220 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
221 : : int i;
222 : : int ret;
223 : :
224 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
225 : 0 : ret = rte_flow_isolate(internals->members[i].port_id, set, err);
226 [ # # ]: 0 : if (unlikely(ret != 0)) {
227 : 0 : RTE_BOND_LOG(ERR, "Operation rte_flow_isolate failed"
228 : : " for member %d with error %d", i, ret);
229 : 0 : internals->flow_isolated_valid = 0;
230 : 0 : return ret;
231 : : }
232 : : }
233 : 0 : internals->flow_isolated = set;
234 : 0 : internals->flow_isolated_valid = 1;
235 : 0 : return 0;
236 : : }
237 : :
238 : : const struct rte_flow_ops bond_flow_ops = {
239 : : .validate = bond_flow_validate,
240 : : .create = bond_flow_create,
241 : : .destroy = bond_flow_destroy,
242 : : .flush = bond_flow_flush,
243 : : .query = bond_flow_query,
244 : : .isolate = bond_flow_isolate,
245 : : };
|