bpf: bpf_prog_pack: Set proper size before freeing ro_header
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlx5 / core / en / tc / act / mirred.c
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
4 #include <linux/if_macvlan.h>
5 #include <linux/if_vlan.h>
6 #include <net/bareudp.h>
7 #include <net/bonding.h>
8 #include "act.h"
9 #include "vlan.h"
10 #include "en/tc_tun_encap.h"
11 #include "en/tc_priv.h"
12 #include "en_rep.h"
13
14 static bool
15 same_vf_reps(struct mlx5e_priv *priv, struct net_device *out_dev)
16 {
17         return mlx5e_eswitch_vf_rep(priv->netdev) &&
18                priv->netdev == out_dev;
19 }
20
21 static int
22 verify_uplink_forwarding(struct mlx5e_priv *priv,
23                          struct mlx5_flow_attr *attr,
24                          struct net_device *out_dev,
25                          struct netlink_ext_ack *extack)
26 {
27         struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
28         struct mlx5e_rep_priv *rep_priv;
29
30         /* Forwarding non encapsulated traffic between
31          * uplink ports is allowed only if
32          * termination_table_raw_traffic cap is set.
33          *
34          * Input vport was stored attr->in_rep.
35          * In LAG case, *priv* is the private data of
36          * uplink which may be not the input vport.
37          */
38         rep_priv = mlx5e_rep_to_rep_priv(attr->esw_attr->in_rep);
39
40         if (!(mlx5e_eswitch_uplink_rep(rep_priv->netdev) &&
41               mlx5e_eswitch_uplink_rep(out_dev)))
42                 return 0;
43
44         if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev,
45                                         termination_table_raw_traffic)) {
46                 NL_SET_ERR_MSG_MOD(extack,
47                                    "devices are both uplink, can't offload forwarding");
48                         return -EOPNOTSUPP;
49         } else if (out_dev != rep_priv->netdev) {
50                 NL_SET_ERR_MSG_MOD(extack,
51                                    "devices are not the same uplink, can't offload forwarding");
52                 return -EOPNOTSUPP;
53         }
54         return 0;
55 }
56
57 static bool
58 is_duplicated_output_device(struct net_device *dev,
59                             struct net_device *out_dev,
60                             int *ifindexes, int if_count,
61                             struct netlink_ext_ack *extack)
62 {
63         int i;
64
65         for (i = 0; i < if_count; i++) {
66                 if (ifindexes[i] == out_dev->ifindex) {
67                         NL_SET_ERR_MSG_MOD(extack, "can't duplicate output to same device");
68                         netdev_err(dev, "can't duplicate output to same device: %s\n",
69                                    out_dev->name);
70                         return true;
71                 }
72         }
73
74         return false;
75 }
76
77 static struct net_device *
78 get_fdb_out_dev(struct net_device *uplink_dev, struct net_device *out_dev)
79 {
80         struct net_device *fdb_out_dev = out_dev;
81         struct net_device *uplink_upper;
82
83         rcu_read_lock();
84         uplink_upper = netdev_master_upper_dev_get_rcu(uplink_dev);
85         if (uplink_upper && netif_is_lag_master(uplink_upper) &&
86             uplink_upper == out_dev) {
87                 fdb_out_dev = uplink_dev;
88         } else if (netif_is_lag_master(out_dev)) {
89                 fdb_out_dev = bond_option_active_slave_get_rcu(netdev_priv(out_dev));
90                 if (fdb_out_dev &&
91                     (!mlx5e_eswitch_rep(fdb_out_dev) ||
92                      !netdev_port_same_parent_id(fdb_out_dev, uplink_dev)))
93                         fdb_out_dev = NULL;
94         }
95         rcu_read_unlock();
96         return fdb_out_dev;
97 }
98
99 static bool
100 tc_act_can_offload_mirred(struct mlx5e_tc_act_parse_state *parse_state,
101                           const struct flow_action_entry *act,
102                           int act_index,
103                           struct mlx5_flow_attr *attr)
104 {
105         struct netlink_ext_ack *extack = parse_state->extack;
106         struct mlx5e_tc_flow *flow = parse_state->flow;
107         struct mlx5e_tc_flow_parse_attr *parse_attr;
108         struct net_device *out_dev = act->dev;
109         struct mlx5e_priv *priv = flow->priv;
110         struct mlx5_esw_flow_attr *esw_attr;
111
112         parse_attr = attr->parse_attr;
113         esw_attr = attr->esw_attr;
114
115         if (!out_dev) {
116                 /* out_dev is NULL when filters with
117                  * non-existing mirred device are replayed to
118                  * the driver.
119                  */
120                 return false;
121         }
122
123         if (parse_state->mpls_push && !netif_is_bareudp(out_dev)) {
124                 NL_SET_ERR_MSG_MOD(extack, "mpls is supported only through a bareudp device");
125                 return false;
126         }
127
128         if (mlx5e_is_ft_flow(flow) && out_dev == priv->netdev) {
129                 /* Ignore forward to self rules generated
130                  * by adding both mlx5 devs to the flow table
131                  * block on a normal nft offload setup.
132                  */
133                 return false;
134         }
135
136         if (esw_attr->out_count >= MLX5_MAX_FLOW_FWD_VPORTS) {
137                 NL_SET_ERR_MSG_MOD(extack,
138                                    "can't support more output ports, can't offload forwarding");
139                 netdev_warn(priv->netdev,
140                             "can't support more than %d output ports, can't offload forwarding\n",
141                             esw_attr->out_count);
142                 return false;
143         }
144
145         if (parse_state->encap ||
146             netdev_port_same_parent_id(priv->netdev, out_dev) ||
147             netif_is_ovs_master(out_dev))
148                 return true;
149
150         if (parse_attr->filter_dev != priv->netdev) {
151                 /* All mlx5 devices are called to configure
152                  * high level device filters. Therefore, the
153                  * *attempt* to  install a filter on invalid
154                  * eswitch should not trigger an explicit error
155                  */
156                 return false;
157         }
158
159         NL_SET_ERR_MSG_MOD(extack, "devices are not on same switch HW, can't offload forwarding");
160
161         return false;
162 }
163
164 static int
165 parse_mirred_encap(struct mlx5e_tc_act_parse_state *parse_state,
166                    const struct flow_action_entry *act,
167                    struct mlx5_flow_attr *attr)
168 {
169         struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr;
170         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
171         struct net_device *out_dev = act->dev;
172
173         parse_attr->mirred_ifindex[esw_attr->out_count] = out_dev->ifindex;
174         parse_attr->tun_info[esw_attr->out_count] =
175                 mlx5e_dup_tun_info(parse_state->tun_info);
176
177         if (!parse_attr->tun_info[esw_attr->out_count])
178                 return -ENOMEM;
179
180         parse_state->encap = false;
181         esw_attr->dests[esw_attr->out_count].flags |= MLX5_ESW_DEST_ENCAP;
182         esw_attr->out_count++;
183         /* attr->dests[].rep is resolved when we handle encap */
184
185         return 0;
186 }
187
188 static int
189 parse_mirred(struct mlx5e_tc_act_parse_state *parse_state,
190              const struct flow_action_entry *act,
191              struct mlx5e_priv *priv,
192              struct mlx5_flow_attr *attr)
193 {
194         struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr;
195         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
196         struct netlink_ext_ack *extack = parse_state->extack;
197         struct mlx5e_rep_priv *rpriv = priv->ppriv;
198         struct net_device *out_dev = act->dev;
199         struct net_device *uplink_dev;
200         struct mlx5e_priv *out_priv;
201         struct mlx5_eswitch *esw;
202         int *ifindexes;
203         int if_count;
204         int err;
205
206         esw = priv->mdev->priv.eswitch;
207         uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH);
208         ifindexes = parse_state->ifindexes;
209         if_count = parse_state->if_count;
210
211         if (is_duplicated_output_device(priv->netdev, out_dev, ifindexes, if_count, extack))
212                 return -EOPNOTSUPP;
213
214         parse_state->ifindexes[if_count] = out_dev->ifindex;
215         parse_state->if_count++;
216
217         out_dev = get_fdb_out_dev(uplink_dev, out_dev);
218         if (!out_dev)
219                 return -ENODEV;
220
221         if (is_vlan_dev(out_dev)) {
222                 err = mlx5e_tc_act_vlan_add_push_action(priv, attr, &out_dev, extack);
223                 if (err)
224                         return err;
225         }
226
227         if (is_vlan_dev(parse_attr->filter_dev)) {
228                 err = mlx5e_tc_act_vlan_add_pop_action(priv, attr, extack);
229                 if (err)
230                         return err;
231         }
232
233         if (netif_is_macvlan(out_dev))
234                 out_dev = macvlan_dev_real_dev(out_dev);
235
236         err = verify_uplink_forwarding(priv, attr, out_dev, extack);
237         if (err)
238                 return err;
239
240         if (!mlx5e_is_valid_eswitch_fwd_dev(priv, out_dev)) {
241                 NL_SET_ERR_MSG_MOD(extack,
242                                    "devices are not on same switch HW, can't offload forwarding");
243                 return -EOPNOTSUPP;
244         }
245
246         if (same_vf_reps(priv, out_dev)) {
247                 NL_SET_ERR_MSG_MOD(extack, "can't forward from a VF to itself");
248                 return -EOPNOTSUPP;
249         }
250
251         out_priv = netdev_priv(out_dev);
252         rpriv = out_priv->ppriv;
253         esw_attr->dests[esw_attr->out_count].rep = rpriv->rep;
254         esw_attr->dests[esw_attr->out_count].mdev = out_priv->mdev;
255         esw_attr->out_count++;
256
257         return 0;
258 }
259
260 static int
261 parse_mirred_ovs_master(struct mlx5e_tc_act_parse_state *parse_state,
262                         const struct flow_action_entry *act,
263                         struct mlx5e_priv *priv,
264                         struct mlx5_flow_attr *attr)
265 {
266         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
267         struct net_device *out_dev = act->dev;
268         int err;
269
270         err = mlx5e_set_fwd_to_int_port_actions(priv, attr, out_dev->ifindex,
271                                                 MLX5E_TC_INT_PORT_EGRESS,
272                                                 &attr->action, esw_attr->out_count);
273         if (err)
274                 return err;
275
276         esw_attr->out_count++;
277         return 0;
278 }
279
280 static int
281 tc_act_parse_mirred(struct mlx5e_tc_act_parse_state *parse_state,
282                     const struct flow_action_entry *act,
283                     struct mlx5e_priv *priv,
284                     struct mlx5_flow_attr *attr)
285 {
286         struct net_device *out_dev = act->dev;
287         int err = -EOPNOTSUPP;
288
289         if (parse_state->encap)
290                 err = parse_mirred_encap(parse_state, act, attr);
291         else if (netdev_port_same_parent_id(priv->netdev, out_dev))
292                 err = parse_mirred(parse_state, act, priv, attr);
293         else if (netif_is_ovs_master(out_dev))
294                 err = parse_mirred_ovs_master(parse_state, act, priv, attr);
295
296         if (err)
297                 return err;
298
299         attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
300                         MLX5_FLOW_CONTEXT_ACTION_COUNT;
301
302         return 0;
303 }
304
305 struct mlx5e_tc_act mlx5e_tc_act_mirred = {
306         .can_offload = tc_act_can_offload_mirred,
307         .parse_action = tc_act_parse_mirred,
308 };