4 * Copyright 2017 6WIND S.A.
5 * Copyright 2017 Mellanox.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of 6WIND S.A. nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/queue.h>
36 #include <rte_malloc.h>
37 #include <rte_tailq.h>
39 #include <rte_flow_driver.h>
41 #include "failsafe_private.h"
43 static struct rte_flow *
44 fs_flow_allocate(const struct rte_flow_attr *attr,
45 const struct rte_flow_item *items,
46 const struct rte_flow_action *actions)
48 struct rte_flow *flow;
51 fdsz = rte_flow_copy(NULL, 0, attr, items, actions);
52 flow = rte_zmalloc(NULL,
53 sizeof(struct rte_flow) + fdsz,
56 ERROR("Could not allocate new flow");
59 flow->fd = (void *)((uintptr_t)flow + sizeof(*flow));
60 if (rte_flow_copy(flow->fd, fdsz, attr, items, actions) != fdsz) {
61 ERROR("Failed to copy flow description");
69 fs_flow_release(struct rte_flow **flow)
76 fs_flow_validate(struct rte_eth_dev *dev,
77 const struct rte_flow_attr *attr,
78 const struct rte_flow_item patterns[],
79 const struct rte_flow_action actions[],
80 struct rte_flow_error *error)
82 struct sub_device *sdev;
86 FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
87 DEBUG("Calling rte_flow_validate on sub_device %d", i);
88 ret = rte_flow_validate(PORT_ID(sdev),
89 attr, patterns, actions, error);
91 ERROR("Operation rte_flow_validate failed for sub_device %d"
92 " with error %d", i, ret);
99 static struct rte_flow *
100 fs_flow_create(struct rte_eth_dev *dev,
101 const struct rte_flow_attr *attr,
102 const struct rte_flow_item patterns[],
103 const struct rte_flow_action actions[],
104 struct rte_flow_error *error)
106 struct sub_device *sdev;
107 struct rte_flow *flow;
110 flow = fs_flow_allocate(attr, patterns, actions);
111 FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
112 flow->flows[i] = rte_flow_create(PORT_ID(sdev),
113 attr, patterns, actions, error);
114 if (flow->flows[i] == NULL) {
115 ERROR("Failed to create flow on sub_device %d",
120 TAILQ_INSERT_TAIL(&PRIV(dev)->flow_list, flow, next);
123 FOREACH_SUBDEV(sdev, i, dev) {
124 if (flow->flows[i] != NULL)
125 rte_flow_destroy(PORT_ID(sdev),
126 flow->flows[i], error);
128 fs_flow_release(&flow);
133 fs_flow_destroy(struct rte_eth_dev *dev,
134 struct rte_flow *flow,
135 struct rte_flow_error *error)
137 struct sub_device *sdev;
142 ERROR("Invalid flow");
146 FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
149 if (flow->flows[i] == NULL)
151 local_ret = rte_flow_destroy(PORT_ID(sdev),
152 flow->flows[i], error);
154 ERROR("Failed to destroy flow on sub_device %d: %d",
160 TAILQ_REMOVE(&PRIV(dev)->flow_list, flow, next);
161 fs_flow_release(&flow);
166 fs_flow_flush(struct rte_eth_dev *dev,
167 struct rte_flow_error *error)
169 struct sub_device *sdev;
170 struct rte_flow *flow;
175 FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
176 DEBUG("Calling rte_flow_flush on sub_device %d", i);
177 ret = rte_flow_flush(PORT_ID(sdev), error);
179 ERROR("Operation rte_flow_flush failed for sub_device %d"
180 " with error %d", i, ret);
184 TAILQ_FOREACH_SAFE(flow, &PRIV(dev)->flow_list, next, tmp) {
185 TAILQ_REMOVE(&PRIV(dev)->flow_list, flow, next);
186 fs_flow_release(&flow);
192 fs_flow_query(struct rte_eth_dev *dev,
193 struct rte_flow *flow,
194 enum rte_flow_action_type type,
196 struct rte_flow_error *error)
198 struct sub_device *sdev;
200 sdev = TX_SUBDEV(dev);
202 return rte_flow_query(PORT_ID(sdev),
203 flow->flows[SUB_ID(sdev)], type, arg, error);
205 WARN("No active sub_device to query about its flow");
210 fs_flow_isolate(struct rte_eth_dev *dev,
212 struct rte_flow_error *error)
214 struct sub_device *sdev;
218 FOREACH_SUBDEV(sdev, i, dev) {
219 if (sdev->state < DEV_PROBED)
221 DEBUG("Calling rte_flow_isolate on sub_device %d", i);
222 if (PRIV(dev)->flow_isolated != sdev->flow_isolated)
223 WARN("flow isolation mode of sub_device %d in incoherent state.",
225 ret = rte_flow_isolate(PORT_ID(sdev), set, error);
227 ERROR("Operation rte_flow_isolate failed for sub_device %d"
228 " with error %d", i, ret);
231 sdev->flow_isolated = set;
233 PRIV(dev)->flow_isolated = set;
237 const struct rte_flow_ops fs_flow_ops = {
238 .validate = fs_flow_validate,
239 .create = fs_flow_create,
240 .destroy = fs_flow_destroy,
241 .flush = fs_flow_flush,
242 .query = fs_flow_query,
243 .isolate = fs_flow_isolate,