49
49
50
50
static const char mlx5e_rep_driver_name [] = "mlx5e_rep" ;
51
51
52
+ struct mlx5e_rep_indr_block_priv {
53
+ struct net_device * netdev ;
54
+ struct mlx5e_rep_priv * rpriv ;
55
+
56
+ struct list_head list ;
57
+ };
58
+
59
+ static void mlx5e_rep_indr_unregister_block (struct net_device * netdev );
60
+
52
61
static void mlx5e_rep_get_drvinfo (struct net_device * dev ,
53
62
struct ethtool_drvinfo * drvinfo )
54
63
{
@@ -518,6 +527,166 @@ static void mlx5e_rep_neigh_update(struct work_struct *work)
518
527
neigh_release (n );
519
528
}
520
529
530
+ static struct mlx5e_rep_indr_block_priv *
531
+ mlx5e_rep_indr_block_priv_lookup (struct mlx5e_rep_priv * rpriv ,
532
+ struct net_device * netdev )
533
+ {
534
+ struct mlx5e_rep_indr_block_priv * cb_priv ;
535
+
536
+ /* All callback list access should be protected by RTNL. */
537
+ ASSERT_RTNL ();
538
+
539
+ list_for_each_entry (cb_priv ,
540
+ & rpriv -> uplink_priv .tc_indr_block_priv_list ,
541
+ list )
542
+ if (cb_priv -> netdev == netdev )
543
+ return cb_priv ;
544
+
545
+ return NULL ;
546
+ }
547
+
548
+ static void mlx5e_rep_indr_clean_block_privs (struct mlx5e_rep_priv * rpriv )
549
+ {
550
+ struct mlx5e_rep_indr_block_priv * cb_priv , * temp ;
551
+ struct list_head * head = & rpriv -> uplink_priv .tc_indr_block_priv_list ;
552
+
553
+ list_for_each_entry_safe (cb_priv , temp , head , list ) {
554
+ mlx5e_rep_indr_unregister_block (cb_priv -> netdev );
555
+ kfree (cb_priv );
556
+ }
557
+ }
558
+
559
+ static int
560
+ mlx5e_rep_indr_offload (struct net_device * netdev ,
561
+ struct tc_cls_flower_offload * flower ,
562
+ struct mlx5e_rep_indr_block_priv * indr_priv )
563
+ {
564
+ return - EOPNOTSUPP ;
565
+ }
566
+
567
+ static int mlx5e_rep_indr_setup_block_cb (enum tc_setup_type type ,
568
+ void * type_data , void * indr_priv )
569
+ {
570
+ struct mlx5e_rep_indr_block_priv * priv = indr_priv ;
571
+
572
+ switch (type ) {
573
+ case TC_SETUP_CLSFLOWER :
574
+ return mlx5e_rep_indr_offload (priv -> netdev , type_data , priv );
575
+ default :
576
+ return - EOPNOTSUPP ;
577
+ }
578
+ }
579
+
580
+ static int
581
+ mlx5e_rep_indr_setup_tc_block (struct net_device * netdev ,
582
+ struct mlx5e_rep_priv * rpriv ,
583
+ struct tc_block_offload * f )
584
+ {
585
+ struct mlx5e_rep_indr_block_priv * indr_priv ;
586
+ int err = 0 ;
587
+
588
+ if (f -> binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS )
589
+ return - EOPNOTSUPP ;
590
+
591
+ switch (f -> command ) {
592
+ case TC_BLOCK_BIND :
593
+ indr_priv = mlx5e_rep_indr_block_priv_lookup (rpriv , netdev );
594
+ if (indr_priv )
595
+ return - EEXIST ;
596
+
597
+ indr_priv = kmalloc (sizeof (* indr_priv ), GFP_KERNEL );
598
+ if (!indr_priv )
599
+ return - ENOMEM ;
600
+
601
+ indr_priv -> netdev = netdev ;
602
+ indr_priv -> rpriv = rpriv ;
603
+ list_add (& indr_priv -> list ,
604
+ & rpriv -> uplink_priv .tc_indr_block_priv_list );
605
+
606
+ err = tcf_block_cb_register (f -> block ,
607
+ mlx5e_rep_indr_setup_block_cb ,
608
+ netdev , indr_priv , f -> extack );
609
+ if (err ) {
610
+ list_del (& indr_priv -> list );
611
+ kfree (indr_priv );
612
+ }
613
+
614
+ return err ;
615
+ case TC_BLOCK_UNBIND :
616
+ tcf_block_cb_unregister (f -> block ,
617
+ mlx5e_rep_indr_setup_block_cb ,
618
+ netdev );
619
+ indr_priv = mlx5e_rep_indr_block_priv_lookup (rpriv , netdev );
620
+ if (indr_priv ) {
621
+ list_del (& indr_priv -> list );
622
+ kfree (indr_priv );
623
+ }
624
+
625
+ return 0 ;
626
+ default :
627
+ return - EOPNOTSUPP ;
628
+ }
629
+ return 0 ;
630
+ }
631
+
632
+ static
633
+ int mlx5e_rep_indr_setup_tc_cb (struct net_device * netdev , void * cb_priv ,
634
+ enum tc_setup_type type , void * type_data )
635
+ {
636
+ switch (type ) {
637
+ case TC_SETUP_BLOCK :
638
+ return mlx5e_rep_indr_setup_tc_block (netdev , cb_priv ,
639
+ type_data );
640
+ default :
641
+ return - EOPNOTSUPP ;
642
+ }
643
+ }
644
+
645
+ static int mlx5e_rep_indr_register_block (struct mlx5e_rep_priv * rpriv ,
646
+ struct net_device * netdev )
647
+ {
648
+ int err ;
649
+
650
+ err = __tc_indr_block_cb_register (netdev , rpriv ,
651
+ mlx5e_rep_indr_setup_tc_cb ,
652
+ netdev );
653
+ if (err ) {
654
+ struct mlx5e_priv * priv = netdev_priv (rpriv -> netdev );
655
+
656
+ mlx5_core_err (priv -> mdev , "Failed to register remote block notifier for %s err=%d\n" ,
657
+ netdev_name (netdev ), err );
658
+ }
659
+ return err ;
660
+ }
661
+
662
+ static void mlx5e_rep_indr_unregister_block (struct net_device * netdev )
663
+ {
664
+ __tc_indr_block_cb_unregister (netdev , mlx5e_rep_indr_setup_tc_cb ,
665
+ netdev );
666
+ }
667
+
668
+ static int mlx5e_nic_rep_netdevice_event (struct notifier_block * nb ,
669
+ unsigned long event , void * ptr )
670
+ {
671
+ struct mlx5e_rep_priv * rpriv = container_of (nb , struct mlx5e_rep_priv ,
672
+ uplink_priv .netdevice_nb );
673
+ struct mlx5e_priv * priv = netdev_priv (rpriv -> netdev );
674
+ struct net_device * netdev = netdev_notifier_info_to_dev (ptr );
675
+
676
+ if (!mlx5e_tc_tun_device_to_offload (priv , netdev ))
677
+ return NOTIFY_OK ;
678
+
679
+ switch (event ) {
680
+ case NETDEV_REGISTER :
681
+ mlx5e_rep_indr_register_block (rpriv , netdev );
682
+ break ;
683
+ case NETDEV_UNREGISTER :
684
+ mlx5e_rep_indr_unregister_block (netdev );
685
+ break ;
686
+ }
687
+ return NOTIFY_OK ;
688
+ }
689
+
521
690
static struct mlx5e_neigh_hash_entry *
522
691
mlx5e_rep_neigh_entry_lookup (struct mlx5e_priv * priv ,
523
692
struct mlx5e_neigh * m_neigh );
@@ -1262,8 +1431,19 @@ mlx5e_nic_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
1262
1431
if (err )
1263
1432
goto err_neigh_cleanup ;
1264
1433
1434
+ /* init indirect block notifications */
1435
+ INIT_LIST_HEAD (& uplink_priv -> tc_indr_block_priv_list );
1436
+ uplink_priv -> netdevice_nb .notifier_call = mlx5e_nic_rep_netdevice_event ;
1437
+ err = register_netdevice_notifier (& uplink_priv -> netdevice_nb );
1438
+ if (err ) {
1439
+ mlx5_core_err (priv -> mdev , "Failed to register netdev notifier\n" );
1440
+ goto err_indirect_block_cleanup ;
1441
+ }
1442
+
1265
1443
return 0 ;
1266
1444
1445
+ err_indirect_block_cleanup :
1446
+ mlx5e_tc_esw_cleanup (& uplink_priv -> tc_ht );
1267
1447
err_neigh_cleanup :
1268
1448
mlx5e_rep_neigh_cleanup (rpriv );
1269
1449
err_remove_sqs :
@@ -1280,6 +1460,10 @@ mlx5e_nic_rep_unload(struct mlx5_eswitch_rep *rep)
1280
1460
if (test_bit (MLX5E_STATE_OPENED , & priv -> state ))
1281
1461
mlx5e_remove_sqs_fwd_rules (priv );
1282
1462
1463
+ /* clean indirect TC block notifications */
1464
+ unregister_netdevice_notifier (& rpriv -> uplink_priv .netdevice_nb );
1465
+ mlx5e_rep_indr_clean_block_privs (rpriv );
1466
+
1283
1467
/* clean uplink offloaded TC rules, delete shared tc flow table */
1284
1468
mlx5e_tc_esw_cleanup (& rpriv -> uplink_priv .tc_ht );
1285
1469
0 commit comments