1*4882a593Smuzhiyun // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2*4882a593Smuzhiyun /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #include <linux/bitfield.h>
5*4882a593Smuzhiyun #include <net/pkt_cls.h>
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include "cmsg.h"
8*4882a593Smuzhiyun #include "main.h"
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun static void
nfp_flower_compile_meta_tci(struct nfp_flower_meta_tci * ext,struct nfp_flower_meta_tci * msk,struct flow_rule * rule,u8 key_type,bool qinq_sup)11*4882a593Smuzhiyun nfp_flower_compile_meta_tci(struct nfp_flower_meta_tci *ext,
12*4882a593Smuzhiyun struct nfp_flower_meta_tci *msk,
13*4882a593Smuzhiyun struct flow_rule *rule, u8 key_type, bool qinq_sup)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun u16 tmp_tci;
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun memset(ext, 0, sizeof(struct nfp_flower_meta_tci));
18*4882a593Smuzhiyun memset(msk, 0, sizeof(struct nfp_flower_meta_tci));
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /* Populate the metadata frame. */
21*4882a593Smuzhiyun ext->nfp_flow_key_layer = key_type;
22*4882a593Smuzhiyun ext->mask_id = ~0;
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun msk->nfp_flow_key_layer = key_type;
25*4882a593Smuzhiyun msk->mask_id = ~0;
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun if (!qinq_sup && flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
28*4882a593Smuzhiyun struct flow_match_vlan match;
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun flow_rule_match_vlan(rule, &match);
31*4882a593Smuzhiyun /* Populate the tci field. */
32*4882a593Smuzhiyun tmp_tci = NFP_FLOWER_MASK_VLAN_PRESENT;
33*4882a593Smuzhiyun tmp_tci |= FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
34*4882a593Smuzhiyun match.key->vlan_priority) |
35*4882a593Smuzhiyun FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
36*4882a593Smuzhiyun match.key->vlan_id);
37*4882a593Smuzhiyun ext->tci = cpu_to_be16(tmp_tci);
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun tmp_tci = NFP_FLOWER_MASK_VLAN_PRESENT;
40*4882a593Smuzhiyun tmp_tci |= FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
41*4882a593Smuzhiyun match.mask->vlan_priority) |
42*4882a593Smuzhiyun FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
43*4882a593Smuzhiyun match.mask->vlan_id);
44*4882a593Smuzhiyun msk->tci = cpu_to_be16(tmp_tci);
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun static void
nfp_flower_compile_ext_meta(struct nfp_flower_ext_meta * frame,u32 key_ext)49*4882a593Smuzhiyun nfp_flower_compile_ext_meta(struct nfp_flower_ext_meta *frame, u32 key_ext)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun frame->nfp_flow_key_layer2 = cpu_to_be32(key_ext);
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun static int
nfp_flower_compile_port(struct nfp_flower_in_port * frame,u32 cmsg_port,bool mask_version,enum nfp_flower_tun_type tun_type,struct netlink_ext_ack * extack)55*4882a593Smuzhiyun nfp_flower_compile_port(struct nfp_flower_in_port *frame, u32 cmsg_port,
56*4882a593Smuzhiyun bool mask_version, enum nfp_flower_tun_type tun_type,
57*4882a593Smuzhiyun struct netlink_ext_ack *extack)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun if (mask_version) {
60*4882a593Smuzhiyun frame->in_port = cpu_to_be32(~0);
61*4882a593Smuzhiyun return 0;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun if (tun_type) {
65*4882a593Smuzhiyun frame->in_port = cpu_to_be32(NFP_FL_PORT_TYPE_TUN | tun_type);
66*4882a593Smuzhiyun } else {
67*4882a593Smuzhiyun if (!cmsg_port) {
68*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid ingress interface for match offload");
69*4882a593Smuzhiyun return -EOPNOTSUPP;
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun frame->in_port = cpu_to_be32(cmsg_port);
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun return 0;
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun static int
nfp_flower_compile_mac(struct nfp_flower_mac_mpls * ext,struct nfp_flower_mac_mpls * msk,struct flow_rule * rule,struct netlink_ext_ack * extack)78*4882a593Smuzhiyun nfp_flower_compile_mac(struct nfp_flower_mac_mpls *ext,
79*4882a593Smuzhiyun struct nfp_flower_mac_mpls *msk, struct flow_rule *rule,
80*4882a593Smuzhiyun struct netlink_ext_ack *extack)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun memset(ext, 0, sizeof(struct nfp_flower_mac_mpls));
83*4882a593Smuzhiyun memset(msk, 0, sizeof(struct nfp_flower_mac_mpls));
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
86*4882a593Smuzhiyun struct flow_match_eth_addrs match;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun flow_rule_match_eth_addrs(rule, &match);
89*4882a593Smuzhiyun /* Populate mac frame. */
90*4882a593Smuzhiyun ether_addr_copy(ext->mac_dst, &match.key->dst[0]);
91*4882a593Smuzhiyun ether_addr_copy(ext->mac_src, &match.key->src[0]);
92*4882a593Smuzhiyun ether_addr_copy(msk->mac_dst, &match.mask->dst[0]);
93*4882a593Smuzhiyun ether_addr_copy(msk->mac_src, &match.mask->src[0]);
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS)) {
97*4882a593Smuzhiyun struct flow_match_mpls match;
98*4882a593Smuzhiyun u32 t_mpls;
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun flow_rule_match_mpls(rule, &match);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /* Only support matching the first LSE */
103*4882a593Smuzhiyun if (match.mask->used_lses != 1) {
104*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack,
105*4882a593Smuzhiyun "unsupported offload: invalid LSE depth for MPLS match offload");
106*4882a593Smuzhiyun return -EOPNOTSUPP;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB,
110*4882a593Smuzhiyun match.key->ls[0].mpls_label) |
111*4882a593Smuzhiyun FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC,
112*4882a593Smuzhiyun match.key->ls[0].mpls_tc) |
113*4882a593Smuzhiyun FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS,
114*4882a593Smuzhiyun match.key->ls[0].mpls_bos) |
115*4882a593Smuzhiyun NFP_FLOWER_MASK_MPLS_Q;
116*4882a593Smuzhiyun ext->mpls_lse = cpu_to_be32(t_mpls);
117*4882a593Smuzhiyun t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB,
118*4882a593Smuzhiyun match.mask->ls[0].mpls_label) |
119*4882a593Smuzhiyun FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC,
120*4882a593Smuzhiyun match.mask->ls[0].mpls_tc) |
121*4882a593Smuzhiyun FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS,
122*4882a593Smuzhiyun match.mask->ls[0].mpls_bos) |
123*4882a593Smuzhiyun NFP_FLOWER_MASK_MPLS_Q;
124*4882a593Smuzhiyun msk->mpls_lse = cpu_to_be32(t_mpls);
125*4882a593Smuzhiyun } else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
126*4882a593Smuzhiyun /* Check for mpls ether type and set NFP_FLOWER_MASK_MPLS_Q
127*4882a593Smuzhiyun * bit, which indicates an mpls ether type but without any
128*4882a593Smuzhiyun * mpls fields.
129*4882a593Smuzhiyun */
130*4882a593Smuzhiyun struct flow_match_basic match;
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun flow_rule_match_basic(rule, &match);
133*4882a593Smuzhiyun if (match.key->n_proto == cpu_to_be16(ETH_P_MPLS_UC) ||
134*4882a593Smuzhiyun match.key->n_proto == cpu_to_be16(ETH_P_MPLS_MC)) {
135*4882a593Smuzhiyun ext->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q);
136*4882a593Smuzhiyun msk->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q);
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun return 0;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun static void
nfp_flower_compile_tport(struct nfp_flower_tp_ports * ext,struct nfp_flower_tp_ports * msk,struct flow_rule * rule)144*4882a593Smuzhiyun nfp_flower_compile_tport(struct nfp_flower_tp_ports *ext,
145*4882a593Smuzhiyun struct nfp_flower_tp_ports *msk,
146*4882a593Smuzhiyun struct flow_rule *rule)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun memset(ext, 0, sizeof(struct nfp_flower_tp_ports));
149*4882a593Smuzhiyun memset(msk, 0, sizeof(struct nfp_flower_tp_ports));
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
152*4882a593Smuzhiyun struct flow_match_ports match;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun flow_rule_match_ports(rule, &match);
155*4882a593Smuzhiyun ext->port_src = match.key->src;
156*4882a593Smuzhiyun ext->port_dst = match.key->dst;
157*4882a593Smuzhiyun msk->port_src = match.mask->src;
158*4882a593Smuzhiyun msk->port_dst = match.mask->dst;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun static void
nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext * ext,struct nfp_flower_ip_ext * msk,struct flow_rule * rule)163*4882a593Smuzhiyun nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext *ext,
164*4882a593Smuzhiyun struct nfp_flower_ip_ext *msk, struct flow_rule *rule)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
167*4882a593Smuzhiyun struct flow_match_basic match;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun flow_rule_match_basic(rule, &match);
170*4882a593Smuzhiyun ext->proto = match.key->ip_proto;
171*4882a593Smuzhiyun msk->proto = match.mask->ip_proto;
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
175*4882a593Smuzhiyun struct flow_match_ip match;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun flow_rule_match_ip(rule, &match);
178*4882a593Smuzhiyun ext->tos = match.key->tos;
179*4882a593Smuzhiyun ext->ttl = match.key->ttl;
180*4882a593Smuzhiyun msk->tos = match.mask->tos;
181*4882a593Smuzhiyun msk->ttl = match.mask->ttl;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) {
185*4882a593Smuzhiyun u16 tcp_flags, tcp_flags_mask;
186*4882a593Smuzhiyun struct flow_match_tcp match;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun flow_rule_match_tcp(rule, &match);
189*4882a593Smuzhiyun tcp_flags = be16_to_cpu(match.key->flags);
190*4882a593Smuzhiyun tcp_flags_mask = be16_to_cpu(match.mask->flags);
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun if (tcp_flags & TCPHDR_FIN)
193*4882a593Smuzhiyun ext->flags |= NFP_FL_TCP_FLAG_FIN;
194*4882a593Smuzhiyun if (tcp_flags_mask & TCPHDR_FIN)
195*4882a593Smuzhiyun msk->flags |= NFP_FL_TCP_FLAG_FIN;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun if (tcp_flags & TCPHDR_SYN)
198*4882a593Smuzhiyun ext->flags |= NFP_FL_TCP_FLAG_SYN;
199*4882a593Smuzhiyun if (tcp_flags_mask & TCPHDR_SYN)
200*4882a593Smuzhiyun msk->flags |= NFP_FL_TCP_FLAG_SYN;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun if (tcp_flags & TCPHDR_RST)
203*4882a593Smuzhiyun ext->flags |= NFP_FL_TCP_FLAG_RST;
204*4882a593Smuzhiyun if (tcp_flags_mask & TCPHDR_RST)
205*4882a593Smuzhiyun msk->flags |= NFP_FL_TCP_FLAG_RST;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun if (tcp_flags & TCPHDR_PSH)
208*4882a593Smuzhiyun ext->flags |= NFP_FL_TCP_FLAG_PSH;
209*4882a593Smuzhiyun if (tcp_flags_mask & TCPHDR_PSH)
210*4882a593Smuzhiyun msk->flags |= NFP_FL_TCP_FLAG_PSH;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun if (tcp_flags & TCPHDR_URG)
213*4882a593Smuzhiyun ext->flags |= NFP_FL_TCP_FLAG_URG;
214*4882a593Smuzhiyun if (tcp_flags_mask & TCPHDR_URG)
215*4882a593Smuzhiyun msk->flags |= NFP_FL_TCP_FLAG_URG;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
219*4882a593Smuzhiyun struct flow_match_control match;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun flow_rule_match_control(rule, &match);
222*4882a593Smuzhiyun if (match.key->flags & FLOW_DIS_IS_FRAGMENT)
223*4882a593Smuzhiyun ext->flags |= NFP_FL_IP_FRAGMENTED;
224*4882a593Smuzhiyun if (match.mask->flags & FLOW_DIS_IS_FRAGMENT)
225*4882a593Smuzhiyun msk->flags |= NFP_FL_IP_FRAGMENTED;
226*4882a593Smuzhiyun if (match.key->flags & FLOW_DIS_FIRST_FRAG)
227*4882a593Smuzhiyun ext->flags |= NFP_FL_IP_FRAG_FIRST;
228*4882a593Smuzhiyun if (match.mask->flags & FLOW_DIS_FIRST_FRAG)
229*4882a593Smuzhiyun msk->flags |= NFP_FL_IP_FRAG_FIRST;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun static void
nfp_flower_fill_vlan(struct flow_dissector_key_vlan * key,struct nfp_flower_vlan * frame,bool outer_vlan)234*4882a593Smuzhiyun nfp_flower_fill_vlan(struct flow_dissector_key_vlan *key,
235*4882a593Smuzhiyun struct nfp_flower_vlan *frame,
236*4882a593Smuzhiyun bool outer_vlan)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun u16 tci;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun tci = NFP_FLOWER_MASK_VLAN_PRESENT;
241*4882a593Smuzhiyun tci |= FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
242*4882a593Smuzhiyun key->vlan_priority) |
243*4882a593Smuzhiyun FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
244*4882a593Smuzhiyun key->vlan_id);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun if (outer_vlan) {
247*4882a593Smuzhiyun frame->outer_tci = cpu_to_be16(tci);
248*4882a593Smuzhiyun frame->outer_tpid = key->vlan_tpid;
249*4882a593Smuzhiyun } else {
250*4882a593Smuzhiyun frame->inner_tci = cpu_to_be16(tci);
251*4882a593Smuzhiyun frame->inner_tpid = key->vlan_tpid;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun static void
nfp_flower_compile_vlan(struct nfp_flower_vlan * ext,struct nfp_flower_vlan * msk,struct flow_rule * rule)256*4882a593Smuzhiyun nfp_flower_compile_vlan(struct nfp_flower_vlan *ext,
257*4882a593Smuzhiyun struct nfp_flower_vlan *msk,
258*4882a593Smuzhiyun struct flow_rule *rule)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun struct flow_match_vlan match;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun memset(ext, 0, sizeof(struct nfp_flower_vlan));
263*4882a593Smuzhiyun memset(msk, 0, sizeof(struct nfp_flower_vlan));
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
266*4882a593Smuzhiyun flow_rule_match_vlan(rule, &match);
267*4882a593Smuzhiyun nfp_flower_fill_vlan(match.key, ext, true);
268*4882a593Smuzhiyun nfp_flower_fill_vlan(match.mask, msk, true);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) {
271*4882a593Smuzhiyun flow_rule_match_cvlan(rule, &match);
272*4882a593Smuzhiyun nfp_flower_fill_vlan(match.key, ext, false);
273*4882a593Smuzhiyun nfp_flower_fill_vlan(match.mask, msk, false);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun static void
nfp_flower_compile_ipv4(struct nfp_flower_ipv4 * ext,struct nfp_flower_ipv4 * msk,struct flow_rule * rule)278*4882a593Smuzhiyun nfp_flower_compile_ipv4(struct nfp_flower_ipv4 *ext,
279*4882a593Smuzhiyun struct nfp_flower_ipv4 *msk, struct flow_rule *rule)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun struct flow_match_ipv4_addrs match;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun memset(ext, 0, sizeof(struct nfp_flower_ipv4));
284*4882a593Smuzhiyun memset(msk, 0, sizeof(struct nfp_flower_ipv4));
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
287*4882a593Smuzhiyun flow_rule_match_ipv4_addrs(rule, &match);
288*4882a593Smuzhiyun ext->ipv4_src = match.key->src;
289*4882a593Smuzhiyun ext->ipv4_dst = match.key->dst;
290*4882a593Smuzhiyun msk->ipv4_src = match.mask->src;
291*4882a593Smuzhiyun msk->ipv4_dst = match.mask->dst;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun static void
nfp_flower_compile_ipv6(struct nfp_flower_ipv6 * ext,struct nfp_flower_ipv6 * msk,struct flow_rule * rule)298*4882a593Smuzhiyun nfp_flower_compile_ipv6(struct nfp_flower_ipv6 *ext,
299*4882a593Smuzhiyun struct nfp_flower_ipv6 *msk, struct flow_rule *rule)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun memset(ext, 0, sizeof(struct nfp_flower_ipv6));
302*4882a593Smuzhiyun memset(msk, 0, sizeof(struct nfp_flower_ipv6));
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
305*4882a593Smuzhiyun struct flow_match_ipv6_addrs match;
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun flow_rule_match_ipv6_addrs(rule, &match);
308*4882a593Smuzhiyun ext->ipv6_src = match.key->src;
309*4882a593Smuzhiyun ext->ipv6_dst = match.key->dst;
310*4882a593Smuzhiyun msk->ipv6_src = match.mask->src;
311*4882a593Smuzhiyun msk->ipv6_dst = match.mask->dst;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun static int
nfp_flower_compile_geneve_opt(void * ext,void * msk,struct flow_rule * rule)318*4882a593Smuzhiyun nfp_flower_compile_geneve_opt(void *ext, void *msk, struct flow_rule *rule)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun struct flow_match_enc_opts match;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun flow_rule_match_enc_opts(rule, &match);
323*4882a593Smuzhiyun memcpy(ext, match.key->data, match.key->len);
324*4882a593Smuzhiyun memcpy(msk, match.mask->data, match.mask->len);
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun return 0;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun static void
nfp_flower_compile_tun_ipv4_addrs(struct nfp_flower_tun_ipv4 * ext,struct nfp_flower_tun_ipv4 * msk,struct flow_rule * rule)330*4882a593Smuzhiyun nfp_flower_compile_tun_ipv4_addrs(struct nfp_flower_tun_ipv4 *ext,
331*4882a593Smuzhiyun struct nfp_flower_tun_ipv4 *msk,
332*4882a593Smuzhiyun struct flow_rule *rule)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
335*4882a593Smuzhiyun struct flow_match_ipv4_addrs match;
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun flow_rule_match_enc_ipv4_addrs(rule, &match);
338*4882a593Smuzhiyun ext->src = match.key->src;
339*4882a593Smuzhiyun ext->dst = match.key->dst;
340*4882a593Smuzhiyun msk->src = match.mask->src;
341*4882a593Smuzhiyun msk->dst = match.mask->dst;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun static void
nfp_flower_compile_tun_ipv6_addrs(struct nfp_flower_tun_ipv6 * ext,struct nfp_flower_tun_ipv6 * msk,struct flow_rule * rule)346*4882a593Smuzhiyun nfp_flower_compile_tun_ipv6_addrs(struct nfp_flower_tun_ipv6 *ext,
347*4882a593Smuzhiyun struct nfp_flower_tun_ipv6 *msk,
348*4882a593Smuzhiyun struct flow_rule *rule)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) {
351*4882a593Smuzhiyun struct flow_match_ipv6_addrs match;
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun flow_rule_match_enc_ipv6_addrs(rule, &match);
354*4882a593Smuzhiyun ext->src = match.key->src;
355*4882a593Smuzhiyun ext->dst = match.key->dst;
356*4882a593Smuzhiyun msk->src = match.mask->src;
357*4882a593Smuzhiyun msk->dst = match.mask->dst;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun static void
nfp_flower_compile_tun_ip_ext(struct nfp_flower_tun_ip_ext * ext,struct nfp_flower_tun_ip_ext * msk,struct flow_rule * rule)362*4882a593Smuzhiyun nfp_flower_compile_tun_ip_ext(struct nfp_flower_tun_ip_ext *ext,
363*4882a593Smuzhiyun struct nfp_flower_tun_ip_ext *msk,
364*4882a593Smuzhiyun struct flow_rule *rule)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) {
367*4882a593Smuzhiyun struct flow_match_ip match;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun flow_rule_match_enc_ip(rule, &match);
370*4882a593Smuzhiyun ext->tos = match.key->tos;
371*4882a593Smuzhiyun ext->ttl = match.key->ttl;
372*4882a593Smuzhiyun msk->tos = match.mask->tos;
373*4882a593Smuzhiyun msk->ttl = match.mask->ttl;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun static void
nfp_flower_compile_tun_udp_key(__be32 * key,__be32 * key_msk,struct flow_rule * rule)378*4882a593Smuzhiyun nfp_flower_compile_tun_udp_key(__be32 *key, __be32 *key_msk,
379*4882a593Smuzhiyun struct flow_rule *rule)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
382*4882a593Smuzhiyun struct flow_match_enc_keyid match;
383*4882a593Smuzhiyun u32 vni;
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun flow_rule_match_enc_keyid(rule, &match);
386*4882a593Smuzhiyun vni = be32_to_cpu(match.key->keyid) << NFP_FL_TUN_VNI_OFFSET;
387*4882a593Smuzhiyun *key = cpu_to_be32(vni);
388*4882a593Smuzhiyun vni = be32_to_cpu(match.mask->keyid) << NFP_FL_TUN_VNI_OFFSET;
389*4882a593Smuzhiyun *key_msk = cpu_to_be32(vni);
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun static void
nfp_flower_compile_tun_gre_key(__be32 * key,__be32 * key_msk,__be16 * flags,__be16 * flags_msk,struct flow_rule * rule)394*4882a593Smuzhiyun nfp_flower_compile_tun_gre_key(__be32 *key, __be32 *key_msk, __be16 *flags,
395*4882a593Smuzhiyun __be16 *flags_msk, struct flow_rule *rule)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
398*4882a593Smuzhiyun struct flow_match_enc_keyid match;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun flow_rule_match_enc_keyid(rule, &match);
401*4882a593Smuzhiyun *key = match.key->keyid;
402*4882a593Smuzhiyun *key_msk = match.mask->keyid;
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun *flags = cpu_to_be16(NFP_FL_GRE_FLAG_KEY);
405*4882a593Smuzhiyun *flags_msk = cpu_to_be16(NFP_FL_GRE_FLAG_KEY);
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun static void
nfp_flower_compile_ipv4_gre_tun(struct nfp_flower_ipv4_gre_tun * ext,struct nfp_flower_ipv4_gre_tun * msk,struct flow_rule * rule)410*4882a593Smuzhiyun nfp_flower_compile_ipv4_gre_tun(struct nfp_flower_ipv4_gre_tun *ext,
411*4882a593Smuzhiyun struct nfp_flower_ipv4_gre_tun *msk,
412*4882a593Smuzhiyun struct flow_rule *rule)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun memset(ext, 0, sizeof(struct nfp_flower_ipv4_gre_tun));
415*4882a593Smuzhiyun memset(msk, 0, sizeof(struct nfp_flower_ipv4_gre_tun));
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun /* NVGRE is the only supported GRE tunnel type */
418*4882a593Smuzhiyun ext->ethertype = cpu_to_be16(ETH_P_TEB);
419*4882a593Smuzhiyun msk->ethertype = cpu_to_be16(~0);
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun nfp_flower_compile_tun_ipv4_addrs(&ext->ipv4, &msk->ipv4, rule);
422*4882a593Smuzhiyun nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
423*4882a593Smuzhiyun nfp_flower_compile_tun_gre_key(&ext->tun_key, &msk->tun_key,
424*4882a593Smuzhiyun &ext->tun_flags, &msk->tun_flags, rule);
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun static void
nfp_flower_compile_ipv4_udp_tun(struct nfp_flower_ipv4_udp_tun * ext,struct nfp_flower_ipv4_udp_tun * msk,struct flow_rule * rule)428*4882a593Smuzhiyun nfp_flower_compile_ipv4_udp_tun(struct nfp_flower_ipv4_udp_tun *ext,
429*4882a593Smuzhiyun struct nfp_flower_ipv4_udp_tun *msk,
430*4882a593Smuzhiyun struct flow_rule *rule)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun memset(ext, 0, sizeof(struct nfp_flower_ipv4_udp_tun));
433*4882a593Smuzhiyun memset(msk, 0, sizeof(struct nfp_flower_ipv4_udp_tun));
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun nfp_flower_compile_tun_ipv4_addrs(&ext->ipv4, &msk->ipv4, rule);
436*4882a593Smuzhiyun nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
437*4882a593Smuzhiyun nfp_flower_compile_tun_udp_key(&ext->tun_id, &msk->tun_id, rule);
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun static void
nfp_flower_compile_ipv6_udp_tun(struct nfp_flower_ipv6_udp_tun * ext,struct nfp_flower_ipv6_udp_tun * msk,struct flow_rule * rule)441*4882a593Smuzhiyun nfp_flower_compile_ipv6_udp_tun(struct nfp_flower_ipv6_udp_tun *ext,
442*4882a593Smuzhiyun struct nfp_flower_ipv6_udp_tun *msk,
443*4882a593Smuzhiyun struct flow_rule *rule)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun memset(ext, 0, sizeof(struct nfp_flower_ipv6_udp_tun));
446*4882a593Smuzhiyun memset(msk, 0, sizeof(struct nfp_flower_ipv6_udp_tun));
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun nfp_flower_compile_tun_ipv6_addrs(&ext->ipv6, &msk->ipv6, rule);
449*4882a593Smuzhiyun nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
450*4882a593Smuzhiyun nfp_flower_compile_tun_udp_key(&ext->tun_id, &msk->tun_id, rule);
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun static void
nfp_flower_compile_ipv6_gre_tun(struct nfp_flower_ipv6_gre_tun * ext,struct nfp_flower_ipv6_gre_tun * msk,struct flow_rule * rule)454*4882a593Smuzhiyun nfp_flower_compile_ipv6_gre_tun(struct nfp_flower_ipv6_gre_tun *ext,
455*4882a593Smuzhiyun struct nfp_flower_ipv6_gre_tun *msk,
456*4882a593Smuzhiyun struct flow_rule *rule)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun memset(ext, 0, sizeof(struct nfp_flower_ipv6_gre_tun));
459*4882a593Smuzhiyun memset(msk, 0, sizeof(struct nfp_flower_ipv6_gre_tun));
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun /* NVGRE is the only supported GRE tunnel type */
462*4882a593Smuzhiyun ext->ethertype = cpu_to_be16(ETH_P_TEB);
463*4882a593Smuzhiyun msk->ethertype = cpu_to_be16(~0);
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun nfp_flower_compile_tun_ipv6_addrs(&ext->ipv6, &msk->ipv6, rule);
466*4882a593Smuzhiyun nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
467*4882a593Smuzhiyun nfp_flower_compile_tun_gre_key(&ext->tun_key, &msk->tun_key,
468*4882a593Smuzhiyun &ext->tun_flags, &msk->tun_flags, rule);
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun
nfp_flower_compile_flow_match(struct nfp_app * app,struct flow_cls_offload * flow,struct nfp_fl_key_ls * key_ls,struct net_device * netdev,struct nfp_fl_payload * nfp_flow,enum nfp_flower_tun_type tun_type,struct netlink_ext_ack * extack)471*4882a593Smuzhiyun int nfp_flower_compile_flow_match(struct nfp_app *app,
472*4882a593Smuzhiyun struct flow_cls_offload *flow,
473*4882a593Smuzhiyun struct nfp_fl_key_ls *key_ls,
474*4882a593Smuzhiyun struct net_device *netdev,
475*4882a593Smuzhiyun struct nfp_fl_payload *nfp_flow,
476*4882a593Smuzhiyun enum nfp_flower_tun_type tun_type,
477*4882a593Smuzhiyun struct netlink_ext_ack *extack)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun struct flow_rule *rule = flow_cls_offload_flow_rule(flow);
480*4882a593Smuzhiyun struct nfp_flower_priv *priv = app->priv;
481*4882a593Smuzhiyun bool qinq_sup;
482*4882a593Smuzhiyun u32 port_id;
483*4882a593Smuzhiyun int ext_len;
484*4882a593Smuzhiyun int err;
485*4882a593Smuzhiyun u8 *ext;
486*4882a593Smuzhiyun u8 *msk;
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun port_id = nfp_flower_get_port_id_from_netdev(app, netdev);
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun memset(nfp_flow->unmasked_data, 0, key_ls->key_size);
491*4882a593Smuzhiyun memset(nfp_flow->mask_data, 0, key_ls->key_size);
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun ext = nfp_flow->unmasked_data;
494*4882a593Smuzhiyun msk = nfp_flow->mask_data;
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun qinq_sup = !!(priv->flower_ext_feats & NFP_FL_FEATS_VLAN_QINQ);
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun nfp_flower_compile_meta_tci((struct nfp_flower_meta_tci *)ext,
499*4882a593Smuzhiyun (struct nfp_flower_meta_tci *)msk,
500*4882a593Smuzhiyun rule, key_ls->key_layer, qinq_sup);
501*4882a593Smuzhiyun ext += sizeof(struct nfp_flower_meta_tci);
502*4882a593Smuzhiyun msk += sizeof(struct nfp_flower_meta_tci);
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun /* Populate Extended Metadata if Required. */
505*4882a593Smuzhiyun if (NFP_FLOWER_LAYER_EXT_META & key_ls->key_layer) {
506*4882a593Smuzhiyun nfp_flower_compile_ext_meta((struct nfp_flower_ext_meta *)ext,
507*4882a593Smuzhiyun key_ls->key_layer_two);
508*4882a593Smuzhiyun nfp_flower_compile_ext_meta((struct nfp_flower_ext_meta *)msk,
509*4882a593Smuzhiyun key_ls->key_layer_two);
510*4882a593Smuzhiyun ext += sizeof(struct nfp_flower_ext_meta);
511*4882a593Smuzhiyun msk += sizeof(struct nfp_flower_ext_meta);
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun /* Populate Exact Port data. */
515*4882a593Smuzhiyun err = nfp_flower_compile_port((struct nfp_flower_in_port *)ext,
516*4882a593Smuzhiyun port_id, false, tun_type, extack);
517*4882a593Smuzhiyun if (err)
518*4882a593Smuzhiyun return err;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun /* Populate Mask Port Data. */
521*4882a593Smuzhiyun err = nfp_flower_compile_port((struct nfp_flower_in_port *)msk,
522*4882a593Smuzhiyun port_id, true, tun_type, extack);
523*4882a593Smuzhiyun if (err)
524*4882a593Smuzhiyun return err;
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun ext += sizeof(struct nfp_flower_in_port);
527*4882a593Smuzhiyun msk += sizeof(struct nfp_flower_in_port);
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun if (NFP_FLOWER_LAYER_MAC & key_ls->key_layer) {
530*4882a593Smuzhiyun err = nfp_flower_compile_mac((struct nfp_flower_mac_mpls *)ext,
531*4882a593Smuzhiyun (struct nfp_flower_mac_mpls *)msk,
532*4882a593Smuzhiyun rule, extack);
533*4882a593Smuzhiyun if (err)
534*4882a593Smuzhiyun return err;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun ext += sizeof(struct nfp_flower_mac_mpls);
537*4882a593Smuzhiyun msk += sizeof(struct nfp_flower_mac_mpls);
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun if (NFP_FLOWER_LAYER_TP & key_ls->key_layer) {
541*4882a593Smuzhiyun nfp_flower_compile_tport((struct nfp_flower_tp_ports *)ext,
542*4882a593Smuzhiyun (struct nfp_flower_tp_ports *)msk,
543*4882a593Smuzhiyun rule);
544*4882a593Smuzhiyun ext += sizeof(struct nfp_flower_tp_ports);
545*4882a593Smuzhiyun msk += sizeof(struct nfp_flower_tp_ports);
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun if (NFP_FLOWER_LAYER_IPV4 & key_ls->key_layer) {
549*4882a593Smuzhiyun nfp_flower_compile_ipv4((struct nfp_flower_ipv4 *)ext,
550*4882a593Smuzhiyun (struct nfp_flower_ipv4 *)msk,
551*4882a593Smuzhiyun rule);
552*4882a593Smuzhiyun ext += sizeof(struct nfp_flower_ipv4);
553*4882a593Smuzhiyun msk += sizeof(struct nfp_flower_ipv4);
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun if (NFP_FLOWER_LAYER_IPV6 & key_ls->key_layer) {
557*4882a593Smuzhiyun nfp_flower_compile_ipv6((struct nfp_flower_ipv6 *)ext,
558*4882a593Smuzhiyun (struct nfp_flower_ipv6 *)msk,
559*4882a593Smuzhiyun rule);
560*4882a593Smuzhiyun ext += sizeof(struct nfp_flower_ipv6);
561*4882a593Smuzhiyun msk += sizeof(struct nfp_flower_ipv6);
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_GRE) {
565*4882a593Smuzhiyun if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_TUN_IPV6) {
566*4882a593Smuzhiyun struct nfp_flower_ipv6_gre_tun *gre_match;
567*4882a593Smuzhiyun struct nfp_ipv6_addr_entry *entry;
568*4882a593Smuzhiyun struct in6_addr *dst;
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun nfp_flower_compile_ipv6_gre_tun((void *)ext,
571*4882a593Smuzhiyun (void *)msk, rule);
572*4882a593Smuzhiyun gre_match = (struct nfp_flower_ipv6_gre_tun *)ext;
573*4882a593Smuzhiyun dst = &gre_match->ipv6.dst;
574*4882a593Smuzhiyun ext += sizeof(struct nfp_flower_ipv6_gre_tun);
575*4882a593Smuzhiyun msk += sizeof(struct nfp_flower_ipv6_gre_tun);
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun entry = nfp_tunnel_add_ipv6_off(app, dst);
578*4882a593Smuzhiyun if (!entry)
579*4882a593Smuzhiyun return -EOPNOTSUPP;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun nfp_flow->nfp_tun_ipv6 = entry;
582*4882a593Smuzhiyun } else {
583*4882a593Smuzhiyun __be32 dst;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun nfp_flower_compile_ipv4_gre_tun((void *)ext,
586*4882a593Smuzhiyun (void *)msk, rule);
587*4882a593Smuzhiyun dst = ((struct nfp_flower_ipv4_gre_tun *)ext)->ipv4.dst;
588*4882a593Smuzhiyun ext += sizeof(struct nfp_flower_ipv4_gre_tun);
589*4882a593Smuzhiyun msk += sizeof(struct nfp_flower_ipv4_gre_tun);
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun /* Store the tunnel destination in the rule data.
592*4882a593Smuzhiyun * This must be present and be an exact match.
593*4882a593Smuzhiyun */
594*4882a593Smuzhiyun nfp_flow->nfp_tun_ipv4_addr = dst;
595*4882a593Smuzhiyun nfp_tunnel_add_ipv4_off(app, dst);
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun }
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun if (NFP_FLOWER_LAYER2_QINQ & key_ls->key_layer_two) {
600*4882a593Smuzhiyun nfp_flower_compile_vlan((struct nfp_flower_vlan *)ext,
601*4882a593Smuzhiyun (struct nfp_flower_vlan *)msk,
602*4882a593Smuzhiyun rule);
603*4882a593Smuzhiyun ext += sizeof(struct nfp_flower_vlan);
604*4882a593Smuzhiyun msk += sizeof(struct nfp_flower_vlan);
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun if (key_ls->key_layer & NFP_FLOWER_LAYER_VXLAN ||
608*4882a593Smuzhiyun key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE) {
609*4882a593Smuzhiyun if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_TUN_IPV6) {
610*4882a593Smuzhiyun struct nfp_flower_ipv6_udp_tun *udp_match;
611*4882a593Smuzhiyun struct nfp_ipv6_addr_entry *entry;
612*4882a593Smuzhiyun struct in6_addr *dst;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun nfp_flower_compile_ipv6_udp_tun((void *)ext,
615*4882a593Smuzhiyun (void *)msk, rule);
616*4882a593Smuzhiyun udp_match = (struct nfp_flower_ipv6_udp_tun *)ext;
617*4882a593Smuzhiyun dst = &udp_match->ipv6.dst;
618*4882a593Smuzhiyun ext += sizeof(struct nfp_flower_ipv6_udp_tun);
619*4882a593Smuzhiyun msk += sizeof(struct nfp_flower_ipv6_udp_tun);
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun entry = nfp_tunnel_add_ipv6_off(app, dst);
622*4882a593Smuzhiyun if (!entry)
623*4882a593Smuzhiyun return -EOPNOTSUPP;
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun nfp_flow->nfp_tun_ipv6 = entry;
626*4882a593Smuzhiyun } else {
627*4882a593Smuzhiyun __be32 dst;
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun nfp_flower_compile_ipv4_udp_tun((void *)ext,
630*4882a593Smuzhiyun (void *)msk, rule);
631*4882a593Smuzhiyun dst = ((struct nfp_flower_ipv4_udp_tun *)ext)->ipv4.dst;
632*4882a593Smuzhiyun ext += sizeof(struct nfp_flower_ipv4_udp_tun);
633*4882a593Smuzhiyun msk += sizeof(struct nfp_flower_ipv4_udp_tun);
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun /* Store the tunnel destination in the rule data.
636*4882a593Smuzhiyun * This must be present and be an exact match.
637*4882a593Smuzhiyun */
638*4882a593Smuzhiyun nfp_flow->nfp_tun_ipv4_addr = dst;
639*4882a593Smuzhiyun nfp_tunnel_add_ipv4_off(app, dst);
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE_OP) {
643*4882a593Smuzhiyun err = nfp_flower_compile_geneve_opt(ext, msk, rule);
644*4882a593Smuzhiyun if (err)
645*4882a593Smuzhiyun return err;
646*4882a593Smuzhiyun }
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun /* Check that the flow key does not exceed the maximum limit.
650*4882a593Smuzhiyun * All structures in the key is multiples of 4 bytes, so use u32.
651*4882a593Smuzhiyun */
652*4882a593Smuzhiyun ext_len = (u32 *)ext - (u32 *)nfp_flow->unmasked_data;
653*4882a593Smuzhiyun if (ext_len > NFP_FLOWER_KEY_MAX_LW) {
654*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack,
655*4882a593Smuzhiyun "unsupported offload: flow key too long");
656*4882a593Smuzhiyun return -EOPNOTSUPP;
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun return 0;
660*4882a593Smuzhiyun }
661