@@ -2128,15 +2128,20 @@ static int mlxsw_sp_fib4_node_list_append(struct mlxsw_sp_fib_entry *fib_entry,
2128
2128
static int
2129
2129
mlxsw_sp_fib4_node_list_insert (struct mlxsw_sp_fib_node * fib_node ,
2130
2130
struct mlxsw_sp_fib_entry * new_entry ,
2131
- bool append )
2131
+ bool replace , bool append )
2132
2132
{
2133
2133
struct mlxsw_sp_fib_entry * fib_entry ;
2134
2134
2135
2135
fib_entry = mlxsw_sp_fib4_node_entry_find (fib_node , & new_entry -> params );
2136
2136
2137
2137
if (append )
2138
2138
return mlxsw_sp_fib4_node_list_append (fib_entry , new_entry );
2139
+ if (replace && WARN_ON (!fib_entry ))
2140
+ return - EINVAL ;
2139
2141
2142
+ /* Insert new entry before replaced one, so that we can later
2143
+ * remove the second.
2144
+ */
2140
2145
if (fib_entry ) {
2141
2146
list_add_tail (& new_entry -> list , & fib_entry -> list );
2142
2147
} else {
@@ -2207,12 +2212,13 @@ mlxsw_sp_fib4_node_entry_del(struct mlxsw_sp *mlxsw_sp,
2207
2212
2208
2213
static int mlxsw_sp_fib4_node_entry_link (struct mlxsw_sp * mlxsw_sp ,
2209
2214
struct mlxsw_sp_fib_entry * fib_entry ,
2210
- bool append )
2215
+ bool replace , bool append )
2211
2216
{
2212
2217
struct mlxsw_sp_fib_node * fib_node = fib_entry -> fib_node ;
2213
2218
int err ;
2214
2219
2215
- err = mlxsw_sp_fib4_node_list_insert (fib_node , fib_entry , append );
2220
+ err = mlxsw_sp_fib4_node_list_insert (fib_node , fib_entry , replace ,
2221
+ append );
2216
2222
if (err )
2217
2223
return err ;
2218
2224
@@ -2240,10 +2246,28 @@ mlxsw_sp_fib4_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
2240
2246
mlxsw_sp_fib4_node_list_remove (fib_entry );
2241
2247
}
2242
2248
2249
+ static void mlxsw_sp_fib4_entry_replace (struct mlxsw_sp * mlxsw_sp ,
2250
+ struct mlxsw_sp_fib_entry * fib_entry ,
2251
+ bool replace )
2252
+ {
2253
+ struct mlxsw_sp_fib_node * fib_node = fib_entry -> fib_node ;
2254
+ struct mlxsw_sp_fib_entry * replaced ;
2255
+
2256
+ if (!replace )
2257
+ return ;
2258
+
2259
+ /* We inserted the new entry before replaced one */
2260
+ replaced = list_next_entry (fib_entry , list );
2261
+
2262
+ mlxsw_sp_fib4_node_entry_unlink (mlxsw_sp , replaced );
2263
+ mlxsw_sp_fib4_entry_destroy (mlxsw_sp , replaced );
2264
+ mlxsw_sp_fib4_node_put (mlxsw_sp , fib_node );
2265
+ }
2266
+
2243
2267
static int
2244
2268
mlxsw_sp_router_fib4_add (struct mlxsw_sp * mlxsw_sp ,
2245
2269
const struct fib_entry_notifier_info * fen_info ,
2246
- bool append )
2270
+ bool replace , bool append )
2247
2271
{
2248
2272
struct mlxsw_sp_fib_entry * fib_entry ;
2249
2273
struct mlxsw_sp_fib_node * fib_node ;
@@ -2265,12 +2289,15 @@ mlxsw_sp_router_fib4_add(struct mlxsw_sp *mlxsw_sp,
2265
2289
goto err_fib4_entry_create ;
2266
2290
}
2267
2291
2268
- err = mlxsw_sp_fib4_node_entry_link (mlxsw_sp , fib_entry , append );
2292
+ err = mlxsw_sp_fib4_node_entry_link (mlxsw_sp , fib_entry , replace ,
2293
+ append );
2269
2294
if (err ) {
2270
2295
dev_warn (mlxsw_sp -> bus_info -> dev , "Failed to link FIB entry to node\n" );
2271
2296
goto err_fib4_node_entry_link ;
2272
2297
}
2273
2298
2299
+ mlxsw_sp_fib4_entry_replace (mlxsw_sp , fib_entry , replace );
2300
+
2274
2301
return 0 ;
2275
2302
2276
2303
err_fib4_node_entry_link :
@@ -2479,17 +2506,19 @@ static void mlxsw_sp_router_fib_event_work(struct work_struct *work)
2479
2506
struct mlxsw_sp_fib_event_work * fib_work =
2480
2507
container_of (work , struct mlxsw_sp_fib_event_work , work );
2481
2508
struct mlxsw_sp * mlxsw_sp = fib_work -> mlxsw_sp ;
2482
- bool append ;
2509
+ bool replace , append ;
2483
2510
int err ;
2484
2511
2485
2512
/* Protect internal structures from changes */
2486
2513
rtnl_lock ();
2487
2514
switch (fib_work -> event ) {
2515
+ case FIB_EVENT_ENTRY_REPLACE : /* fall through */
2488
2516
case FIB_EVENT_ENTRY_APPEND : /* fall through */
2489
2517
case FIB_EVENT_ENTRY_ADD :
2518
+ replace = fib_work -> event == FIB_EVENT_ENTRY_REPLACE ;
2490
2519
append = fib_work -> event == FIB_EVENT_ENTRY_APPEND ;
2491
2520
err = mlxsw_sp_router_fib4_add (mlxsw_sp , & fib_work -> fen_info ,
2492
- append );
2521
+ replace , append );
2493
2522
if (err )
2494
2523
mlxsw_sp_router_fib4_abort (mlxsw_sp );
2495
2524
fib_info_put (fib_work -> fen_info .fi );
@@ -2533,6 +2562,7 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
2533
2562
fib_work -> event = event ;
2534
2563
2535
2564
switch (event ) {
2565
+ case FIB_EVENT_ENTRY_REPLACE : /* fall through */
2536
2566
case FIB_EVENT_ENTRY_APPEND : /* fall through */
2537
2567
case FIB_EVENT_ENTRY_ADD : /* fall through */
2538
2568
case FIB_EVENT_ENTRY_DEL :
0 commit comments