@@ -236,6 +236,71 @@ static void flow_offload_ipv4_dnat(struct net *net,
236
236
(u8 * )& addr , (u8 * )& mask );
237
237
}
238
238
239
+ static void flow_offload_ipv6_mangle (struct nf_flow_rule * flow_rule ,
240
+ unsigned int offset ,
241
+ u8 * addr , u8 * mask )
242
+ {
243
+ struct flow_action_entry * entry ;
244
+ int i ;
245
+
246
+ for (i = 0 ; i < sizeof (struct in6_addr ) / sizeof (u32 ); i += sizeof (u32 )) {
247
+ entry = flow_action_entry_next (flow_rule );
248
+ flow_offload_mangle (entry , FLOW_ACT_MANGLE_HDR_TYPE_IP6 ,
249
+ offset + i ,
250
+ & addr [i ], mask );
251
+ }
252
+ }
253
+
254
+ static void flow_offload_ipv6_snat (struct net * net ,
255
+ const struct flow_offload * flow ,
256
+ enum flow_offload_tuple_dir dir ,
257
+ struct nf_flow_rule * flow_rule )
258
+ {
259
+ u32 mask = ~htonl (0xffffffff );
260
+ const u8 * addr ;
261
+ u32 offset ;
262
+
263
+ switch (dir ) {
264
+ case FLOW_OFFLOAD_DIR_ORIGINAL :
265
+ addr = flow -> tuplehash [FLOW_OFFLOAD_DIR_REPLY ].tuple .dst_v6 .s6_addr ;
266
+ offset = offsetof(struct ipv6hdr , saddr );
267
+ break ;
268
+ case FLOW_OFFLOAD_DIR_REPLY :
269
+ addr = flow -> tuplehash [FLOW_OFFLOAD_DIR_ORIGINAL ].tuple .src_v6 .s6_addr ;
270
+ offset = offsetof(struct ipv6hdr , daddr );
271
+ break ;
272
+ default :
273
+ return ;
274
+ }
275
+
276
+ flow_offload_ipv6_mangle (flow_rule , offset , (u8 * )addr , (u8 * )& mask );
277
+ }
278
+
279
+ static void flow_offload_ipv6_dnat (struct net * net ,
280
+ const struct flow_offload * flow ,
281
+ enum flow_offload_tuple_dir dir ,
282
+ struct nf_flow_rule * flow_rule )
283
+ {
284
+ u32 mask = ~htonl (0xffffffff );
285
+ const u8 * addr ;
286
+ u32 offset ;
287
+
288
+ switch (dir ) {
289
+ case FLOW_OFFLOAD_DIR_ORIGINAL :
290
+ addr = flow -> tuplehash [FLOW_OFFLOAD_DIR_REPLY ].tuple .src_v6 .s6_addr ;
291
+ offset = offsetof(struct ipv6hdr , daddr );
292
+ break ;
293
+ case FLOW_OFFLOAD_DIR_REPLY :
294
+ addr = flow -> tuplehash [FLOW_OFFLOAD_DIR_ORIGINAL ].tuple .dst_v6 .s6_addr ;
295
+ offset = offsetof(struct ipv6hdr , saddr );
296
+ break ;
297
+ default :
298
+ return ;
299
+ }
300
+
301
+ flow_offload_ipv6_mangle (flow_rule , offset , (u8 * )addr , (u8 * )& mask );
302
+ }
303
+
239
304
static int flow_offload_l4proto (const struct flow_offload * flow )
240
305
{
241
306
u8 protonum = flow -> tuplehash [FLOW_OFFLOAD_DIR_ORIGINAL ].tuple .l4proto ;
@@ -342,9 +407,9 @@ static void flow_offload_redirect(const struct flow_offload *flow,
342
407
dev_hold (rt -> dst .dev );
343
408
}
344
409
345
- int nf_flow_rule_route (struct net * net , const struct flow_offload * flow ,
346
- enum flow_offload_tuple_dir dir ,
347
- struct nf_flow_rule * flow_rule )
410
+ int nf_flow_rule_route_ipv4 (struct net * net , const struct flow_offload * flow ,
411
+ enum flow_offload_tuple_dir dir ,
412
+ struct nf_flow_rule * flow_rule )
348
413
{
349
414
if (flow_offload_eth_src (net , flow , dir , flow_rule ) < 0 ||
350
415
flow_offload_eth_dst (net , flow , dir , flow_rule ) < 0 )
@@ -366,7 +431,32 @@ int nf_flow_rule_route(struct net *net, const struct flow_offload *flow,
366
431
367
432
return 0 ;
368
433
}
369
- EXPORT_SYMBOL_GPL (nf_flow_rule_route );
434
+ EXPORT_SYMBOL_GPL (nf_flow_rule_route_ipv4 );
435
+
436
+ int nf_flow_rule_route_ipv6 (struct net * net , const struct flow_offload * flow ,
437
+ enum flow_offload_tuple_dir dir ,
438
+ struct nf_flow_rule * flow_rule )
439
+ {
440
+ if (flow_offload_eth_src (net , flow , dir , flow_rule ) < 0 ||
441
+ flow_offload_eth_dst (net , flow , dir , flow_rule ) < 0 )
442
+ return -1 ;
443
+
444
+ if (flow -> flags & FLOW_OFFLOAD_SNAT ) {
445
+ flow_offload_ipv6_snat (net , flow , dir , flow_rule );
446
+ flow_offload_port_snat (net , flow , dir , flow_rule );
447
+ }
448
+ if (flow -> flags & FLOW_OFFLOAD_DNAT ) {
449
+ flow_offload_ipv6_dnat (net , flow , dir , flow_rule );
450
+ flow_offload_port_dnat (net , flow , dir , flow_rule );
451
+ }
452
+
453
+ flow_offload_redirect (flow , dir , flow_rule );
454
+
455
+ return 0 ;
456
+ }
457
+ EXPORT_SYMBOL_GPL (nf_flow_rule_route_ipv6 );
458
+
459
+ #define NF_FLOW_RULE_ACTION_MAX 16
370
460
371
461
static struct nf_flow_rule *
372
462
nf_flow_offload_rule_alloc (struct net * net ,
@@ -383,7 +473,7 @@ nf_flow_offload_rule_alloc(struct net *net,
383
473
if (!flow_rule )
384
474
goto err_flow ;
385
475
386
- flow_rule -> rule = flow_rule_alloc (10 );
476
+ flow_rule -> rule = flow_rule_alloc (NF_FLOW_RULE_ACTION_MAX );
387
477
if (!flow_rule -> rule )
388
478
goto err_flow_rule ;
389
479
0 commit comments