37
37
#include <net/tc_act/tc_gact.h>
38
38
#include <net/tc_act/tc_mirred.h>
39
39
#include <net/tc_act/tc_vlan.h>
40
+ #include <net/tc_act/tc_tunnel_key.h>
40
41
41
42
#include "cmsg.h"
42
43
#include "main.h"
@@ -80,14 +81,27 @@ nfp_fl_push_vlan(struct nfp_fl_push_vlan *push_vlan,
80
81
push_vlan -> vlan_tci = cpu_to_be16 (tmp_push_vlan_tci );
81
82
}
82
83
84
+ static bool nfp_fl_netdev_is_tunnel_type (struct net_device * out_dev ,
85
+ enum nfp_flower_tun_type tun_type )
86
+ {
87
+ if (!out_dev -> rtnl_link_ops )
88
+ return false;
89
+
90
+ if (!strcmp (out_dev -> rtnl_link_ops -> kind , "vxlan" ))
91
+ return tun_type == NFP_FL_TUNNEL_VXLAN ;
92
+
93
+ return false;
94
+ }
95
+
83
96
static int
84
97
nfp_fl_output (struct nfp_fl_output * output , const struct tc_action * action ,
85
98
struct nfp_fl_payload * nfp_flow , bool last ,
86
- struct net_device * in_dev )
99
+ struct net_device * in_dev , enum nfp_flower_tun_type tun_type ,
100
+ int * tun_out_cnt )
87
101
{
88
102
size_t act_size = sizeof (struct nfp_fl_output );
103
+ u16 tmp_output_op , tmp_flags ;
89
104
struct net_device * out_dev ;
90
- u16 tmp_output_op ;
91
105
int ifindex ;
92
106
93
107
/* Set action opcode to output action. */
@@ -97,34 +111,126 @@ nfp_fl_output(struct nfp_fl_output *output, const struct tc_action *action,
97
111
98
112
output -> a_op = cpu_to_be16 (tmp_output_op );
99
113
100
- /* Set action output parameters. */
101
- output -> flags = cpu_to_be16 (last ? NFP_FL_OUT_FLAGS_LAST : 0 );
102
-
103
114
ifindex = tcf_mirred_ifindex (action );
104
115
out_dev = __dev_get_by_index (dev_net (in_dev ), ifindex );
105
116
if (!out_dev )
106
117
return - EOPNOTSUPP ;
107
118
108
- /* Only offload egress ports are on the same device as the ingress
109
- * port.
119
+ tmp_flags = last ? NFP_FL_OUT_FLAGS_LAST : 0 ;
120
+
121
+ if (tun_type ) {
122
+ /* Verify the egress netdev matches the tunnel type. */
123
+ if (!nfp_fl_netdev_is_tunnel_type (out_dev , tun_type ))
124
+ return - EOPNOTSUPP ;
125
+
126
+ if (* tun_out_cnt )
127
+ return - EOPNOTSUPP ;
128
+ (* tun_out_cnt )++ ;
129
+
130
+ output -> flags = cpu_to_be16 (tmp_flags |
131
+ NFP_FL_OUT_FLAGS_USE_TUN );
132
+ output -> port = cpu_to_be32 (NFP_FL_PORT_TYPE_TUN | tun_type );
133
+ } else {
134
+ /* Set action output parameters. */
135
+ output -> flags = cpu_to_be16 (tmp_flags );
136
+
137
+ /* Only offload if egress ports are on the same device as the
138
+ * ingress port.
139
+ */
140
+ if (!switchdev_port_same_parent_id (in_dev , out_dev ))
141
+ return - EOPNOTSUPP ;
142
+
143
+ output -> port = cpu_to_be32 (nfp_repr_get_port_id (out_dev ));
144
+ if (!output -> port )
145
+ return - EOPNOTSUPP ;
146
+ }
147
+ nfp_flow -> meta .shortcut = output -> port ;
148
+
149
+ return 0 ;
150
+ }
151
+
152
+ static bool nfp_fl_supported_tun_port (const struct tc_action * action )
153
+ {
154
+ struct ip_tunnel_info * tun = tcf_tunnel_info (action );
155
+
156
+ return tun -> key .tp_dst == htons (NFP_FL_VXLAN_PORT );
157
+ }
158
+
159
+ static struct nfp_fl_pre_tunnel * nfp_fl_pre_tunnel (char * act_data , int act_len )
160
+ {
161
+ size_t act_size = sizeof (struct nfp_fl_pre_tunnel );
162
+ struct nfp_fl_pre_tunnel * pre_tun_act ;
163
+ u16 tmp_pre_tun_op ;
164
+
165
+ /* Pre_tunnel action must be first on action list.
166
+ * If other actions already exist they need pushed forward.
110
167
*/
111
- if (!switchdev_port_same_parent_id (in_dev , out_dev ))
112
- return - EOPNOTSUPP ;
168
+ if (act_len )
169
+ memmove (act_data + act_size , act_data , act_len );
170
+
171
+ pre_tun_act = (struct nfp_fl_pre_tunnel * )act_data ;
172
+
173
+ memset (pre_tun_act , 0 , act_size );
174
+
175
+ tmp_pre_tun_op =
176
+ FIELD_PREP (NFP_FL_ACT_LEN_LW , act_size >> NFP_FL_LW_SIZ ) |
177
+ FIELD_PREP (NFP_FL_ACT_JMP_ID , NFP_FL_ACTION_OPCODE_PRE_TUNNEL );
178
+
179
+ pre_tun_act -> a_op = cpu_to_be16 (tmp_pre_tun_op );
113
180
114
- output -> port = cpu_to_be32 (nfp_repr_get_port_id (out_dev ));
115
- if (!output -> port )
181
+ return pre_tun_act ;
182
+ }
183
+
184
+ static int
185
+ nfp_fl_set_vxlan (struct nfp_fl_set_vxlan * set_vxlan ,
186
+ const struct tc_action * action ,
187
+ struct nfp_fl_pre_tunnel * pre_tun )
188
+ {
189
+ struct ip_tunnel_info * vxlan = tcf_tunnel_info (action );
190
+ size_t act_size = sizeof (struct nfp_fl_set_vxlan );
191
+ u32 tmp_set_vxlan_type_index = 0 ;
192
+ u16 tmp_set_vxlan_op ;
193
+ /* Currently support one pre-tunnel so index is always 0. */
194
+ int pretun_idx = 0 ;
195
+
196
+ if (vxlan -> options_len ) {
197
+ /* Do not support options e.g. vxlan gpe. */
116
198
return - EOPNOTSUPP ;
199
+ }
117
200
118
- nfp_flow -> meta .shortcut = output -> port ;
201
+ tmp_set_vxlan_op =
202
+ FIELD_PREP (NFP_FL_ACT_LEN_LW , act_size >> NFP_FL_LW_SIZ ) |
203
+ FIELD_PREP (NFP_FL_ACT_JMP_ID ,
204
+ NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL );
205
+
206
+ set_vxlan -> a_op = cpu_to_be16 (tmp_set_vxlan_op );
207
+
208
+ /* Set tunnel type and pre-tunnel index. */
209
+ tmp_set_vxlan_type_index |=
210
+ FIELD_PREP (NFP_FL_IPV4_TUNNEL_TYPE , NFP_FL_TUNNEL_VXLAN ) |
211
+ FIELD_PREP (NFP_FL_IPV4_PRE_TUN_INDEX , pretun_idx );
212
+
213
+ set_vxlan -> tun_type_index = cpu_to_be32 (tmp_set_vxlan_type_index );
214
+
215
+ set_vxlan -> tun_id = vxlan -> key .tun_id ;
216
+ set_vxlan -> tun_flags = vxlan -> key .tun_flags ;
217
+ set_vxlan -> ipv4_ttl = vxlan -> key .ttl ;
218
+ set_vxlan -> ipv4_tos = vxlan -> key .tos ;
219
+
220
+ /* Complete pre_tunnel action. */
221
+ pre_tun -> ipv4_dst = vxlan -> key .u .ipv4 .dst ;
119
222
120
223
return 0 ;
121
224
}
122
225
123
226
static int
124
227
nfp_flower_loop_action (const struct tc_action * a ,
125
228
struct nfp_fl_payload * nfp_fl , int * a_len ,
126
- struct net_device * netdev )
229
+ struct net_device * netdev ,
230
+ enum nfp_flower_tun_type * tun_type , int * tun_out_cnt )
127
231
{
232
+ struct nfp_fl_pre_tunnel * pre_tun ;
233
+ struct nfp_fl_set_vxlan * s_vxl ;
128
234
struct nfp_fl_push_vlan * psh_v ;
129
235
struct nfp_fl_pop_vlan * pop_v ;
130
236
struct nfp_fl_output * output ;
@@ -137,7 +243,8 @@ nfp_flower_loop_action(const struct tc_action *a,
137
243
return - EOPNOTSUPP ;
138
244
139
245
output = (struct nfp_fl_output * )& nfp_fl -> action_data [* a_len ];
140
- err = nfp_fl_output (output , a , nfp_fl , true, netdev );
246
+ err = nfp_fl_output (output , a , nfp_fl , true, netdev , * tun_type ,
247
+ tun_out_cnt );
141
248
if (err )
142
249
return err ;
143
250
@@ -147,7 +254,8 @@ nfp_flower_loop_action(const struct tc_action *a,
147
254
return - EOPNOTSUPP ;
148
255
149
256
output = (struct nfp_fl_output * )& nfp_fl -> action_data [* a_len ];
150
- err = nfp_fl_output (output , a , nfp_fl , false, netdev );
257
+ err = nfp_fl_output (output , a , nfp_fl , false, netdev , * tun_type ,
258
+ tun_out_cnt );
151
259
if (err )
152
260
return err ;
153
261
@@ -170,6 +278,29 @@ nfp_flower_loop_action(const struct tc_action *a,
170
278
171
279
nfp_fl_push_vlan (psh_v , a );
172
280
* a_len += sizeof (struct nfp_fl_push_vlan );
281
+ } else if (is_tcf_tunnel_set (a ) && nfp_fl_supported_tun_port (a )) {
282
+ /* Pre-tunnel action is required for tunnel encap.
283
+ * This checks for next hop entries on NFP.
284
+ * If none, the packet falls back before applying other actions.
285
+ */
286
+ if (* a_len + sizeof (struct nfp_fl_pre_tunnel ) +
287
+ sizeof (struct nfp_fl_set_vxlan ) > NFP_FL_MAX_A_SIZ )
288
+ return - EOPNOTSUPP ;
289
+
290
+ * tun_type = NFP_FL_TUNNEL_VXLAN ;
291
+ pre_tun = nfp_fl_pre_tunnel (nfp_fl -> action_data , * a_len );
292
+ nfp_fl -> meta .shortcut = cpu_to_be32 (NFP_FL_SC_ACT_NULL );
293
+ * a_len += sizeof (struct nfp_fl_pre_tunnel );
294
+
295
+ s_vxl = (struct nfp_fl_set_vxlan * )& nfp_fl -> action_data [* a_len ];
296
+ err = nfp_fl_set_vxlan (s_vxl , a , pre_tun );
297
+ if (err )
298
+ return err ;
299
+
300
+ * a_len += sizeof (struct nfp_fl_set_vxlan );
301
+ } else if (is_tcf_tunnel_release (a )) {
302
+ /* Tunnel decap is handled by default so accept action. */
303
+ return 0 ;
173
304
} else {
174
305
/* Currently we do not handle any other actions. */
175
306
return - EOPNOTSUPP ;
@@ -182,18 +313,22 @@ int nfp_flower_compile_action(struct tc_cls_flower_offload *flow,
182
313
struct net_device * netdev ,
183
314
struct nfp_fl_payload * nfp_flow )
184
315
{
185
- int act_len , act_cnt , err ;
316
+ int act_len , act_cnt , err , tun_out_cnt ;
317
+ enum nfp_flower_tun_type tun_type ;
186
318
const struct tc_action * a ;
187
319
LIST_HEAD (actions );
188
320
189
321
memset (nfp_flow -> action_data , 0 , NFP_FL_MAX_A_SIZ );
190
322
nfp_flow -> meta .act_len = 0 ;
323
+ tun_type = NFP_FL_TUNNEL_NONE ;
191
324
act_len = 0 ;
192
325
act_cnt = 0 ;
326
+ tun_out_cnt = 0 ;
193
327
194
328
tcf_exts_to_list (flow -> exts , & actions );
195
329
list_for_each_entry (a , & actions , list ) {
196
- err = nfp_flower_loop_action (a , nfp_flow , & act_len , netdev );
330
+ err = nfp_flower_loop_action (a , nfp_flow , & act_len , netdev ,
331
+ & tun_type , & tun_out_cnt );
197
332
if (err )
198
333
return err ;
199
334
act_cnt ++ ;
0 commit comments