b456e81a73a43f84ae0226699554fa75708a175f
[linux-2.6-microblaze.git] / drivers / net / ethernet / netronome / nfp / flower / action.c
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
3
4 #include <linux/bitfield.h>
5 #include <linux/mpls.h>
6 #include <net/pkt_cls.h>
7 #include <net/tc_act/tc_csum.h>
8 #include <net/tc_act/tc_gact.h>
9 #include <net/tc_act/tc_mirred.h>
10 #include <net/tc_act/tc_mpls.h>
11 #include <net/tc_act/tc_pedit.h>
12 #include <net/tc_act/tc_vlan.h>
13 #include <net/tc_act/tc_tunnel_key.h>
14
15 #include "cmsg.h"
16 #include "main.h"
17 #include "../nfp_net_repr.h"
18
19 /* The kernel versions of TUNNEL_* are not ABI and therefore vulnerable
20  * to change. Such changes will break our FW ABI.
21  */
22 #define NFP_FL_TUNNEL_CSUM                      cpu_to_be16(0x01)
23 #define NFP_FL_TUNNEL_KEY                       cpu_to_be16(0x04)
24 #define NFP_FL_TUNNEL_GENEVE_OPT                cpu_to_be16(0x0800)
25 #define NFP_FL_SUPPORTED_TUNNEL_INFO_FLAGS      (IP_TUNNEL_INFO_TX | \
26                                                  IP_TUNNEL_INFO_IPV6)
27 #define NFP_FL_SUPPORTED_UDP_TUN_FLAGS          (NFP_FL_TUNNEL_CSUM | \
28                                                  NFP_FL_TUNNEL_KEY | \
29                                                  NFP_FL_TUNNEL_GENEVE_OPT)
30
31 static int
32 nfp_fl_push_mpls(struct nfp_fl_push_mpls *push_mpls,
33                  const struct flow_action_entry *act,
34                  struct netlink_ext_ack *extack)
35 {
36         size_t act_size = sizeof(struct nfp_fl_push_mpls);
37         u32 mpls_lse = 0;
38
39         push_mpls->head.jump_id = NFP_FL_ACTION_OPCODE_PUSH_MPLS;
40         push_mpls->head.len_lw = act_size >> NFP_FL_LW_SIZ;
41
42         /* BOS is optional in the TC action but required for offload. */
43         if (act->mpls_push.bos != ACT_MPLS_BOS_NOT_SET) {
44                 mpls_lse |= act->mpls_push.bos << MPLS_LS_S_SHIFT;
45         } else {
46                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: BOS field must explicitly be set for MPLS push");
47                 return -EOPNOTSUPP;
48         }
49
50         /* Leave MPLS TC as a default value of 0 if not explicitly set. */
51         if (act->mpls_push.tc != ACT_MPLS_TC_NOT_SET)
52                 mpls_lse |= act->mpls_push.tc << MPLS_LS_TC_SHIFT;
53
54         /* Proto, label and TTL are enforced and verified for MPLS push. */
55         mpls_lse |= act->mpls_push.label << MPLS_LS_LABEL_SHIFT;
56         mpls_lse |= act->mpls_push.ttl << MPLS_LS_TTL_SHIFT;
57         push_mpls->ethtype = act->mpls_push.proto;
58         push_mpls->lse = cpu_to_be32(mpls_lse);
59
60         return 0;
61 }
62
63 static void
64 nfp_fl_pop_mpls(struct nfp_fl_pop_mpls *pop_mpls,
65                 const struct flow_action_entry *act)
66 {
67         size_t act_size = sizeof(struct nfp_fl_pop_mpls);
68
69         pop_mpls->head.jump_id = NFP_FL_ACTION_OPCODE_POP_MPLS;
70         pop_mpls->head.len_lw = act_size >> NFP_FL_LW_SIZ;
71         pop_mpls->ethtype = act->mpls_pop.proto;
72 }
73
74 static void
75 nfp_fl_set_mpls(struct nfp_fl_set_mpls *set_mpls,
76                 const struct flow_action_entry *act)
77 {
78         size_t act_size = sizeof(struct nfp_fl_set_mpls);
79         u32 mpls_lse = 0, mpls_mask = 0;
80
81         set_mpls->head.jump_id = NFP_FL_ACTION_OPCODE_SET_MPLS;
82         set_mpls->head.len_lw = act_size >> NFP_FL_LW_SIZ;
83
84         if (act->mpls_mangle.label != ACT_MPLS_LABEL_NOT_SET) {
85                 mpls_lse |= act->mpls_mangle.label << MPLS_LS_LABEL_SHIFT;
86                 mpls_mask |= MPLS_LS_LABEL_MASK;
87         }
88         if (act->mpls_mangle.tc != ACT_MPLS_TC_NOT_SET) {
89                 mpls_lse |= act->mpls_mangle.tc << MPLS_LS_TC_SHIFT;
90                 mpls_mask |= MPLS_LS_TC_MASK;
91         }
92         if (act->mpls_mangle.bos != ACT_MPLS_BOS_NOT_SET) {
93                 mpls_lse |= act->mpls_mangle.bos << MPLS_LS_S_SHIFT;
94                 mpls_mask |= MPLS_LS_S_MASK;
95         }
96         if (act->mpls_mangle.ttl) {
97                 mpls_lse |= act->mpls_mangle.ttl << MPLS_LS_TTL_SHIFT;
98                 mpls_mask |= MPLS_LS_TTL_MASK;
99         }
100
101         set_mpls->lse = cpu_to_be32(mpls_lse);
102         set_mpls->lse_mask = cpu_to_be32(mpls_mask);
103 }
104
105 static void nfp_fl_pop_vlan(struct nfp_fl_pop_vlan *pop_vlan)
106 {
107         size_t act_size = sizeof(struct nfp_fl_pop_vlan);
108
109         pop_vlan->head.jump_id = NFP_FL_ACTION_OPCODE_POP_VLAN;
110         pop_vlan->head.len_lw = act_size >> NFP_FL_LW_SIZ;
111         pop_vlan->reserved = 0;
112 }
113
114 static void
115 nfp_fl_push_vlan(struct nfp_fl_push_vlan *push_vlan,
116                  const struct flow_action_entry *act)
117 {
118         size_t act_size = sizeof(struct nfp_fl_push_vlan);
119         u16 tmp_push_vlan_tci;
120
121         push_vlan->head.jump_id = NFP_FL_ACTION_OPCODE_PUSH_VLAN;
122         push_vlan->head.len_lw = act_size >> NFP_FL_LW_SIZ;
123         push_vlan->reserved = 0;
124         push_vlan->vlan_tpid = act->vlan.proto;
125
126         tmp_push_vlan_tci =
127                 FIELD_PREP(NFP_FL_PUSH_VLAN_PRIO, act->vlan.prio) |
128                 FIELD_PREP(NFP_FL_PUSH_VLAN_VID, act->vlan.vid);
129         push_vlan->vlan_tci = cpu_to_be16(tmp_push_vlan_tci);
130 }
131
132 static int
133 nfp_fl_pre_lag(struct nfp_app *app, const struct flow_action_entry *act,
134                struct nfp_fl_payload *nfp_flow, int act_len,
135                struct netlink_ext_ack *extack)
136 {
137         size_t act_size = sizeof(struct nfp_fl_pre_lag);
138         struct nfp_fl_pre_lag *pre_lag;
139         struct net_device *out_dev;
140         int err;
141
142         out_dev = act->dev;
143         if (!out_dev || !netif_is_lag_master(out_dev))
144                 return 0;
145
146         if (act_len + act_size > NFP_FL_MAX_A_SIZ) {
147                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed action list size exceeded at LAG action");
148                 return -EOPNOTSUPP;
149         }
150
151         /* Pre_lag action must be first on action list.
152          * If other actions already exist they need pushed forward.
153          */
154         if (act_len)
155                 memmove(nfp_flow->action_data + act_size,
156                         nfp_flow->action_data, act_len);
157
158         pre_lag = (struct nfp_fl_pre_lag *)nfp_flow->action_data;
159         err = nfp_flower_lag_populate_pre_action(app, out_dev, pre_lag, extack);
160         if (err)
161                 return err;
162
163         pre_lag->head.jump_id = NFP_FL_ACTION_OPCODE_PRE_LAG;
164         pre_lag->head.len_lw = act_size >> NFP_FL_LW_SIZ;
165
166         nfp_flow->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL);
167
168         return act_size;
169 }
170
171 static int
172 nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output,
173               const struct flow_action_entry *act,
174               struct nfp_fl_payload *nfp_flow,
175               bool last, struct net_device *in_dev,
176               enum nfp_flower_tun_type tun_type, int *tun_out_cnt,
177               bool pkt_host, struct netlink_ext_ack *extack)
178 {
179         size_t act_size = sizeof(struct nfp_fl_output);
180         struct nfp_flower_priv *priv = app->priv;
181         struct net_device *out_dev;
182         u16 tmp_flags;
183
184         output->head.jump_id = NFP_FL_ACTION_OPCODE_OUTPUT;
185         output->head.len_lw = act_size >> NFP_FL_LW_SIZ;
186
187         out_dev = act->dev;
188         if (!out_dev) {
189                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid egress interface for mirred action");
190                 return -EOPNOTSUPP;
191         }
192
193         tmp_flags = last ? NFP_FL_OUT_FLAGS_LAST : 0;
194
195         if (tun_type) {
196                 /* Verify the egress netdev matches the tunnel type. */
197                 if (!nfp_fl_netdev_is_tunnel_type(out_dev, tun_type)) {
198                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: egress interface does not match the required tunnel type");
199                         return -EOPNOTSUPP;
200                 }
201
202                 if (*tun_out_cnt) {
203                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: cannot offload more than one tunnel mirred output per filter");
204                         return -EOPNOTSUPP;
205                 }
206                 (*tun_out_cnt)++;
207
208                 output->flags = cpu_to_be16(tmp_flags |
209                                             NFP_FL_OUT_FLAGS_USE_TUN);
210                 output->port = cpu_to_be32(NFP_FL_PORT_TYPE_TUN | tun_type);
211         } else if (netif_is_lag_master(out_dev) &&
212                    priv->flower_en_feats & NFP_FL_ENABLE_LAG) {
213                 int gid;
214
215                 output->flags = cpu_to_be16(tmp_flags);
216                 gid = nfp_flower_lag_get_output_id(app, out_dev);
217                 if (gid < 0) {
218                         NL_SET_ERR_MSG_MOD(extack, "invalid entry: cannot find group id for LAG action");
219                         return gid;
220                 }
221                 output->port = cpu_to_be32(NFP_FL_LAG_OUT | gid);
222         } else if (nfp_flower_internal_port_can_offload(app, out_dev)) {
223                 if (!(priv->flower_ext_feats & NFP_FL_FEATS_PRE_TUN_RULES) &&
224                     !(priv->flower_ext_feats & NFP_FL_FEATS_DECAP_V2)) {
225                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: pre-tunnel rules not supported in loaded firmware");
226                         return -EOPNOTSUPP;
227                 }
228
229                 if (nfp_flow->pre_tun_rule.dev || !pkt_host) {
230                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: pre-tunnel rules require single egress dev and ptype HOST action");
231                         return -EOPNOTSUPP;
232                 }
233
234                 nfp_flow->pre_tun_rule.dev = out_dev;
235
236                 return 0;
237         } else {
238                 /* Set action output parameters. */
239                 output->flags = cpu_to_be16(tmp_flags);
240
241                 if (nfp_netdev_is_nfp_repr(in_dev)) {
242                         /* Confirm ingress and egress are on same device. */
243                         if (!netdev_port_same_parent_id(in_dev, out_dev)) {
244                                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: ingress and egress interfaces are on different devices");
245                                 return -EOPNOTSUPP;
246                         }
247                 }
248
249                 if (!nfp_netdev_is_nfp_repr(out_dev)) {
250                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: egress interface is not an nfp port");
251                         return -EOPNOTSUPP;
252                 }
253
254                 output->port = cpu_to_be32(nfp_repr_get_port_id(out_dev));
255                 if (!output->port) {
256                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid port id for egress interface");
257                         return -EOPNOTSUPP;
258                 }
259         }
260         nfp_flow->meta.shortcut = output->port;
261
262         return 0;
263 }
264
265 static bool
266 nfp_flower_tun_is_gre(struct flow_rule *rule, int start_idx)
267 {
268         struct flow_action_entry *act = rule->action.entries;
269         int num_act = rule->action.num_entries;
270         int act_idx;
271
272         /* Preparse action list for next mirred or redirect action */
273         for (act_idx = start_idx + 1; act_idx < num_act; act_idx++)
274                 if (act[act_idx].id == FLOW_ACTION_REDIRECT ||
275                     act[act_idx].id == FLOW_ACTION_MIRRED)
276                         return netif_is_gretap(act[act_idx].dev) ||
277                                netif_is_ip6gretap(act[act_idx].dev);
278
279         return false;
280 }
281
282 static enum nfp_flower_tun_type
283 nfp_fl_get_tun_from_act(struct nfp_app *app,
284                         struct flow_rule *rule,
285                         const struct flow_action_entry *act, int act_idx)
286 {
287         const struct ip_tunnel_info *tun = act->tunnel;
288         struct nfp_flower_priv *priv = app->priv;
289
290         /* Determine the tunnel type based on the egress netdev
291          * in the mirred action for tunnels without l4.
292          */
293         if (nfp_flower_tun_is_gre(rule, act_idx))
294                 return NFP_FL_TUNNEL_GRE;
295
296         switch (tun->key.tp_dst) {
297         case htons(IANA_VXLAN_UDP_PORT):
298                 return NFP_FL_TUNNEL_VXLAN;
299         case htons(GENEVE_UDP_PORT):
300                 if (priv->flower_ext_feats & NFP_FL_FEATS_GENEVE)
301                         return NFP_FL_TUNNEL_GENEVE;
302                 fallthrough;
303         default:
304                 return NFP_FL_TUNNEL_NONE;
305         }
306 }
307
308 static struct nfp_fl_pre_tunnel *nfp_fl_pre_tunnel(char *act_data, int act_len)
309 {
310         size_t act_size = sizeof(struct nfp_fl_pre_tunnel);
311         struct nfp_fl_pre_tunnel *pre_tun_act;
312
313         /* Pre_tunnel action must be first on action list.
314          * If other actions already exist they need to be pushed forward.
315          */
316         if (act_len)
317                 memmove(act_data + act_size, act_data, act_len);
318
319         pre_tun_act = (struct nfp_fl_pre_tunnel *)act_data;
320
321         memset(pre_tun_act, 0, act_size);
322
323         pre_tun_act->head.jump_id = NFP_FL_ACTION_OPCODE_PRE_TUNNEL;
324         pre_tun_act->head.len_lw = act_size >> NFP_FL_LW_SIZ;
325
326         return pre_tun_act;
327 }
328
329 static int
330 nfp_fl_push_geneve_options(struct nfp_fl_payload *nfp_fl, int *list_len,
331                            const struct flow_action_entry *act,
332                            struct netlink_ext_ack *extack)
333 {
334         struct ip_tunnel_info *ip_tun = (struct ip_tunnel_info *)act->tunnel;
335         int opt_len, opt_cnt, act_start, tot_push_len;
336         u8 *src = ip_tunnel_info_opts(ip_tun);
337
338         /* We need to populate the options in reverse order for HW.
339          * Therefore we go through the options, calculating the
340          * number of options and the total size, then we populate
341          * them in reverse order in the action list.
342          */
343         opt_cnt = 0;
344         tot_push_len = 0;
345         opt_len = ip_tun->options_len;
346         while (opt_len > 0) {
347                 struct geneve_opt *opt = (struct geneve_opt *)src;
348
349                 opt_cnt++;
350                 if (opt_cnt > NFP_FL_MAX_GENEVE_OPT_CNT) {
351                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed number of geneve options exceeded");
352                         return -EOPNOTSUPP;
353                 }
354
355                 tot_push_len += sizeof(struct nfp_fl_push_geneve) +
356                                opt->length * 4;
357                 if (tot_push_len > NFP_FL_MAX_GENEVE_OPT_ACT) {
358                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed action list size exceeded at push geneve options");
359                         return -EOPNOTSUPP;
360                 }
361
362                 opt_len -= sizeof(struct geneve_opt) + opt->length * 4;
363                 src += sizeof(struct geneve_opt) + opt->length * 4;
364         }
365
366         if (*list_len + tot_push_len > NFP_FL_MAX_A_SIZ) {
367                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed action list size exceeded at push geneve options");
368                 return -EOPNOTSUPP;
369         }
370
371         act_start = *list_len;
372         *list_len += tot_push_len;
373         src = ip_tunnel_info_opts(ip_tun);
374         while (opt_cnt) {
375                 struct geneve_opt *opt = (struct geneve_opt *)src;
376                 struct nfp_fl_push_geneve *push;
377                 size_t act_size, len;
378
379                 opt_cnt--;
380                 act_size = sizeof(struct nfp_fl_push_geneve) + opt->length * 4;
381                 tot_push_len -= act_size;
382                 len = act_start + tot_push_len;
383
384                 push = (struct nfp_fl_push_geneve *)&nfp_fl->action_data[len];
385                 push->head.jump_id = NFP_FL_ACTION_OPCODE_PUSH_GENEVE;
386                 push->head.len_lw = act_size >> NFP_FL_LW_SIZ;
387                 push->reserved = 0;
388                 push->class = opt->opt_class;
389                 push->type = opt->type;
390                 push->length = opt->length;
391                 memcpy(&push->opt_data, opt->opt_data, opt->length * 4);
392
393                 src += sizeof(struct geneve_opt) + opt->length * 4;
394         }
395
396         return 0;
397 }
398
399 static int
400 nfp_fl_set_tun(struct nfp_app *app, struct nfp_fl_set_tun *set_tun,
401                const struct flow_action_entry *act,
402                struct nfp_fl_pre_tunnel *pre_tun,
403                enum nfp_flower_tun_type tun_type,
404                struct net_device *netdev, struct netlink_ext_ack *extack)
405 {
406         const struct ip_tunnel_info *ip_tun = act->tunnel;
407         bool ipv6 = ip_tunnel_info_af(ip_tun) == AF_INET6;
408         size_t act_size = sizeof(struct nfp_fl_set_tun);
409         struct nfp_flower_priv *priv = app->priv;
410         u32 tmp_set_ip_tun_type_index = 0;
411         /* Currently support one pre-tunnel so index is always 0. */
412         int pretun_idx = 0;
413
414         if (!IS_ENABLED(CONFIG_IPV6) && ipv6)
415                 return -EOPNOTSUPP;
416
417         if (ipv6 && !(priv->flower_ext_feats & NFP_FL_FEATS_IPV6_TUN))
418                 return -EOPNOTSUPP;
419
420         BUILD_BUG_ON(NFP_FL_TUNNEL_CSUM != TUNNEL_CSUM ||
421                      NFP_FL_TUNNEL_KEY  != TUNNEL_KEY ||
422                      NFP_FL_TUNNEL_GENEVE_OPT != TUNNEL_GENEVE_OPT);
423         if (ip_tun->options_len &&
424             (tun_type != NFP_FL_TUNNEL_GENEVE ||
425             !(priv->flower_ext_feats & NFP_FL_FEATS_GENEVE_OPT))) {
426                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: loaded firmware does not support geneve options offload");
427                 return -EOPNOTSUPP;
428         }
429
430         set_tun->head.jump_id = NFP_FL_ACTION_OPCODE_SET_TUNNEL;
431         set_tun->head.len_lw = act_size >> NFP_FL_LW_SIZ;
432
433         /* Set tunnel type and pre-tunnel index. */
434         tmp_set_ip_tun_type_index |=
435                 FIELD_PREP(NFP_FL_TUNNEL_TYPE, tun_type) |
436                 FIELD_PREP(NFP_FL_PRE_TUN_INDEX, pretun_idx);
437
438         set_tun->tun_type_index = cpu_to_be32(tmp_set_ip_tun_type_index);
439         set_tun->tun_id = ip_tun->key.tun_id;
440
441         if (ip_tun->key.ttl) {
442                 set_tun->ttl = ip_tun->key.ttl;
443 #ifdef CONFIG_IPV6
444         } else if (ipv6) {
445                 struct net *net = dev_net(netdev);
446                 struct flowi6 flow = {};
447                 struct dst_entry *dst;
448
449                 flow.daddr = ip_tun->key.u.ipv6.dst;
450                 flow.flowi4_proto = IPPROTO_UDP;
451                 dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &flow, NULL);
452                 if (!IS_ERR(dst)) {
453                         set_tun->ttl = ip6_dst_hoplimit(dst);
454                         dst_release(dst);
455                 } else {
456                         set_tun->ttl = net->ipv6.devconf_all->hop_limit;
457                 }
458 #endif
459         } else {
460                 struct net *net = dev_net(netdev);
461                 struct flowi4 flow = {};
462                 struct rtable *rt;
463                 int err;
464
465                 /* Do a route lookup to determine ttl - if fails then use
466                  * default. Note that CONFIG_INET is a requirement of
467                  * CONFIG_NET_SWITCHDEV so must be defined here.
468                  */
469                 flow.daddr = ip_tun->key.u.ipv4.dst;
470                 flow.flowi4_proto = IPPROTO_UDP;
471                 rt = ip_route_output_key(net, &flow);
472                 err = PTR_ERR_OR_ZERO(rt);
473                 if (!err) {
474                         set_tun->ttl = ip4_dst_hoplimit(&rt->dst);
475                         ip_rt_put(rt);
476                 } else {
477                         set_tun->ttl = net->ipv4.sysctl_ip_default_ttl;
478                 }
479         }
480
481         set_tun->tos = ip_tun->key.tos;
482
483         if (!(ip_tun->key.tun_flags & NFP_FL_TUNNEL_KEY) ||
484             ip_tun->key.tun_flags & ~NFP_FL_SUPPORTED_UDP_TUN_FLAGS) {
485                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: loaded firmware does not support tunnel flag offload");
486                 return -EOPNOTSUPP;
487         }
488         set_tun->tun_flags = ip_tun->key.tun_flags;
489
490         if (tun_type == NFP_FL_TUNNEL_GENEVE) {
491                 set_tun->tun_proto = htons(ETH_P_TEB);
492                 set_tun->tun_len = ip_tun->options_len / 4;
493         }
494
495         /* Complete pre_tunnel action. */
496         if (ipv6) {
497                 pre_tun->flags |= cpu_to_be16(NFP_FL_PRE_TUN_IPV6);
498                 pre_tun->ipv6_dst = ip_tun->key.u.ipv6.dst;
499         } else {
500                 pre_tun->ipv4_dst = ip_tun->key.u.ipv4.dst;
501         }
502
503         return 0;
504 }
505
506 static void nfp_fl_set_helper32(u32 value, u32 mask, u8 *p_exact, u8 *p_mask)
507 {
508         u32 oldvalue = get_unaligned((u32 *)p_exact);
509         u32 oldmask = get_unaligned((u32 *)p_mask);
510
511         value &= mask;
512         value |= oldvalue & ~mask;
513
514         put_unaligned(oldmask | mask, (u32 *)p_mask);
515         put_unaligned(value, (u32 *)p_exact);
516 }
517
518 static int
519 nfp_fl_set_eth(const struct flow_action_entry *act, u32 off,
520                struct nfp_fl_set_eth *set_eth, struct netlink_ext_ack *extack)
521 {
522         u32 exact, mask;
523
524         if (off + 4 > ETH_ALEN * 2) {
525                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid pedit ethernet action");
526                 return -EOPNOTSUPP;
527         }
528
529         mask = ~act->mangle.mask;
530         exact = act->mangle.val;
531
532         if (exact & ~mask) {
533                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid pedit ethernet action");
534                 return -EOPNOTSUPP;
535         }
536
537         nfp_fl_set_helper32(exact, mask, &set_eth->eth_addr_val[off],
538                             &set_eth->eth_addr_mask[off]);
539
540         set_eth->reserved = cpu_to_be16(0);
541         set_eth->head.jump_id = NFP_FL_ACTION_OPCODE_SET_ETHERNET;
542         set_eth->head.len_lw = sizeof(*set_eth) >> NFP_FL_LW_SIZ;
543
544         return 0;
545 }
546
547 struct ipv4_ttl_word {
548         __u8    ttl;
549         __u8    protocol;
550         __sum16 check;
551 };
552
553 static int
554 nfp_fl_set_ip4(const struct flow_action_entry *act, u32 off,
555                struct nfp_fl_set_ip4_addrs *set_ip_addr,
556                struct nfp_fl_set_ip4_ttl_tos *set_ip_ttl_tos,
557                struct netlink_ext_ack *extack)
558 {
559         struct ipv4_ttl_word *ttl_word_mask;
560         struct ipv4_ttl_word *ttl_word;
561         struct iphdr *tos_word_mask;
562         struct iphdr *tos_word;
563         __be32 exact, mask;
564
565         /* We are expecting tcf_pedit to return a big endian value */
566         mask = (__force __be32)~act->mangle.mask;
567         exact = (__force __be32)act->mangle.val;
568
569         if (exact & ~mask) {
570                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid pedit IPv4 action");
571                 return -EOPNOTSUPP;
572         }
573
574         switch (off) {
575         case offsetof(struct iphdr, daddr):
576                 set_ip_addr->ipv4_dst_mask |= mask;
577                 set_ip_addr->ipv4_dst &= ~mask;
578                 set_ip_addr->ipv4_dst |= exact & mask;
579                 set_ip_addr->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS;
580                 set_ip_addr->head.len_lw = sizeof(*set_ip_addr) >>
581                                            NFP_FL_LW_SIZ;
582                 break;
583         case offsetof(struct iphdr, saddr):
584                 set_ip_addr->ipv4_src_mask |= mask;
585                 set_ip_addr->ipv4_src &= ~mask;
586                 set_ip_addr->ipv4_src |= exact & mask;
587                 set_ip_addr->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS;
588                 set_ip_addr->head.len_lw = sizeof(*set_ip_addr) >>
589                                            NFP_FL_LW_SIZ;
590                 break;
591         case offsetof(struct iphdr, ttl):
592                 ttl_word_mask = (struct ipv4_ttl_word *)&mask;
593                 ttl_word = (struct ipv4_ttl_word *)&exact;
594
595                 if (ttl_word_mask->protocol || ttl_word_mask->check) {
596                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid pedit IPv4 ttl action");
597                         return -EOPNOTSUPP;
598                 }
599
600                 set_ip_ttl_tos->ipv4_ttl_mask |= ttl_word_mask->ttl;
601                 set_ip_ttl_tos->ipv4_ttl &= ~ttl_word_mask->ttl;
602                 set_ip_ttl_tos->ipv4_ttl |= ttl_word->ttl & ttl_word_mask->ttl;
603                 set_ip_ttl_tos->head.jump_id =
604                         NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS;
605                 set_ip_ttl_tos->head.len_lw = sizeof(*set_ip_ttl_tos) >>
606                                               NFP_FL_LW_SIZ;
607                 break;
608         case round_down(offsetof(struct iphdr, tos), 4):
609                 tos_word_mask = (struct iphdr *)&mask;
610                 tos_word = (struct iphdr *)&exact;
611
612                 if (tos_word_mask->version || tos_word_mask->ihl ||
613                     tos_word_mask->tot_len) {
614                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid pedit IPv4 tos action");
615                         return -EOPNOTSUPP;
616                 }
617
618                 set_ip_ttl_tos->ipv4_tos_mask |= tos_word_mask->tos;
619                 set_ip_ttl_tos->ipv4_tos &= ~tos_word_mask->tos;
620                 set_ip_ttl_tos->ipv4_tos |= tos_word->tos & tos_word_mask->tos;
621                 set_ip_ttl_tos->head.jump_id =
622                         NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS;
623                 set_ip_ttl_tos->head.len_lw = sizeof(*set_ip_ttl_tos) >>
624                                               NFP_FL_LW_SIZ;
625                 break;
626         default:
627                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: pedit on unsupported section of IPv4 header");
628                 return -EOPNOTSUPP;
629         }
630
631         return 0;
632 }
633
634 static void
635 nfp_fl_set_ip6_helper(int opcode_tag, u8 word, __be32 exact, __be32 mask,
636                       struct nfp_fl_set_ipv6_addr *ip6)
637 {
638         ip6->ipv6[word].mask |= mask;
639         ip6->ipv6[word].exact &= ~mask;
640         ip6->ipv6[word].exact |= exact & mask;
641
642         ip6->reserved = cpu_to_be16(0);
643         ip6->head.jump_id = opcode_tag;
644         ip6->head.len_lw = sizeof(*ip6) >> NFP_FL_LW_SIZ;
645 }
646
647 struct ipv6_hop_limit_word {
648         __be16 payload_len;
649         u8 nexthdr;
650         u8 hop_limit;
651 };
652
653 static int
654 nfp_fl_set_ip6_hop_limit_flow_label(u32 off, __be32 exact, __be32 mask,
655                                     struct nfp_fl_set_ipv6_tc_hl_fl *ip_hl_fl,
656                                     struct netlink_ext_ack *extack)
657 {
658         struct ipv6_hop_limit_word *fl_hl_mask;
659         struct ipv6_hop_limit_word *fl_hl;
660
661         switch (off) {
662         case offsetof(struct ipv6hdr, payload_len):
663                 fl_hl_mask = (struct ipv6_hop_limit_word *)&mask;
664                 fl_hl = (struct ipv6_hop_limit_word *)&exact;
665
666                 if (fl_hl_mask->nexthdr || fl_hl_mask->payload_len) {
667                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid pedit IPv6 hop limit action");
668                         return -EOPNOTSUPP;
669                 }
670
671                 ip_hl_fl->ipv6_hop_limit_mask |= fl_hl_mask->hop_limit;
672                 ip_hl_fl->ipv6_hop_limit &= ~fl_hl_mask->hop_limit;
673                 ip_hl_fl->ipv6_hop_limit |= fl_hl->hop_limit &
674                                             fl_hl_mask->hop_limit;
675                 break;
676         case round_down(offsetof(struct ipv6hdr, flow_lbl), 4):
677                 if (mask & ~IPV6_FLOWINFO_MASK ||
678                     exact & ~IPV6_FLOWINFO_MASK) {
679                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid pedit IPv6 flow info action");
680                         return -EOPNOTSUPP;
681                 }
682
683                 ip_hl_fl->ipv6_label_mask |= mask;
684                 ip_hl_fl->ipv6_label &= ~mask;
685                 ip_hl_fl->ipv6_label |= exact & mask;
686                 break;
687         }
688
689         ip_hl_fl->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV6_TC_HL_FL;
690         ip_hl_fl->head.len_lw = sizeof(*ip_hl_fl) >> NFP_FL_LW_SIZ;
691
692         return 0;
693 }
694
695 static int
696 nfp_fl_set_ip6(const struct flow_action_entry *act, u32 off,
697                struct nfp_fl_set_ipv6_addr *ip_dst,
698                struct nfp_fl_set_ipv6_addr *ip_src,
699                struct nfp_fl_set_ipv6_tc_hl_fl *ip_hl_fl,
700                struct netlink_ext_ack *extack)
701 {
702         __be32 exact, mask;
703         int err = 0;
704         u8 word;
705
706         /* We are expecting tcf_pedit to return a big endian value */
707         mask = (__force __be32)~act->mangle.mask;
708         exact = (__force __be32)act->mangle.val;
709
710         if (exact & ~mask) {
711                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid pedit IPv6 action");
712                 return -EOPNOTSUPP;
713         }
714
715         if (off < offsetof(struct ipv6hdr, saddr)) {
716                 err = nfp_fl_set_ip6_hop_limit_flow_label(off, exact, mask,
717                                                           ip_hl_fl, extack);
718         } else if (off < offsetof(struct ipv6hdr, daddr)) {
719                 word = (off - offsetof(struct ipv6hdr, saddr)) / sizeof(exact);
720                 nfp_fl_set_ip6_helper(NFP_FL_ACTION_OPCODE_SET_IPV6_SRC, word,
721                                       exact, mask, ip_src);
722         } else if (off < offsetof(struct ipv6hdr, daddr) +
723                        sizeof(struct in6_addr)) {
724                 word = (off - offsetof(struct ipv6hdr, daddr)) / sizeof(exact);
725                 nfp_fl_set_ip6_helper(NFP_FL_ACTION_OPCODE_SET_IPV6_DST, word,
726                                       exact, mask, ip_dst);
727         } else {
728                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: pedit on unsupported section of IPv6 header");
729                 return -EOPNOTSUPP;
730         }
731
732         return err;
733 }
734
735 static int
736 nfp_fl_set_tport(const struct flow_action_entry *act, u32 off,
737                  struct nfp_fl_set_tport *set_tport, int opcode,
738                  struct netlink_ext_ack *extack)
739 {
740         u32 exact, mask;
741
742         if (off) {
743                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: pedit on unsupported section of L4 header");
744                 return -EOPNOTSUPP;
745         }
746
747         mask = ~act->mangle.mask;
748         exact = act->mangle.val;
749
750         if (exact & ~mask) {
751                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid pedit L4 action");
752                 return -EOPNOTSUPP;
753         }
754
755         nfp_fl_set_helper32(exact, mask, set_tport->tp_port_val,
756                             set_tport->tp_port_mask);
757
758         set_tport->reserved = cpu_to_be16(0);
759         set_tport->head.jump_id = opcode;
760         set_tport->head.len_lw = sizeof(*set_tport) >> NFP_FL_LW_SIZ;
761
762         return 0;
763 }
764
765 static u32 nfp_fl_csum_l4_to_flag(u8 ip_proto)
766 {
767         switch (ip_proto) {
768         case 0:
769                 /* Filter doesn't force proto match,
770                  * both TCP and UDP will be updated if encountered
771                  */
772                 return TCA_CSUM_UPDATE_FLAG_TCP | TCA_CSUM_UPDATE_FLAG_UDP;
773         case IPPROTO_TCP:
774                 return TCA_CSUM_UPDATE_FLAG_TCP;
775         case IPPROTO_UDP:
776                 return TCA_CSUM_UPDATE_FLAG_UDP;
777         default:
778                 /* All other protocols will be ignored by FW */
779                 return 0;
780         }
781 }
782
783 struct nfp_flower_pedit_acts {
784         struct nfp_fl_set_ipv6_addr set_ip6_dst, set_ip6_src;
785         struct nfp_fl_set_ipv6_tc_hl_fl set_ip6_tc_hl_fl;
786         struct nfp_fl_set_ip4_ttl_tos set_ip_ttl_tos;
787         struct nfp_fl_set_ip4_addrs set_ip_addr;
788         struct nfp_fl_set_tport set_tport;
789         struct nfp_fl_set_eth set_eth;
790 };
791
792 static int
793 nfp_fl_commit_mangle(struct flow_rule *rule, char *nfp_action,
794                      int *a_len, struct nfp_flower_pedit_acts *set_act,
795                      u32 *csum_updated)
796 {
797         size_t act_size = 0;
798         u8 ip_proto = 0;
799
800         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
801                 struct flow_match_basic match;
802
803                 flow_rule_match_basic(rule, &match);
804                 ip_proto = match.key->ip_proto;
805         }
806
807         if (set_act->set_eth.head.len_lw) {
808                 act_size = sizeof(set_act->set_eth);
809                 memcpy(nfp_action, &set_act->set_eth, act_size);
810                 *a_len += act_size;
811         }
812
813         if (set_act->set_ip_ttl_tos.head.len_lw) {
814                 nfp_action += act_size;
815                 act_size = sizeof(set_act->set_ip_ttl_tos);
816                 memcpy(nfp_action, &set_act->set_ip_ttl_tos, act_size);
817                 *a_len += act_size;
818
819                 /* Hardware will automatically fix IPv4 and TCP/UDP checksum. */
820                 *csum_updated |= TCA_CSUM_UPDATE_FLAG_IPV4HDR |
821                                 nfp_fl_csum_l4_to_flag(ip_proto);
822         }
823
824         if (set_act->set_ip_addr.head.len_lw) {
825                 nfp_action += act_size;
826                 act_size = sizeof(set_act->set_ip_addr);
827                 memcpy(nfp_action, &set_act->set_ip_addr, act_size);
828                 *a_len += act_size;
829
830                 /* Hardware will automatically fix IPv4 and TCP/UDP checksum. */
831                 *csum_updated |= TCA_CSUM_UPDATE_FLAG_IPV4HDR |
832                                 nfp_fl_csum_l4_to_flag(ip_proto);
833         }
834
835         if (set_act->set_ip6_tc_hl_fl.head.len_lw) {
836                 nfp_action += act_size;
837                 act_size = sizeof(set_act->set_ip6_tc_hl_fl);
838                 memcpy(nfp_action, &set_act->set_ip6_tc_hl_fl, act_size);
839                 *a_len += act_size;
840
841                 /* Hardware will automatically fix TCP/UDP checksum. */
842                 *csum_updated |= nfp_fl_csum_l4_to_flag(ip_proto);
843         }
844
845         if (set_act->set_ip6_dst.head.len_lw &&
846             set_act->set_ip6_src.head.len_lw) {
847                 /* TC compiles set src and dst IPv6 address as a single action,
848                  * the hardware requires this to be 2 separate actions.
849                  */
850                 nfp_action += act_size;
851                 act_size = sizeof(set_act->set_ip6_src);
852                 memcpy(nfp_action, &set_act->set_ip6_src, act_size);
853                 *a_len += act_size;
854
855                 act_size = sizeof(set_act->set_ip6_dst);
856                 memcpy(&nfp_action[sizeof(set_act->set_ip6_src)],
857                        &set_act->set_ip6_dst, act_size);
858                 *a_len += act_size;
859
860                 /* Hardware will automatically fix TCP/UDP checksum. */
861                 *csum_updated |= nfp_fl_csum_l4_to_flag(ip_proto);
862         } else if (set_act->set_ip6_dst.head.len_lw) {
863                 nfp_action += act_size;
864                 act_size = sizeof(set_act->set_ip6_dst);
865                 memcpy(nfp_action, &set_act->set_ip6_dst, act_size);
866                 *a_len += act_size;
867
868                 /* Hardware will automatically fix TCP/UDP checksum. */
869                 *csum_updated |= nfp_fl_csum_l4_to_flag(ip_proto);
870         } else if (set_act->set_ip6_src.head.len_lw) {
871                 nfp_action += act_size;
872                 act_size = sizeof(set_act->set_ip6_src);
873                 memcpy(nfp_action, &set_act->set_ip6_src, act_size);
874                 *a_len += act_size;
875
876                 /* Hardware will automatically fix TCP/UDP checksum. */
877                 *csum_updated |= nfp_fl_csum_l4_to_flag(ip_proto);
878         }
879         if (set_act->set_tport.head.len_lw) {
880                 nfp_action += act_size;
881                 act_size = sizeof(set_act->set_tport);
882                 memcpy(nfp_action, &set_act->set_tport, act_size);
883                 *a_len += act_size;
884
885                 /* Hardware will automatically fix TCP/UDP checksum. */
886                 *csum_updated |= nfp_fl_csum_l4_to_flag(ip_proto);
887         }
888
889         return 0;
890 }
891
892 static int
893 nfp_fl_pedit(const struct flow_action_entry *act,
894              char *nfp_action, int *a_len,
895              u32 *csum_updated, struct nfp_flower_pedit_acts *set_act,
896              struct netlink_ext_ack *extack)
897 {
898         enum flow_action_mangle_base htype;
899         u32 offset;
900
901         htype = act->mangle.htype;
902         offset = act->mangle.offset;
903
904         switch (htype) {
905         case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH:
906                 return nfp_fl_set_eth(act, offset, &set_act->set_eth, extack);
907         case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4:
908                 return nfp_fl_set_ip4(act, offset, &set_act->set_ip_addr,
909                                       &set_act->set_ip_ttl_tos, extack);
910         case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6:
911                 return nfp_fl_set_ip6(act, offset, &set_act->set_ip6_dst,
912                                       &set_act->set_ip6_src,
913                                       &set_act->set_ip6_tc_hl_fl, extack);
914         case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP:
915                 return nfp_fl_set_tport(act, offset, &set_act->set_tport,
916                                         NFP_FL_ACTION_OPCODE_SET_TCP, extack);
917         case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP:
918                 return nfp_fl_set_tport(act, offset, &set_act->set_tport,
919                                         NFP_FL_ACTION_OPCODE_SET_UDP, extack);
920         default:
921                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: pedit on unsupported header");
922                 return -EOPNOTSUPP;
923         }
924 }
925
926 static struct nfp_fl_meter *nfp_fl_meter(char *act_data)
927 {
928         size_t act_size = sizeof(struct nfp_fl_meter);
929         struct nfp_fl_meter *meter_act;
930
931         meter_act = (struct nfp_fl_meter *)act_data;
932
933         memset(meter_act, 0, act_size);
934
935         meter_act->head.jump_id = NFP_FL_ACTION_OPCODE_METER;
936         meter_act->head.len_lw = act_size >> NFP_FL_LW_SIZ;
937
938         return meter_act;
939 }
940
941 static int
942 nfp_flower_meter_action(struct nfp_app *app,
943                         const struct flow_action_entry *action,
944                         struct nfp_fl_payload *nfp_fl, int *a_len,
945                         struct net_device *netdev,
946                         struct netlink_ext_ack *extack)
947 {
948         struct nfp_fl_meter *fl_meter;
949         u32 meter_id;
950
951         if (*a_len + sizeof(struct nfp_fl_meter) > NFP_FL_MAX_A_SIZ) {
952                 NL_SET_ERR_MSG_MOD(extack,
953                                    "unsupported offload:meter action size beyond the allowed maximum");
954                 return -EOPNOTSUPP;
955         }
956
957         meter_id = action->hw_index;
958         if (!nfp_flower_search_meter_entry(app, meter_id)) {
959                 NL_SET_ERR_MSG_MOD(extack,
960                                    "can not offload flow table with unsupported police action.");
961                 return -EOPNOTSUPP;
962         }
963
964         fl_meter = nfp_fl_meter(&nfp_fl->action_data[*a_len]);
965         *a_len += sizeof(struct nfp_fl_meter);
966         fl_meter->meter_id = cpu_to_be32(meter_id);
967
968         return 0;
969 }
970
971 static int
972 nfp_flower_output_action(struct nfp_app *app,
973                          const struct flow_action_entry *act,
974                          struct nfp_fl_payload *nfp_fl, int *a_len,
975                          struct net_device *netdev, bool last,
976                          enum nfp_flower_tun_type *tun_type, int *tun_out_cnt,
977                          int *out_cnt, u32 *csum_updated, bool pkt_host,
978                          struct netlink_ext_ack *extack)
979 {
980         struct nfp_flower_priv *priv = app->priv;
981         struct nfp_fl_output *output;
982         int err, prelag_size;
983
984         /* If csum_updated has not been reset by now, it means HW will
985          * incorrectly update csums when they are not requested.
986          */
987         if (*csum_updated) {
988                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: set actions without updating checksums are not supported");
989                 return -EOPNOTSUPP;
990         }
991
992         if (*a_len + sizeof(struct nfp_fl_output) > NFP_FL_MAX_A_SIZ) {
993                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: mirred output increases action list size beyond the allowed maximum");
994                 return -EOPNOTSUPP;
995         }
996
997         output = (struct nfp_fl_output *)&nfp_fl->action_data[*a_len];
998         err = nfp_fl_output(app, output, act, nfp_fl, last, netdev, *tun_type,
999                             tun_out_cnt, pkt_host, extack);
1000         if (err)
1001                 return err;
1002
1003         *a_len += sizeof(struct nfp_fl_output);
1004
1005         if (priv->flower_en_feats & NFP_FL_ENABLE_LAG) {
1006                 /* nfp_fl_pre_lag returns -err or size of prelag action added.
1007                  * This will be 0 if it is not egressing to a lag dev.
1008                  */
1009                 prelag_size = nfp_fl_pre_lag(app, act, nfp_fl, *a_len, extack);
1010                 if (prelag_size < 0) {
1011                         return prelag_size;
1012                 } else if (prelag_size > 0 && (!last || *out_cnt)) {
1013                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: LAG action has to be last action in action list");
1014                         return -EOPNOTSUPP;
1015                 }
1016
1017                 *a_len += prelag_size;
1018         }
1019         (*out_cnt)++;
1020
1021         return 0;
1022 }
1023
1024 static int
1025 nfp_flower_loop_action(struct nfp_app *app, const struct flow_action_entry *act,
1026                        struct flow_rule *rule,
1027                        struct nfp_fl_payload *nfp_fl, int *a_len,
1028                        struct net_device *netdev,
1029                        enum nfp_flower_tun_type *tun_type, int *tun_out_cnt,
1030                        int *out_cnt, u32 *csum_updated,
1031                        struct nfp_flower_pedit_acts *set_act, bool *pkt_host,
1032                        struct netlink_ext_ack *extack, int act_idx)
1033 {
1034         struct nfp_flower_priv *fl_priv = app->priv;
1035         struct nfp_fl_pre_tunnel *pre_tun;
1036         struct nfp_fl_set_tun *set_tun;
1037         struct nfp_fl_push_vlan *psh_v;
1038         struct nfp_fl_push_mpls *psh_m;
1039         struct nfp_fl_pop_vlan *pop_v;
1040         struct nfp_fl_pop_mpls *pop_m;
1041         struct nfp_fl_set_mpls *set_m;
1042         int err;
1043
1044         switch (act->id) {
1045         case FLOW_ACTION_DROP:
1046                 nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_DROP);
1047                 break;
1048         case FLOW_ACTION_REDIRECT_INGRESS:
1049         case FLOW_ACTION_REDIRECT:
1050                 err = nfp_flower_output_action(app, act, nfp_fl, a_len, netdev,
1051                                                true, tun_type, tun_out_cnt,
1052                                                out_cnt, csum_updated, *pkt_host,
1053                                                extack);
1054                 if (err)
1055                         return err;
1056                 break;
1057         case FLOW_ACTION_MIRRED_INGRESS:
1058         case FLOW_ACTION_MIRRED:
1059                 err = nfp_flower_output_action(app, act, nfp_fl, a_len, netdev,
1060                                                false, tun_type, tun_out_cnt,
1061                                                out_cnt, csum_updated, *pkt_host,
1062                                                extack);
1063                 if (err)
1064                         return err;
1065                 break;
1066         case FLOW_ACTION_VLAN_POP:
1067                 if (*a_len +
1068                     sizeof(struct nfp_fl_pop_vlan) > NFP_FL_MAX_A_SIZ) {
1069                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed action list size exceeded at pop vlan");
1070                         return -EOPNOTSUPP;
1071                 }
1072
1073                 pop_v = (struct nfp_fl_pop_vlan *)&nfp_fl->action_data[*a_len];
1074                 nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_POPV);
1075
1076                 nfp_fl_pop_vlan(pop_v);
1077                 *a_len += sizeof(struct nfp_fl_pop_vlan);
1078                 break;
1079         case FLOW_ACTION_VLAN_PUSH:
1080                 if (*a_len +
1081                     sizeof(struct nfp_fl_push_vlan) > NFP_FL_MAX_A_SIZ) {
1082                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed action list size exceeded at push vlan");
1083                         return -EOPNOTSUPP;
1084                 }
1085
1086                 psh_v = (struct nfp_fl_push_vlan *)&nfp_fl->action_data[*a_len];
1087                 nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL);
1088
1089                 nfp_fl_push_vlan(psh_v, act);
1090                 *a_len += sizeof(struct nfp_fl_push_vlan);
1091                 break;
1092         case FLOW_ACTION_TUNNEL_ENCAP: {
1093                 const struct ip_tunnel_info *ip_tun = act->tunnel;
1094
1095                 *tun_type = nfp_fl_get_tun_from_act(app, rule, act, act_idx);
1096                 if (*tun_type == NFP_FL_TUNNEL_NONE) {
1097                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: unsupported tunnel type in action list");
1098                         return -EOPNOTSUPP;
1099                 }
1100
1101                 if (ip_tun->mode & ~NFP_FL_SUPPORTED_TUNNEL_INFO_FLAGS) {
1102                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: unsupported tunnel flags in action list");
1103                         return -EOPNOTSUPP;
1104                 }
1105
1106                 /* Pre-tunnel action is required for tunnel encap.
1107                  * This checks for next hop entries on NFP.
1108                  * If none, the packet falls back before applying other actions.
1109                  */
1110                 if (*a_len + sizeof(struct nfp_fl_pre_tunnel) +
1111                     sizeof(struct nfp_fl_set_tun) > NFP_FL_MAX_A_SIZ) {
1112                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed action list size exceeded at tunnel encap");
1113                         return -EOPNOTSUPP;
1114                 }
1115
1116                 pre_tun = nfp_fl_pre_tunnel(nfp_fl->action_data, *a_len);
1117                 nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL);
1118                 *a_len += sizeof(struct nfp_fl_pre_tunnel);
1119
1120                 err = nfp_fl_push_geneve_options(nfp_fl, a_len, act, extack);
1121                 if (err)
1122                         return err;
1123
1124                 set_tun = (void *)&nfp_fl->action_data[*a_len];
1125                 err = nfp_fl_set_tun(app, set_tun, act, pre_tun, *tun_type,
1126                                      netdev, extack);
1127                 if (err)
1128                         return err;
1129                 *a_len += sizeof(struct nfp_fl_set_tun);
1130                 }
1131                 break;
1132         case FLOW_ACTION_TUNNEL_DECAP:
1133                 /* Tunnel decap is handled by default so accept action. */
1134                 return 0;
1135         case FLOW_ACTION_MANGLE:
1136                 if (nfp_fl_pedit(act, &nfp_fl->action_data[*a_len],
1137                                  a_len, csum_updated, set_act, extack))
1138                         return -EOPNOTSUPP;
1139                 break;
1140         case FLOW_ACTION_CSUM:
1141                 /* csum action requests recalc of something we have not fixed */
1142                 if (act->csum_flags & ~*csum_updated) {
1143                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: unsupported csum update action in action list");
1144                         return -EOPNOTSUPP;
1145                 }
1146                 /* If we will correctly fix the csum we can remove it from the
1147                  * csum update list. Which will later be used to check support.
1148                  */
1149                 *csum_updated &= ~act->csum_flags;
1150                 break;
1151         case FLOW_ACTION_MPLS_PUSH:
1152                 if (*a_len +
1153                     sizeof(struct nfp_fl_push_mpls) > NFP_FL_MAX_A_SIZ) {
1154                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed action list size exceeded at push MPLS");
1155                         return -EOPNOTSUPP;
1156                 }
1157
1158                 psh_m = (struct nfp_fl_push_mpls *)&nfp_fl->action_data[*a_len];
1159                 nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL);
1160
1161                 err = nfp_fl_push_mpls(psh_m, act, extack);
1162                 if (err)
1163                         return err;
1164                 *a_len += sizeof(struct nfp_fl_push_mpls);
1165                 break;
1166         case FLOW_ACTION_MPLS_POP:
1167                 if (*a_len +
1168                     sizeof(struct nfp_fl_pop_mpls) > NFP_FL_MAX_A_SIZ) {
1169                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed action list size exceeded at pop MPLS");
1170                         return -EOPNOTSUPP;
1171                 }
1172
1173                 pop_m = (struct nfp_fl_pop_mpls *)&nfp_fl->action_data[*a_len];
1174                 nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL);
1175
1176                 nfp_fl_pop_mpls(pop_m, act);
1177                 *a_len += sizeof(struct nfp_fl_pop_mpls);
1178                 break;
1179         case FLOW_ACTION_MPLS_MANGLE:
1180                 if (*a_len +
1181                     sizeof(struct nfp_fl_set_mpls) > NFP_FL_MAX_A_SIZ) {
1182                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed action list size exceeded at set MPLS");
1183                         return -EOPNOTSUPP;
1184                 }
1185
1186                 set_m = (struct nfp_fl_set_mpls *)&nfp_fl->action_data[*a_len];
1187                 nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL);
1188
1189                 nfp_fl_set_mpls(set_m, act);
1190                 *a_len += sizeof(struct nfp_fl_set_mpls);
1191                 break;
1192         case FLOW_ACTION_PTYPE:
1193                 /* TC ptype skbedit sets PACKET_HOST for ingress redirect. */
1194                 if (act->ptype != PACKET_HOST)
1195                         return -EOPNOTSUPP;
1196
1197                 *pkt_host = true;
1198                 break;
1199         case FLOW_ACTION_POLICE:
1200                 if (!(fl_priv->flower_ext_feats & NFP_FL_FEATS_QOS_METER)) {
1201                         NL_SET_ERR_MSG_MOD(extack,
1202                                            "unsupported offload: unsupported police action in action list");
1203                         return -EOPNOTSUPP;
1204                 }
1205
1206                 err = nfp_flower_meter_action(app, act, nfp_fl, a_len, netdev,
1207                                               extack);
1208                 if (err)
1209                         return err;
1210                 break;
1211         default:
1212                 /* Currently we do not handle any other actions. */
1213                 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: unsupported action in action list");
1214                 return -EOPNOTSUPP;
1215         }
1216
1217         return 0;
1218 }
1219
1220 static bool nfp_fl_check_mangle_start(struct flow_action *flow_act,
1221                                       int current_act_idx)
1222 {
1223         struct flow_action_entry current_act;
1224         struct flow_action_entry prev_act;
1225
1226         current_act = flow_act->entries[current_act_idx];
1227         if (current_act.id != FLOW_ACTION_MANGLE)
1228                 return false;
1229
1230         if (current_act_idx == 0)
1231                 return true;
1232
1233         prev_act = flow_act->entries[current_act_idx - 1];
1234
1235         return prev_act.id != FLOW_ACTION_MANGLE;
1236 }
1237
1238 static bool nfp_fl_check_mangle_end(struct flow_action *flow_act,
1239                                     int current_act_idx)
1240 {
1241         struct flow_action_entry current_act;
1242         struct flow_action_entry next_act;
1243
1244         current_act = flow_act->entries[current_act_idx];
1245         if (current_act.id != FLOW_ACTION_MANGLE)
1246                 return false;
1247
1248         if (current_act_idx == flow_act->num_entries)
1249                 return true;
1250
1251         next_act = flow_act->entries[current_act_idx + 1];
1252
1253         return next_act.id != FLOW_ACTION_MANGLE;
1254 }
1255
1256 int nfp_flower_compile_action(struct nfp_app *app,
1257                               struct flow_rule *rule,
1258                               struct net_device *netdev,
1259                               struct nfp_fl_payload *nfp_flow,
1260                               struct netlink_ext_ack *extack)
1261 {
1262         int act_len, act_cnt, err, tun_out_cnt, out_cnt, i;
1263         struct nfp_flower_pedit_acts set_act;
1264         enum nfp_flower_tun_type tun_type;
1265         struct flow_action_entry *act;
1266         bool pkt_host = false;
1267         u32 csum_updated = 0;
1268
1269         if (!flow_action_hw_stats_check(&rule->action, extack,
1270                                         FLOW_ACTION_HW_STATS_DELAYED_BIT))
1271                 return -EOPNOTSUPP;
1272
1273         memset(nfp_flow->action_data, 0, NFP_FL_MAX_A_SIZ);
1274         nfp_flow->meta.act_len = 0;
1275         tun_type = NFP_FL_TUNNEL_NONE;
1276         act_len = 0;
1277         act_cnt = 0;
1278         tun_out_cnt = 0;
1279         out_cnt = 0;
1280
1281         flow_action_for_each(i, act, &rule->action) {
1282                 if (nfp_fl_check_mangle_start(&rule->action, i))
1283                         memset(&set_act, 0, sizeof(set_act));
1284                 err = nfp_flower_loop_action(app, act, rule, nfp_flow, &act_len,
1285                                              netdev, &tun_type, &tun_out_cnt,
1286                                              &out_cnt, &csum_updated,
1287                                              &set_act, &pkt_host, extack, i);
1288                 if (err)
1289                         return err;
1290                 act_cnt++;
1291                 if (nfp_fl_check_mangle_end(&rule->action, i))
1292                         nfp_fl_commit_mangle(rule,
1293                                              &nfp_flow->action_data[act_len],
1294                                              &act_len, &set_act, &csum_updated);
1295         }
1296
1297         /* We optimise when the action list is small, this can unfortunately
1298          * not happen once we have more than one action in the action list.
1299          */
1300         if (act_cnt > 1)
1301                 nfp_flow->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL);
1302
1303         nfp_flow->meta.act_len = act_len;
1304
1305         return 0;
1306 }