1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2018 Mellanox Technologies, Ltd
7 #include <rte_malloc.h>
11 #include "rte_eth_bond_private.h"
13 static struct rte_flow
*
14 bond_flow_alloc(int numa_node
, const struct rte_flow_attr
*attr
,
15 const struct rte_flow_item
*items
,
16 const struct rte_flow_action
*actions
)
18 struct rte_flow
*flow
;
21 fdsz
= rte_flow_copy(NULL
, 0, attr
, items
, actions
);
22 flow
= rte_zmalloc_socket(NULL
, sizeof(struct rte_flow
) + fdsz
,
23 RTE_CACHE_LINE_SIZE
, numa_node
);
24 if (unlikely(flow
== NULL
)) {
25 RTE_BOND_LOG(ERR
, "Could not allocate new flow");
28 flow
->fd
= (void *)((uintptr_t)flow
+ sizeof(*flow
));
29 if (unlikely(rte_flow_copy(flow
->fd
, fdsz
, attr
, items
, actions
) !=
31 RTE_BOND_LOG(ERR
, "Failed to copy flow description");
39 bond_flow_release(struct rte_flow
**flow
)
46 bond_flow_validate(struct rte_eth_dev
*dev
, const struct rte_flow_attr
*attr
,
47 const struct rte_flow_item patterns
[],
48 const struct rte_flow_action actions
[],
49 struct rte_flow_error
*err
)
51 struct bond_dev_private
*internals
= dev
->data
->dev_private
;
55 for (i
= 0; i
< internals
->slave_count
; i
++) {
56 ret
= rte_flow_validate(internals
->slaves
[i
].port_id
, attr
,
57 patterns
, actions
, err
);
59 RTE_BOND_LOG(ERR
, "Operation rte_flow_validate failed"
60 " for slave %d with error %d", i
, ret
);
67 static struct rte_flow
*
68 bond_flow_create(struct rte_eth_dev
*dev
, const struct rte_flow_attr
*attr
,
69 const struct rte_flow_item patterns
[],
70 const struct rte_flow_action actions
[],
71 struct rte_flow_error
*err
)
73 struct bond_dev_private
*internals
= dev
->data
->dev_private
;
74 struct rte_flow
*flow
;
77 flow
= bond_flow_alloc(dev
->data
->numa_node
, attr
, patterns
, actions
);
78 if (unlikely(flow
== NULL
)) {
79 rte_flow_error_set(err
, ENOMEM
, RTE_FLOW_ERROR_TYPE_UNSPECIFIED
,
80 NULL
, rte_strerror(ENOMEM
));
83 for (i
= 0; i
< internals
->slave_count
; i
++) {
84 flow
->flows
[i
] = rte_flow_create(internals
->slaves
[i
].port_id
,
85 attr
, patterns
, actions
, err
);
86 if (unlikely(flow
->flows
[i
] == NULL
)) {
87 RTE_BOND_LOG(ERR
, "Failed to create flow on slave %d",
92 TAILQ_INSERT_TAIL(&internals
->flow_list
, flow
, next
);
95 /* Destroy all slaves flows. */
96 for (i
= 0; i
< internals
->slave_count
; i
++) {
97 if (flow
->flows
[i
] != NULL
)
98 rte_flow_destroy(internals
->slaves
[i
].port_id
,
101 bond_flow_release(&flow
);
106 bond_flow_destroy(struct rte_eth_dev
*dev
, struct rte_flow
*flow
,
107 struct rte_flow_error
*err
)
109 struct bond_dev_private
*internals
= dev
->data
->dev_private
;
113 for (i
= 0; i
< internals
->slave_count
; i
++) {
116 if (unlikely(flow
->flows
[i
] == NULL
))
118 lret
= rte_flow_destroy(internals
->slaves
[i
].port_id
,
119 flow
->flows
[i
], err
);
120 if (unlikely(lret
!= 0)) {
121 RTE_BOND_LOG(ERR
, "Failed to destroy flow on slave %d:"
126 TAILQ_REMOVE(&internals
->flow_list
, flow
, next
);
127 bond_flow_release(&flow
);
132 bond_flow_flush(struct rte_eth_dev
*dev
, struct rte_flow_error
*err
)
134 struct bond_dev_private
*internals
= dev
->data
->dev_private
;
135 struct rte_flow
*flow
;
140 /* Destroy all bond flows from its slaves instead of flushing them to
141 * keep the LACP flow or any other external flows.
143 TAILQ_FOREACH_SAFE(flow
, &internals
->flow_list
, next
, tmp
) {
144 lret
= bond_flow_destroy(dev
, flow
, err
);
145 if (unlikely(lret
!= 0))
148 if (unlikely(ret
!= 0))
149 RTE_BOND_LOG(ERR
, "Failed to flush flow in all slaves");
154 bond_flow_query_count(struct rte_eth_dev
*dev
, struct rte_flow
*flow
,
155 const struct rte_flow_action
*action
,
156 struct rte_flow_query_count
*count
,
157 struct rte_flow_error
*err
)
159 struct bond_dev_private
*internals
= dev
->data
->dev_private
;
160 struct rte_flow_query_count slave_count
;
166 rte_memcpy(&slave_count
, count
, sizeof(slave_count
));
167 for (i
= 0; i
< internals
->slave_count
; i
++) {
168 ret
= rte_flow_query(internals
->slaves
[i
].port_id
,
169 flow
->flows
[i
], action
,
171 if (unlikely(ret
!= 0)) {
172 RTE_BOND_LOG(ERR
, "Failed to query flow on"
173 " slave %d: %d", i
, ret
);
176 count
->bytes
+= slave_count
.bytes
;
177 count
->hits
+= slave_count
.hits
;
178 slave_count
.bytes
= 0;
179 slave_count
.hits
= 0;
185 bond_flow_query(struct rte_eth_dev
*dev
, struct rte_flow
*flow
,
186 const struct rte_flow_action
*action
, void *arg
,
187 struct rte_flow_error
*err
)
189 switch (action
->type
) {
190 case RTE_FLOW_ACTION_TYPE_COUNT
:
191 return bond_flow_query_count(dev
, flow
, action
, arg
, err
);
193 return rte_flow_error_set(err
, ENOTSUP
,
194 RTE_FLOW_ERROR_TYPE_ACTION
, arg
,
195 rte_strerror(ENOTSUP
));
200 bond_flow_isolate(struct rte_eth_dev
*dev
, int set
,
201 struct rte_flow_error
*err
)
203 struct bond_dev_private
*internals
= dev
->data
->dev_private
;
207 for (i
= 0; i
< internals
->slave_count
; i
++) {
208 ret
= rte_flow_isolate(internals
->slaves
[i
].port_id
, set
, err
);
209 if (unlikely(ret
!= 0)) {
210 RTE_BOND_LOG(ERR
, "Operation rte_flow_isolate failed"
211 " for slave %d with error %d", i
, ret
);
212 internals
->flow_isolated_valid
= 0;
216 internals
->flow_isolated
= set
;
217 internals
->flow_isolated_valid
= 1;
221 const struct rte_flow_ops bond_flow_ops
= {
222 .validate
= bond_flow_validate
,
223 .create
= bond_flow_create
,
224 .destroy
= bond_flow_destroy
,
225 .flush
= bond_flow_flush
,
226 .query
= bond_flow_query
,
227 .isolate
= bond_flow_isolate
,