@@ -89,6 +89,7 @@ struct mlxsw_sp_router {
89
89
struct delayed_work nexthop_probe_dw ;
90
90
#define MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL 5000 /* ms */
91
91
struct list_head nexthop_neighs_list ;
92
+ struct list_head ipip_list ;
92
93
bool aborted ;
93
94
struct notifier_block fib_nb ;
94
95
const struct mlxsw_sp_rif_ops * * rif_ops_arr ;
@@ -915,6 +916,170 @@ static u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev)
915
916
return l3mdev_fib_table (ol_dev ) ? : RT_TABLE_MAIN ;
916
917
}
917
918
919
+ static struct mlxsw_sp_rif *
920
+ mlxsw_sp_rif_create (struct mlxsw_sp * mlxsw_sp ,
921
+ const struct mlxsw_sp_rif_params * params );
922
+
923
+ static struct mlxsw_sp_rif_ipip_lb *
924
+ mlxsw_sp_ipip_ol_ipip_lb_create (struct mlxsw_sp * mlxsw_sp ,
925
+ enum mlxsw_sp_ipip_type ipipt ,
926
+ struct net_device * ol_dev )
927
+ {
928
+ struct mlxsw_sp_rif_params_ipip_lb lb_params ;
929
+ const struct mlxsw_sp_ipip_ops * ipip_ops ;
930
+ struct mlxsw_sp_rif * rif ;
931
+
932
+ ipip_ops = mlxsw_sp -> router -> ipip_ops_arr [ipipt ];
933
+ lb_params = (struct mlxsw_sp_rif_params_ipip_lb ) {
934
+ .common .dev = ol_dev ,
935
+ .common .lag = false,
936
+ .lb_config = ipip_ops -> ol_loopback_config (mlxsw_sp , ol_dev ),
937
+ };
938
+
939
+ rif = mlxsw_sp_rif_create (mlxsw_sp , & lb_params .common );
940
+ if (IS_ERR (rif ))
941
+ return ERR_CAST (rif );
942
+ return container_of (rif , struct mlxsw_sp_rif_ipip_lb , common );
943
+ }
944
+
945
+ static struct mlxsw_sp_ipip_entry *
946
+ mlxsw_sp_ipip_entry_alloc (struct mlxsw_sp * mlxsw_sp ,
947
+ enum mlxsw_sp_ipip_type ipipt ,
948
+ struct net_device * ol_dev )
949
+ {
950
+ struct mlxsw_sp_ipip_entry * ipip_entry ;
951
+ struct mlxsw_sp_ipip_entry * ret = NULL ;
952
+
953
+ ipip_entry = kzalloc (sizeof (* ipip_entry ), GFP_KERNEL );
954
+ if (!ipip_entry )
955
+ return ERR_PTR (- ENOMEM );
956
+
957
+ ipip_entry -> ol_lb = mlxsw_sp_ipip_ol_ipip_lb_create (mlxsw_sp , ipipt ,
958
+ ol_dev );
959
+ if (IS_ERR (ipip_entry -> ol_lb )) {
960
+ ret = ERR_CAST (ipip_entry -> ol_lb );
961
+ goto err_ol_ipip_lb_create ;
962
+ }
963
+
964
+ ipip_entry -> ipipt = ipipt ;
965
+ ipip_entry -> ol_dev = ol_dev ;
966
+
967
+ return ipip_entry ;
968
+
969
+ err_ol_ipip_lb_create :
970
+ kfree (ipip_entry );
971
+ return ret ;
972
+ }
973
+
974
+ static void
975
+ mlxsw_sp_ipip_entry_destroy (struct mlxsw_sp_ipip_entry * ipip_entry )
976
+ {
977
+ WARN_ON (ipip_entry -> ref_count > 0 );
978
+ mlxsw_sp_rif_destroy (& ipip_entry -> ol_lb -> common );
979
+ kfree (ipip_entry );
980
+ }
981
+
982
+ static __be32
983
+ mlxsw_sp_ipip_netdev_saddr4 (const struct net_device * ol_dev )
984
+ {
985
+ struct ip_tunnel * tun = netdev_priv (ol_dev );
986
+
987
+ return tun -> parms .iph .saddr ;
988
+ }
989
+
990
+ union mlxsw_sp_l3addr
991
+ mlxsw_sp_ipip_netdev_saddr (enum mlxsw_sp_l3proto proto ,
992
+ const struct net_device * ol_dev )
993
+ {
994
+ switch (proto ) {
995
+ case MLXSW_SP_L3_PROTO_IPV4 :
996
+ return (union mlxsw_sp_l3addr ) {
997
+ .addr4 = mlxsw_sp_ipip_netdev_saddr4 (ol_dev ),
998
+ };
999
+ case MLXSW_SP_L3_PROTO_IPV6 :
1000
+ break ;
1001
+ };
1002
+
1003
+ WARN_ON (1 );
1004
+ return (union mlxsw_sp_l3addr ) {
1005
+ .addr4 = 0 ,
1006
+ };
1007
+ }
1008
+
1009
+ static bool mlxsw_sp_l3addr_eq (const union mlxsw_sp_l3addr * addr1 ,
1010
+ const union mlxsw_sp_l3addr * addr2 )
1011
+ {
1012
+ return !memcmp (addr1 , addr2 , sizeof (* addr1 ));
1013
+ }
1014
+
1015
+ static bool
1016
+ mlxsw_sp_ipip_entry_saddr_matches (struct mlxsw_sp * mlxsw_sp ,
1017
+ const enum mlxsw_sp_l3proto ul_proto ,
1018
+ union mlxsw_sp_l3addr saddr ,
1019
+ u32 ul_tb_id ,
1020
+ struct mlxsw_sp_ipip_entry * ipip_entry )
1021
+ {
1022
+ u32 tun_ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id (ipip_entry -> ol_dev );
1023
+ enum mlxsw_sp_ipip_type ipipt = ipip_entry -> ipipt ;
1024
+ union mlxsw_sp_l3addr tun_saddr ;
1025
+
1026
+ if (mlxsw_sp -> router -> ipip_ops_arr [ipipt ]-> ul_proto != ul_proto )
1027
+ return false;
1028
+
1029
+ tun_saddr = mlxsw_sp_ipip_netdev_saddr (ul_proto , ipip_entry -> ol_dev );
1030
+ return tun_ul_tb_id == ul_tb_id &&
1031
+ mlxsw_sp_l3addr_eq (& tun_saddr , & saddr );
1032
+ }
1033
+
1034
+ static struct mlxsw_sp_ipip_entry *
1035
+ mlxsw_sp_ipip_entry_get (struct mlxsw_sp * mlxsw_sp ,
1036
+ enum mlxsw_sp_ipip_type ipipt ,
1037
+ struct net_device * ol_dev )
1038
+ {
1039
+ u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id (ol_dev );
1040
+ struct mlxsw_sp_router * router = mlxsw_sp -> router ;
1041
+ struct mlxsw_sp_ipip_entry * ipip_entry ;
1042
+ enum mlxsw_sp_l3proto ul_proto ;
1043
+ union mlxsw_sp_l3addr saddr ;
1044
+
1045
+ list_for_each_entry (ipip_entry , & mlxsw_sp -> router -> ipip_list ,
1046
+ ipip_list_node ) {
1047
+ if (ipip_entry -> ol_dev == ol_dev )
1048
+ goto inc_ref_count ;
1049
+
1050
+ /* The configuration where several tunnels have the same local
1051
+ * address in the same underlay table needs special treatment in
1052
+ * the HW. That is currently not implemented in the driver.
1053
+ */
1054
+ ul_proto = router -> ipip_ops_arr [ipip_entry -> ipipt ]-> ul_proto ;
1055
+ saddr = mlxsw_sp_ipip_netdev_saddr (ul_proto , ol_dev );
1056
+ if (mlxsw_sp_ipip_entry_saddr_matches (mlxsw_sp , ul_proto , saddr ,
1057
+ ul_tb_id , ipip_entry ))
1058
+ return ERR_PTR (- EEXIST );
1059
+ }
1060
+
1061
+ ipip_entry = mlxsw_sp_ipip_entry_alloc (mlxsw_sp , ipipt , ol_dev );
1062
+ if (IS_ERR (ipip_entry ))
1063
+ return ipip_entry ;
1064
+
1065
+ list_add_tail (& ipip_entry -> ipip_list_node ,
1066
+ & mlxsw_sp -> router -> ipip_list );
1067
+
1068
+ inc_ref_count :
1069
+ ++ ipip_entry -> ref_count ;
1070
+ return ipip_entry ;
1071
+ }
1072
+
1073
+ static void
1074
+ mlxsw_sp_ipip_entry_put (struct mlxsw_sp * mlxsw_sp ,
1075
+ struct mlxsw_sp_ipip_entry * ipip_entry )
1076
+ {
1077
+ if (-- ipip_entry -> ref_count == 0 ) {
1078
+ list_del (& ipip_entry -> ipip_list_node );
1079
+ mlxsw_sp_ipip_entry_destroy (ipip_entry );
1080
+ }
1081
+ }
1082
+
918
1083
struct mlxsw_sp_neigh_key {
919
1084
struct neighbour * n ;
920
1085
};
@@ -1654,6 +1819,7 @@ static void mlxsw_sp_neigh_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
1654
1819
1655
1820
enum mlxsw_sp_nexthop_type {
1656
1821
MLXSW_SP_NEXTHOP_TYPE_ETH ,
1822
+ MLXSW_SP_NEXTHOP_TYPE_IPIP ,
1657
1823
};
1658
1824
1659
1825
struct mlxsw_sp_nexthop_key {
@@ -1683,6 +1849,7 @@ struct mlxsw_sp_nexthop {
1683
1849
enum mlxsw_sp_nexthop_type type ;
1684
1850
union {
1685
1851
struct mlxsw_sp_neigh_entry * neigh_entry ;
1852
+ struct mlxsw_sp_ipip_entry * ipip_entry ;
1686
1853
};
1687
1854
};
1688
1855
@@ -1970,6 +2137,16 @@ static int mlxsw_sp_nexthop_mac_update(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
1970
2137
return mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (ratr ), ratr_pl );
1971
2138
}
1972
2139
2140
+ static int mlxsw_sp_nexthop_ipip_update (struct mlxsw_sp * mlxsw_sp ,
2141
+ u32 adj_index ,
2142
+ struct mlxsw_sp_nexthop * nh )
2143
+ {
2144
+ const struct mlxsw_sp_ipip_ops * ipip_ops ;
2145
+
2146
+ ipip_ops = mlxsw_sp -> router -> ipip_ops_arr [nh -> ipip_entry -> ipipt ];
2147
+ return ipip_ops -> nexthop_update (mlxsw_sp , adj_index , nh -> ipip_entry );
2148
+ }
2149
+
1973
2150
static int
1974
2151
mlxsw_sp_nexthop_group_update (struct mlxsw_sp * mlxsw_sp ,
1975
2152
struct mlxsw_sp_nexthop_group * nh_grp ,
@@ -1994,6 +2171,10 @@ mlxsw_sp_nexthop_group_update(struct mlxsw_sp *mlxsw_sp,
1994
2171
err = mlxsw_sp_nexthop_mac_update
1995
2172
(mlxsw_sp , adj_index , nh );
1996
2173
break ;
2174
+ case MLXSW_SP_NEXTHOP_TYPE_IPIP :
2175
+ err = mlxsw_sp_nexthop_ipip_update
2176
+ (mlxsw_sp , adj_index , nh );
2177
+ break ;
1997
2178
}
1998
2179
if (err )
1999
2180
return err ;
@@ -2297,6 +2478,46 @@ static bool mlxsw_sp_netdev_ipip_type(const struct mlxsw_sp *mlxsw_sp,
2297
2478
return false;
2298
2479
}
2299
2480
2481
+ static int mlxsw_sp_nexthop_ipip_init (struct mlxsw_sp * mlxsw_sp ,
2482
+ enum mlxsw_sp_ipip_type ipipt ,
2483
+ struct mlxsw_sp_nexthop * nh ,
2484
+ struct net_device * ol_dev )
2485
+ {
2486
+ if (!nh -> nh_grp -> gateway || nh -> ipip_entry )
2487
+ return 0 ;
2488
+
2489
+ nh -> ipip_entry = mlxsw_sp_ipip_entry_get (mlxsw_sp , ipipt , ol_dev );
2490
+ if (IS_ERR (nh -> ipip_entry ))
2491
+ return PTR_ERR (nh -> ipip_entry );
2492
+
2493
+ __mlxsw_sp_nexthop_neigh_update (nh , false);
2494
+ return 0 ;
2495
+ }
2496
+
2497
+ static void mlxsw_sp_nexthop_ipip_fini (struct mlxsw_sp * mlxsw_sp ,
2498
+ struct mlxsw_sp_nexthop * nh )
2499
+ {
2500
+ struct mlxsw_sp_ipip_entry * ipip_entry = nh -> ipip_entry ;
2501
+
2502
+ if (!ipip_entry )
2503
+ return ;
2504
+
2505
+ __mlxsw_sp_nexthop_neigh_update (nh , true);
2506
+ mlxsw_sp_ipip_entry_put (mlxsw_sp , ipip_entry );
2507
+ nh -> ipip_entry = NULL ;
2508
+ }
2509
+
2510
+ static bool mlxsw_sp_nexthop4_ipip_type (const struct mlxsw_sp * mlxsw_sp ,
2511
+ const struct fib_nh * fib_nh ,
2512
+ enum mlxsw_sp_ipip_type * p_ipipt )
2513
+ {
2514
+ struct net_device * dev = fib_nh -> nh_dev ;
2515
+
2516
+ return dev &&
2517
+ fib_nh -> nh_parent -> fib_type == RTN_UNICAST &&
2518
+ mlxsw_sp_netdev_ipip_type (mlxsw_sp , dev , p_ipipt );
2519
+ }
2520
+
2300
2521
static void mlxsw_sp_nexthop_type_fini (struct mlxsw_sp * mlxsw_sp ,
2301
2522
struct mlxsw_sp_nexthop * nh )
2302
2523
{
@@ -2305,17 +2526,29 @@ static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
2305
2526
mlxsw_sp_nexthop_neigh_fini (mlxsw_sp , nh );
2306
2527
mlxsw_sp_nexthop_rif_fini (nh );
2307
2528
break ;
2529
+ case MLXSW_SP_NEXTHOP_TYPE_IPIP :
2530
+ mlxsw_sp_nexthop_ipip_fini (mlxsw_sp , nh );
2531
+ break ;
2308
2532
}
2309
2533
}
2310
2534
2311
2535
static int mlxsw_sp_nexthop4_type_init (struct mlxsw_sp * mlxsw_sp ,
2312
2536
struct mlxsw_sp_nexthop * nh ,
2313
2537
struct fib_nh * fib_nh )
2314
2538
{
2539
+ struct mlxsw_sp_router * router = mlxsw_sp -> router ;
2315
2540
struct net_device * dev = fib_nh -> nh_dev ;
2541
+ enum mlxsw_sp_ipip_type ipipt ;
2316
2542
struct mlxsw_sp_rif * rif ;
2317
2543
int err ;
2318
2544
2545
+ if (mlxsw_sp_nexthop4_ipip_type (mlxsw_sp , fib_nh , & ipipt ) &&
2546
+ router -> ipip_ops_arr [ipipt ]-> can_offload (mlxsw_sp , dev ,
2547
+ MLXSW_SP_L3_PROTO_IPV4 )) {
2548
+ nh -> type = MLXSW_SP_NEXTHOP_TYPE_IPIP ;
2549
+ return mlxsw_sp_nexthop_ipip_init (mlxsw_sp , ipipt , nh , dev );
2550
+ }
2551
+
2319
2552
nh -> type = MLXSW_SP_NEXTHOP_TYPE_ETH ;
2320
2553
rif = mlxsw_sp_rif_find_by_dev (mlxsw_sp , dev );
2321
2554
if (!rif )
@@ -2421,7 +2654,8 @@ static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
2421
2654
static bool mlxsw_sp_fi_is_gateway (const struct mlxsw_sp * mlxsw_sp ,
2422
2655
const struct fib_info * fi )
2423
2656
{
2424
- return fi -> fib_nh -> nh_scope == RT_SCOPE_LINK ;
2657
+ return fi -> fib_nh -> nh_scope == RT_SCOPE_LINK ||
2658
+ mlxsw_sp_nexthop4_ipip_type (mlxsw_sp , fi -> fib_nh , NULL );
2425
2659
}
2426
2660
2427
2661
static struct mlxsw_sp_nexthop_group *
@@ -5411,11 +5645,13 @@ static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp)
5411
5645
static int mlxsw_sp_ipips_init (struct mlxsw_sp * mlxsw_sp )
5412
5646
{
5413
5647
mlxsw_sp -> router -> ipip_ops_arr = mlxsw_sp_ipip_ops_arr ;
5648
+ INIT_LIST_HEAD (& mlxsw_sp -> router -> ipip_list );
5414
5649
return 0 ;
5415
5650
}
5416
5651
5417
5652
static void mlxsw_sp_ipips_fini (struct mlxsw_sp * mlxsw_sp )
5418
5653
{
5654
+ WARN_ON (!list_empty (& mlxsw_sp -> router -> ipip_list ));
5419
5655
}
5420
5656
5421
5657
static void mlxsw_sp_router_fib_dump_flush (struct notifier_block * nb )
0 commit comments