@@ -384,10 +384,21 @@ nfp_fl_set_eth(const struct tc_action *action, int idx, u32 off,
384
384
return 0 ;
385
385
}
386
386
387
+ struct ipv4_ttl_word {
388
+ __u8 ttl ;
389
+ __u8 protocol ;
390
+ __sum16 check ;
391
+ };
392
+
387
393
static int
388
394
nfp_fl_set_ip4 (const struct tc_action * action , int idx , u32 off ,
389
- struct nfp_fl_set_ip4_addrs * set_ip_addr )
395
+ struct nfp_fl_set_ip4_addrs * set_ip_addr ,
396
+ struct nfp_fl_set_ip4_ttl_tos * set_ip_ttl_tos )
390
397
{
398
+ struct ipv4_ttl_word * ttl_word_mask ;
399
+ struct ipv4_ttl_word * ttl_word ;
400
+ struct iphdr * tos_word_mask ;
401
+ struct iphdr * tos_word ;
391
402
__be32 exact , mask ;
392
403
393
404
/* We are expecting tcf_pedit to return a big endian value */
@@ -402,20 +413,53 @@ nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off,
402
413
set_ip_addr -> ipv4_dst_mask |= mask ;
403
414
set_ip_addr -> ipv4_dst &= ~mask ;
404
415
set_ip_addr -> ipv4_dst |= exact & mask ;
416
+ set_ip_addr -> head .jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS ;
417
+ set_ip_addr -> head .len_lw = sizeof (* set_ip_addr ) >>
418
+ NFP_FL_LW_SIZ ;
405
419
break ;
406
420
case offsetof(struct iphdr , saddr ):
407
421
set_ip_addr -> ipv4_src_mask |= mask ;
408
422
set_ip_addr -> ipv4_src &= ~mask ;
409
423
set_ip_addr -> ipv4_src |= exact & mask ;
424
+ set_ip_addr -> head .jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS ;
425
+ set_ip_addr -> head .len_lw = sizeof (* set_ip_addr ) >>
426
+ NFP_FL_LW_SIZ ;
427
+ break ;
428
+ case offsetof(struct iphdr , ttl ):
429
+ ttl_word_mask = (struct ipv4_ttl_word * )& mask ;
430
+ ttl_word = (struct ipv4_ttl_word * )& exact ;
431
+
432
+ if (ttl_word_mask -> protocol || ttl_word_mask -> check )
433
+ return - EOPNOTSUPP ;
434
+
435
+ set_ip_ttl_tos -> ipv4_ttl_mask |= ttl_word_mask -> ttl ;
436
+ set_ip_ttl_tos -> ipv4_ttl &= ~ttl_word_mask -> ttl ;
437
+ set_ip_ttl_tos -> ipv4_ttl |= ttl_word -> ttl & ttl_word_mask -> ttl ;
438
+ set_ip_ttl_tos -> head .jump_id =
439
+ NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS ;
440
+ set_ip_ttl_tos -> head .len_lw = sizeof (* set_ip_ttl_tos ) >>
441
+ NFP_FL_LW_SIZ ;
442
+ break ;
443
+ case round_down (offsetof(struct iphdr , tos ), 4 ):
444
+ tos_word_mask = (struct iphdr * )& mask ;
445
+ tos_word = (struct iphdr * )& exact ;
446
+
447
+ if (tos_word_mask -> version || tos_word_mask -> ihl ||
448
+ tos_word_mask -> tot_len )
449
+ return - EOPNOTSUPP ;
450
+
451
+ set_ip_ttl_tos -> ipv4_tos_mask |= tos_word_mask -> tos ;
452
+ set_ip_ttl_tos -> ipv4_tos &= ~tos_word_mask -> tos ;
453
+ set_ip_ttl_tos -> ipv4_tos |= tos_word -> tos & tos_word_mask -> tos ;
454
+ set_ip_ttl_tos -> head .jump_id =
455
+ NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS ;
456
+ set_ip_ttl_tos -> head .len_lw = sizeof (* set_ip_ttl_tos ) >>
457
+ NFP_FL_LW_SIZ ;
410
458
break ;
411
459
default :
412
460
return - EOPNOTSUPP ;
413
461
}
414
462
415
- set_ip_addr -> reserved = cpu_to_be16 (0 );
416
- set_ip_addr -> head .jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS ;
417
- set_ip_addr -> head .len_lw = sizeof (* set_ip_addr ) >> NFP_FL_LW_SIZ ;
418
-
419
463
return 0 ;
420
464
}
421
465
@@ -432,12 +476,57 @@ nfp_fl_set_ip6_helper(int opcode_tag, u8 word, __be32 exact, __be32 mask,
432
476
ip6 -> head .len_lw = sizeof (* ip6 ) >> NFP_FL_LW_SIZ ;
433
477
}
434
478
479
+ struct ipv6_hop_limit_word {
480
+ __be16 payload_len ;
481
+ u8 nexthdr ;
482
+ u8 hop_limit ;
483
+ };
484
+
485
+ static int
486
+ nfp_fl_set_ip6_hop_limit_flow_label (u32 off , __be32 exact , __be32 mask ,
487
+ struct nfp_fl_set_ipv6_tc_hl_fl * ip_hl_fl )
488
+ {
489
+ struct ipv6_hop_limit_word * fl_hl_mask ;
490
+ struct ipv6_hop_limit_word * fl_hl ;
491
+
492
+ switch (off ) {
493
+ case offsetof(struct ipv6hdr , payload_len ):
494
+ fl_hl_mask = (struct ipv6_hop_limit_word * )& mask ;
495
+ fl_hl = (struct ipv6_hop_limit_word * )& exact ;
496
+
497
+ if (fl_hl_mask -> nexthdr || fl_hl_mask -> payload_len )
498
+ return - EOPNOTSUPP ;
499
+
500
+ ip_hl_fl -> ipv6_hop_limit_mask |= fl_hl_mask -> hop_limit ;
501
+ ip_hl_fl -> ipv6_hop_limit &= ~fl_hl_mask -> hop_limit ;
502
+ ip_hl_fl -> ipv6_hop_limit |= fl_hl -> hop_limit &
503
+ fl_hl_mask -> hop_limit ;
504
+ break ;
505
+ case round_down (offsetof(struct ipv6hdr , flow_lbl ), 4 ):
506
+ if (mask & ~IPV6_FLOW_LABEL_MASK ||
507
+ exact & ~IPV6_FLOW_LABEL_MASK )
508
+ return - EOPNOTSUPP ;
509
+
510
+ ip_hl_fl -> ipv6_label_mask |= mask ;
511
+ ip_hl_fl -> ipv6_label &= ~mask ;
512
+ ip_hl_fl -> ipv6_label |= exact & mask ;
513
+ break ;
514
+ }
515
+
516
+ ip_hl_fl -> head .jump_id = NFP_FL_ACTION_OPCODE_SET_IPV6_TC_HL_FL ;
517
+ ip_hl_fl -> head .len_lw = sizeof (* ip_hl_fl ) >> NFP_FL_LW_SIZ ;
518
+
519
+ return 0 ;
520
+ }
521
+
435
522
static int
436
523
nfp_fl_set_ip6 (const struct tc_action * action , int idx , u32 off ,
437
524
struct nfp_fl_set_ipv6_addr * ip_dst ,
438
- struct nfp_fl_set_ipv6_addr * ip_src )
525
+ struct nfp_fl_set_ipv6_addr * ip_src ,
526
+ struct nfp_fl_set_ipv6_tc_hl_fl * ip_hl_fl )
439
527
{
440
528
__be32 exact , mask ;
529
+ int err = 0 ;
441
530
u8 word ;
442
531
443
532
/* We are expecting tcf_pedit to return a big endian value */
@@ -448,7 +537,8 @@ nfp_fl_set_ip6(const struct tc_action *action, int idx, u32 off,
448
537
return - EOPNOTSUPP ;
449
538
450
539
if (off < offsetof(struct ipv6hdr , saddr )) {
451
- return - EOPNOTSUPP ;
540
+ err = nfp_fl_set_ip6_hop_limit_flow_label (off , exact , mask ,
541
+ ip_hl_fl );
452
542
} else if (off < offsetof(struct ipv6hdr , daddr )) {
453
543
word = (off - offsetof(struct ipv6hdr , saddr )) / sizeof (exact );
454
544
nfp_fl_set_ip6_helper (NFP_FL_ACTION_OPCODE_SET_IPV6_SRC , word ,
@@ -462,7 +552,7 @@ nfp_fl_set_ip6(const struct tc_action *action, int idx, u32 off,
462
552
return - EOPNOTSUPP ;
463
553
}
464
554
465
- return 0 ;
555
+ return err ;
466
556
}
467
557
468
558
static int
@@ -513,6 +603,8 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
513
603
char * nfp_action , int * a_len , u32 * csum_updated )
514
604
{
515
605
struct nfp_fl_set_ipv6_addr set_ip6_dst , set_ip6_src ;
606
+ struct nfp_fl_set_ipv6_tc_hl_fl set_ip6_tc_hl_fl ;
607
+ struct nfp_fl_set_ip4_ttl_tos set_ip_ttl_tos ;
516
608
struct nfp_fl_set_ip4_addrs set_ip_addr ;
517
609
struct nfp_fl_set_tport set_tport ;
518
610
struct nfp_fl_set_eth set_eth ;
@@ -522,6 +614,8 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
522
614
u32 offset , cmd ;
523
615
u8 ip_proto = 0 ;
524
616
617
+ memset (& set_ip6_tc_hl_fl , 0 , sizeof (set_ip6_tc_hl_fl ));
618
+ memset (& set_ip_ttl_tos , 0 , sizeof (set_ip_ttl_tos ));
525
619
memset (& set_ip6_dst , 0 , sizeof (set_ip6_dst ));
526
620
memset (& set_ip6_src , 0 , sizeof (set_ip6_src ));
527
621
memset (& set_ip_addr , 0 , sizeof (set_ip_addr ));
@@ -542,11 +636,12 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
542
636
err = nfp_fl_set_eth (action , idx , offset , & set_eth );
543
637
break ;
544
638
case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 :
545
- err = nfp_fl_set_ip4 (action , idx , offset , & set_ip_addr );
639
+ err = nfp_fl_set_ip4 (action , idx , offset , & set_ip_addr ,
640
+ & set_ip_ttl_tos );
546
641
break ;
547
642
case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6 :
548
643
err = nfp_fl_set_ip6 (action , idx , offset , & set_ip6_dst ,
549
- & set_ip6_src );
644
+ & set_ip6_src , & set_ip6_tc_hl_fl );
550
645
break ;
551
646
case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP :
552
647
err = nfp_fl_set_tport (action , idx , offset , & set_tport ,
@@ -577,6 +672,16 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
577
672
memcpy (nfp_action , & set_eth , act_size );
578
673
* a_len += act_size ;
579
674
}
675
+ if (set_ip_ttl_tos .head .len_lw ) {
676
+ nfp_action += act_size ;
677
+ act_size = sizeof (set_ip_ttl_tos );
678
+ memcpy (nfp_action , & set_ip_ttl_tos , act_size );
679
+ * a_len += act_size ;
680
+
681
+ /* Hardware will automatically fix IPv4 and TCP/UDP checksum. */
682
+ * csum_updated |= TCA_CSUM_UPDATE_FLAG_IPV4HDR |
683
+ nfp_fl_csum_l4_to_flag (ip_proto );
684
+ }
580
685
if (set_ip_addr .head .len_lw ) {
581
686
nfp_action += act_size ;
582
687
act_size = sizeof (set_ip_addr );
@@ -587,6 +692,15 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
587
692
* csum_updated |= TCA_CSUM_UPDATE_FLAG_IPV4HDR |
588
693
nfp_fl_csum_l4_to_flag (ip_proto );
589
694
}
695
+ if (set_ip6_tc_hl_fl .head .len_lw ) {
696
+ nfp_action += act_size ;
697
+ act_size = sizeof (set_ip6_tc_hl_fl );
698
+ memcpy (nfp_action , & set_ip6_tc_hl_fl , act_size );
699
+ * a_len += act_size ;
700
+
701
+ /* Hardware will automatically fix TCP/UDP checksum. */
702
+ * csum_updated |= nfp_fl_csum_l4_to_flag (ip_proto );
703
+ }
590
704
if (set_ip6_dst .head .len_lw && set_ip6_src .head .len_lw ) {
591
705
/* TC compiles set src and dst IPv6 address as a single action,
592
706
* the hardware requires this to be 2 separate actions.
0 commit comments