Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mlxsw: spectrum_router: Prevent incorrect replacement of local table routes

The driver uses the same table to represent both the main and local
routing tables. Prevent routes in the main table from replacing routes
in the local table to reflect the fact that the local table is consulted
first during lookup.

Fixes: b6a1d871d37a ("mlxsw: spectrum_router: Start using new IPv4 route notifications")
Fixes: dacad7b34b59 ("mlxsw: spectrum_router: Start using new IPv6 route notifications")
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ido Schimmel and committed by
David S. Miller
0508ff89 f8c2afa6

+51 -1
+51 -1
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
··· 4844 4844 fib_node->fib_entry = NULL; 4845 4845 } 4846 4846 4847 + static bool mlxsw_sp_fib4_allow_replace(struct mlxsw_sp_fib4_entry *fib4_entry) 4848 + { 4849 + struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node; 4850 + struct mlxsw_sp_fib4_entry *fib4_replaced; 4851 + 4852 + if (!fib_node->fib_entry) 4853 + return true; 4854 + 4855 + fib4_replaced = container_of(fib_node->fib_entry, 4856 + struct mlxsw_sp_fib4_entry, common); 4857 + if (fib4_entry->tb_id == RT_TABLE_MAIN && 4858 + fib4_replaced->tb_id == RT_TABLE_LOCAL) 4859 + return false; 4860 + 4861 + return true; 4862 + } 4863 + 4847 4864 static int 4848 4865 mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp, 4849 4866 const struct fib_entry_notifier_info *fen_info) ··· 4887 4870 dev_warn(mlxsw_sp->bus_info->dev, "Failed to create FIB entry\n"); 4888 4871 err = PTR_ERR(fib4_entry); 4889 4872 goto err_fib4_entry_create; 4873 + } 4874 + 4875 + if (!mlxsw_sp_fib4_allow_replace(fib4_entry)) { 4876 + mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry); 4877 + mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); 4878 + return 0; 4890 4879 } 4891 4880 4892 4881 replaced = fib_node->fib_entry; ··· 4931 4908 return; 4932 4909 4933 4910 fib4_entry = mlxsw_sp_fib4_entry_lookup(mlxsw_sp, fen_info); 4934 - if (WARN_ON(!fib4_entry)) 4911 + if (!fib4_entry) 4935 4912 return; 4936 4913 fib_node = fib4_entry->common.fib_node; 4937 4914 ··· 5431 5408 return NULL; 5432 5409 } 5433 5410 5411 + static bool mlxsw_sp_fib6_allow_replace(struct mlxsw_sp_fib6_entry *fib6_entry) 5412 + { 5413 + struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node; 5414 + struct mlxsw_sp_fib6_entry *fib6_replaced; 5415 + struct fib6_info *rt, *rt_replaced; 5416 + 5417 + if (!fib_node->fib_entry) 5418 + return true; 5419 + 5420 + fib6_replaced = container_of(fib_node->fib_entry, 5421 + struct mlxsw_sp_fib6_entry, 5422 + common); 5423 + rt = mlxsw_sp_fib6_entry_rt(fib6_entry); 5424 + rt_replaced = mlxsw_sp_fib6_entry_rt(fib6_replaced); 5425 + if (rt->fib6_table->tb6_id == RT_TABLE_MAIN && 5426 + rt_replaced->fib6_table->tb6_id == RT_TABLE_LOCAL) 5427 + return false; 5428 + 5429 + return true; 5430 + } 5431 + 5434 5432 static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp, 5435 5433 struct fib6_info **rt_arr, 5436 5434 unsigned int nrt6) ··· 5484 5440 if (IS_ERR(fib6_entry)) { 5485 5441 err = PTR_ERR(fib6_entry); 5486 5442 goto err_fib6_entry_create; 5443 + } 5444 + 5445 + if (!mlxsw_sp_fib6_allow_replace(fib6_entry)) { 5446 + mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry); 5447 + mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); 5448 + return 0; 5487 5449 } 5488 5450 5489 5451 replaced = fib_node->fib_entry;