@@ -381,6 +381,14 @@ enum mlxsw_sp_fib_entry_type {
381
381
MLXSW_SP_FIB_ENTRY_TYPE_REMOTE ,
382
382
MLXSW_SP_FIB_ENTRY_TYPE_LOCAL ,
383
383
MLXSW_SP_FIB_ENTRY_TYPE_TRAP ,
384
+
385
+ /* This is a special case of local delivery, where a packet should be
386
+ * decapsulated on reception. Note that there is no corresponding ENCAP,
387
+ * because that's a type of next hop, not of FIB entry. (There can be
388
+ * several next hops in a REMOTE entry, and some of them may be
389
+ * encapsulating entries.)
390
+ */
391
+ MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP ,
384
392
};
385
393
386
394
struct mlxsw_sp_nexthop_group ;
@@ -394,12 +402,18 @@ struct mlxsw_sp_fib_node {
394
402
struct mlxsw_sp_fib_key key ;
395
403
};
396
404
405
+ struct mlxsw_sp_fib_entry_decap {
406
+ struct mlxsw_sp_ipip_entry * ipip_entry ;
407
+ u32 tunnel_index ;
408
+ };
409
+
397
410
struct mlxsw_sp_fib_entry {
398
411
struct list_head list ;
399
412
struct mlxsw_sp_fib_node * fib_node ;
400
413
enum mlxsw_sp_fib_entry_type type ;
401
414
struct list_head nexthop_group_node ;
402
415
struct mlxsw_sp_nexthop_group * nh_group ;
416
+ struct mlxsw_sp_fib_entry_decap decap ; /* Valid for decap entries. */
403
417
};
404
418
405
419
struct mlxsw_sp_fib4_entry {
@@ -1031,6 +1045,48 @@ mlxsw_sp_ipip_entry_saddr_matches(struct mlxsw_sp *mlxsw_sp,
1031
1045
mlxsw_sp_l3addr_eq (& tun_saddr , & saddr );
1032
1046
}
1033
1047
1048
+ static int
1049
+ mlxsw_sp_fib_entry_decap_init (struct mlxsw_sp * mlxsw_sp ,
1050
+ struct mlxsw_sp_fib_entry * fib_entry ,
1051
+ struct mlxsw_sp_ipip_entry * ipip_entry )
1052
+ {
1053
+ u32 tunnel_index ;
1054
+ int err ;
1055
+
1056
+ err = mlxsw_sp_kvdl_alloc (mlxsw_sp , 1 , & tunnel_index );
1057
+ if (err )
1058
+ return err ;
1059
+
1060
+ ipip_entry -> decap_fib_entry = fib_entry ;
1061
+ fib_entry -> decap .ipip_entry = ipip_entry ;
1062
+ fib_entry -> decap .tunnel_index = tunnel_index ;
1063
+ return 0 ;
1064
+ }
1065
+
1066
+ static void mlxsw_sp_fib_entry_decap_fini (struct mlxsw_sp * mlxsw_sp ,
1067
+ struct mlxsw_sp_fib_entry * fib_entry )
1068
+ {
1069
+ /* Unlink this node from the IPIP entry that it's the decap entry of. */
1070
+ fib_entry -> decap .ipip_entry -> decap_fib_entry = NULL ;
1071
+ fib_entry -> decap .ipip_entry = NULL ;
1072
+ mlxsw_sp_kvdl_free (mlxsw_sp , fib_entry -> decap .tunnel_index );
1073
+ }
1074
+
1075
+ static int mlxsw_sp_fib_entry_update (struct mlxsw_sp * mlxsw_sp ,
1076
+ struct mlxsw_sp_fib_entry * fib_entry );
1077
+
1078
+ static void
1079
+ mlxsw_sp_ipip_entry_demote_decap (struct mlxsw_sp * mlxsw_sp ,
1080
+ struct mlxsw_sp_ipip_entry * ipip_entry )
1081
+ {
1082
+ struct mlxsw_sp_fib_entry * fib_entry = ipip_entry -> decap_fib_entry ;
1083
+
1084
+ mlxsw_sp_fib_entry_decap_fini (mlxsw_sp , fib_entry );
1085
+ fib_entry -> type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP ;
1086
+
1087
+ mlxsw_sp_fib_entry_update (mlxsw_sp , fib_entry );
1088
+ }
1089
+
1034
1090
static struct mlxsw_sp_ipip_entry *
1035
1091
mlxsw_sp_ipip_entry_get (struct mlxsw_sp * mlxsw_sp ,
1036
1092
enum mlxsw_sp_ipip_type ipipt ,
@@ -1076,10 +1132,51 @@ mlxsw_sp_ipip_entry_put(struct mlxsw_sp *mlxsw_sp,
1076
1132
{
1077
1133
if (-- ipip_entry -> ref_count == 0 ) {
1078
1134
list_del (& ipip_entry -> ipip_list_node );
1135
+ if (ipip_entry -> decap_fib_entry )
1136
+ mlxsw_sp_ipip_entry_demote_decap (mlxsw_sp , ipip_entry );
1079
1137
mlxsw_sp_ipip_entry_destroy (ipip_entry );
1080
1138
}
1081
1139
}
1082
1140
1141
+ static bool
1142
+ mlxsw_sp_ipip_entry_matches_decap (struct mlxsw_sp * mlxsw_sp ,
1143
+ const struct net_device * ul_dev ,
1144
+ enum mlxsw_sp_l3proto ul_proto ,
1145
+ union mlxsw_sp_l3addr ul_dip ,
1146
+ struct mlxsw_sp_ipip_entry * ipip_entry )
1147
+ {
1148
+ u32 ul_tb_id = l3mdev_fib_table (ul_dev ) ? : RT_TABLE_MAIN ;
1149
+ enum mlxsw_sp_ipip_type ipipt = ipip_entry -> ipipt ;
1150
+ struct net_device * ipip_ul_dev ;
1151
+
1152
+ if (mlxsw_sp -> router -> ipip_ops_arr [ipipt ]-> ul_proto != ul_proto )
1153
+ return false;
1154
+
1155
+ ipip_ul_dev = __mlxsw_sp_ipip_netdev_ul_dev_get (ipip_entry -> ol_dev );
1156
+ return mlxsw_sp_ipip_entry_saddr_matches (mlxsw_sp , ul_proto , ul_dip ,
1157
+ ul_tb_id , ipip_entry ) &&
1158
+ (!ipip_ul_dev || ipip_ul_dev == ul_dev );
1159
+ }
1160
+
1161
+ /* Given decap parameters, find the corresponding IPIP entry. */
1162
+ static struct mlxsw_sp_ipip_entry *
1163
+ mlxsw_sp_ipip_entry_find_by_decap (struct mlxsw_sp * mlxsw_sp ,
1164
+ const struct net_device * ul_dev ,
1165
+ enum mlxsw_sp_l3proto ul_proto ,
1166
+ union mlxsw_sp_l3addr ul_dip )
1167
+ {
1168
+ struct mlxsw_sp_ipip_entry * ipip_entry ;
1169
+
1170
+ list_for_each_entry (ipip_entry , & mlxsw_sp -> router -> ipip_list ,
1171
+ ipip_list_node )
1172
+ if (mlxsw_sp_ipip_entry_matches_decap (mlxsw_sp , ul_dev ,
1173
+ ul_proto , ul_dip ,
1174
+ ipip_entry ))
1175
+ return ipip_entry ;
1176
+
1177
+ return NULL ;
1178
+ }
1179
+
1083
1180
struct mlxsw_sp_neigh_key {
1084
1181
struct neighbour * n ;
1085
1182
};
@@ -2186,9 +2283,6 @@ mlxsw_sp_nexthop_group_update(struct mlxsw_sp *mlxsw_sp,
2186
2283
return 0 ;
2187
2284
}
2188
2285
2189
- static int mlxsw_sp_fib_entry_update (struct mlxsw_sp * mlxsw_sp ,
2190
- struct mlxsw_sp_fib_entry * fib_entry );
2191
-
2192
2286
static bool
2193
2287
mlxsw_sp_fib_node_entry_is_first (const struct mlxsw_sp_fib_node * fib_node ,
2194
2288
const struct mlxsw_sp_fib_entry * fib_entry );
@@ -2779,6 +2873,8 @@ mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
2779
2873
return !!nh_group -> adj_index_valid ;
2780
2874
case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL :
2781
2875
return !!nh_group -> nh_rif ;
2876
+ case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP :
2877
+ return true;
2782
2878
default :
2783
2879
return false;
2784
2880
}
@@ -2810,7 +2906,8 @@ mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
2810
2906
struct mlxsw_sp_nexthop_group * nh_grp = fib_entry -> nh_group ;
2811
2907
int i ;
2812
2908
2813
- if (fib_entry -> type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL ) {
2909
+ if (fib_entry -> type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL ||
2910
+ fib_entry -> type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP ) {
2814
2911
nh_grp -> nexthops -> key .fib_nh -> nh_flags |= RTNH_F_OFFLOAD ;
2815
2912
return ;
2816
2913
}
@@ -3015,6 +3112,22 @@ static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp *mlxsw_sp,
3015
3112
return mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (ralue ), ralue_pl );
3016
3113
}
3017
3114
3115
+ static int
3116
+ mlxsw_sp_fib_entry_op_ipip_decap (struct mlxsw_sp * mlxsw_sp ,
3117
+ struct mlxsw_sp_fib_entry * fib_entry ,
3118
+ enum mlxsw_reg_ralue_op op )
3119
+ {
3120
+ struct mlxsw_sp_ipip_entry * ipip_entry = fib_entry -> decap .ipip_entry ;
3121
+ const struct mlxsw_sp_ipip_ops * ipip_ops ;
3122
+
3123
+ if (WARN_ON (!ipip_entry ))
3124
+ return - EINVAL ;
3125
+
3126
+ ipip_ops = mlxsw_sp -> router -> ipip_ops_arr [ipip_entry -> ipipt ];
3127
+ return ipip_ops -> fib_entry_op (mlxsw_sp , ipip_entry , op ,
3128
+ fib_entry -> decap .tunnel_index );
3129
+ }
3130
+
3018
3131
static int __mlxsw_sp_fib_entry_op (struct mlxsw_sp * mlxsw_sp ,
3019
3132
struct mlxsw_sp_fib_entry * fib_entry ,
3020
3133
enum mlxsw_reg_ralue_op op )
@@ -3026,6 +3139,9 @@ static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
3026
3139
return mlxsw_sp_fib_entry_op_local (mlxsw_sp , fib_entry , op );
3027
3140
case MLXSW_SP_FIB_ENTRY_TYPE_TRAP :
3028
3141
return mlxsw_sp_fib_entry_op_trap (mlxsw_sp , fib_entry , op );
3142
+ case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP :
3143
+ return mlxsw_sp_fib_entry_op_ipip_decap (mlxsw_sp ,
3144
+ fib_entry , op );
3029
3145
}
3030
3146
return - EINVAL ;
3031
3147
}
@@ -3060,11 +3176,23 @@ mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp,
3060
3176
const struct fib_entry_notifier_info * fen_info ,
3061
3177
struct mlxsw_sp_fib_entry * fib_entry )
3062
3178
{
3179
+ union mlxsw_sp_l3addr dip = { .addr4 = htonl (fen_info -> dst ) };
3180
+ struct net_device * dev = fen_info -> fi -> fib_dev ;
3181
+ struct mlxsw_sp_ipip_entry * ipip_entry ;
3063
3182
struct fib_info * fi = fen_info -> fi ;
3064
3183
3065
3184
switch (fen_info -> type ) {
3066
- case RTN_BROADCAST : /* fall through */
3067
3185
case RTN_LOCAL :
3186
+ ipip_entry = mlxsw_sp_ipip_entry_find_by_decap (mlxsw_sp , dev ,
3187
+ MLXSW_SP_L3_PROTO_IPV4 , dip );
3188
+ if (ipip_entry ) {
3189
+ fib_entry -> type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP ;
3190
+ return mlxsw_sp_fib_entry_decap_init (mlxsw_sp ,
3191
+ fib_entry ,
3192
+ ipip_entry );
3193
+ }
3194
+ /* fall through */
3195
+ case RTN_BROADCAST :
3068
3196
fib_entry -> type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP ;
3069
3197
return 0 ;
3070
3198
case RTN_UNREACHABLE : /* fall through */
@@ -3557,6 +3685,9 @@ mlxsw_sp_fib4_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
3557
3685
{
3558
3686
mlxsw_sp_fib_node_entry_del (mlxsw_sp , & fib4_entry -> common );
3559
3687
mlxsw_sp_fib4_node_list_remove (fib4_entry );
3688
+
3689
+ if (fib4_entry -> common .type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP )
3690
+ mlxsw_sp_fib_entry_decap_fini (mlxsw_sp , & fib4_entry -> common );
3560
3691
}
3561
3692
3562
3693
static void mlxsw_sp_fib4_entry_replace (struct mlxsw_sp * mlxsw_sp ,
0 commit comments