Skip to content

Commit e036c58

Browse files
committed
Merge branch 'mlxsw-Various-fixes'
Ido Schimmel says: ==================== mlxsw: Various fixes This patch set contains various fixes for the mlxsw driver. Patch #1 fixes an issue introduced in 5.6 in which a route in the main table can replace an identical route in the local table despite the local table having an higher precedence. Patch #2 contains a test case for the bug fixed in patch #1. Patch #3 also fixes an issue introduced in 5.6 in which the driver failed to clear the offload indication from IPv6 nexthops upon abort. Patch #4 fixes an issue that prevents the driver from loading on Spectrum-3 systems. The problem and solution are explained in detail in the commit message. Patch #5 adds a missing error path. Discovered using smatch. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents f8c2afa + 3a99cbb commit e036c58

File tree

5 files changed

+142
-6
lines changed

5 files changed

+142
-6
lines changed

drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon)
573573

574574
static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon)
575575
{
576+
enum mlxsw_reg_mgpir_device_type device_type;
576577
int index, max_index, sensor_index;
577578
char mgpir_pl[MLXSW_REG_MGPIR_LEN];
578579
char mtmp_pl[MLXSW_REG_MTMP_LEN];
@@ -584,8 +585,9 @@ static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon)
584585
if (err)
585586
return err;
586587

587-
mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, NULL, NULL, NULL);
588-
if (!gbox_num)
588+
mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL, NULL);
589+
if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
590+
!gbox_num)
589591
return 0;
590592

591593
index = mlxsw_hwmon->module_sensor_max;

drivers/net/ethernet/mellanox/mlxsw/core_thermal.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -895,8 +895,10 @@ static int
895895
mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
896896
struct mlxsw_thermal *thermal)
897897
{
898+
enum mlxsw_reg_mgpir_device_type device_type;
898899
struct mlxsw_thermal_module *gearbox_tz;
899900
char mgpir_pl[MLXSW_REG_MGPIR_LEN];
901+
u8 gbox_num;
900902
int i;
901903
int err;
902904

@@ -908,11 +910,13 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
908910
if (err)
909911
return err;
910912

911-
mlxsw_reg_mgpir_unpack(mgpir_pl, &thermal->tz_gearbox_num, NULL, NULL,
913+
mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL,
912914
NULL);
913-
if (!thermal->tz_gearbox_num)
915+
if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
916+
!gbox_num)
914917
return 0;
915918

919+
thermal->tz_gearbox_num = gbox_num;
916920
thermal->tz_gearbox_arr = kcalloc(thermal->tz_gearbox_num,
917921
sizeof(*thermal->tz_gearbox_arr),
918922
GFP_KERNEL);

drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ mlxsw_sp_dpipe_table_erif_entries_dump(void *priv, bool counters_enabled,
215215
start_again:
216216
err = devlink_dpipe_entry_ctx_prepare(dump_ctx);
217217
if (err)
218-
return err;
218+
goto err_ctx_prepare;
219219
j = 0;
220220
for (; i < rif_count; i++) {
221221
struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
@@ -247,6 +247,7 @@ mlxsw_sp_dpipe_table_erif_entries_dump(void *priv, bool counters_enabled,
247247
return 0;
248248
err_entry_append:
249249
err_entry_get:
250+
err_ctx_prepare:
250251
rtnl_unlock();
251252
devlink_dpipe_entry_clear(&entry);
252253
return err;

drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4844,6 +4844,23 @@ mlxsw_sp_fib_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
48444844
fib_node->fib_entry = NULL;
48454845
}
48464846

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+
48474864
static int
48484865
mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
48494866
const struct fib_entry_notifier_info *fen_info)
@@ -4872,6 +4889,12 @@ mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
48724889
goto err_fib4_entry_create;
48734890
}
48744891

4892+
if (!mlxsw_sp_fib4_allow_replace(fib4_entry)) {
4893+
mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
4894+
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4895+
return 0;
4896+
}
4897+
48754898
replaced = fib_node->fib_entry;
48764899
err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib4_entry->common);
48774900
if (err) {
@@ -4908,7 +4931,7 @@ static void mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp,
49084931
return;
49094932

49104933
fib4_entry = mlxsw_sp_fib4_entry_lookup(mlxsw_sp, fen_info);
4911-
if (WARN_ON(!fib4_entry))
4934+
if (!fib4_entry)
49124935
return;
49134936
fib_node = fib4_entry->common.fib_node;
49144937

@@ -4970,6 +4993,9 @@ static void mlxsw_sp_rt6_release(struct fib6_info *rt)
49704993

49714994
static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
49724995
{
4996+
struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
4997+
4998+
fib6_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
49734999
mlxsw_sp_rt6_release(mlxsw_sp_rt6->rt);
49745000
kfree(mlxsw_sp_rt6);
49755001
}
@@ -5408,6 +5434,27 @@ mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
54085434
return NULL;
54095435
}
54105436

5437+
static bool mlxsw_sp_fib6_allow_replace(struct mlxsw_sp_fib6_entry *fib6_entry)
5438+
{
5439+
struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
5440+
struct mlxsw_sp_fib6_entry *fib6_replaced;
5441+
struct fib6_info *rt, *rt_replaced;
5442+
5443+
if (!fib_node->fib_entry)
5444+
return true;
5445+
5446+
fib6_replaced = container_of(fib_node->fib_entry,
5447+
struct mlxsw_sp_fib6_entry,
5448+
common);
5449+
rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
5450+
rt_replaced = mlxsw_sp_fib6_entry_rt(fib6_replaced);
5451+
if (rt->fib6_table->tb6_id == RT_TABLE_MAIN &&
5452+
rt_replaced->fib6_table->tb6_id == RT_TABLE_LOCAL)
5453+
return false;
5454+
5455+
return true;
5456+
}
5457+
54115458
static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
54125459
struct fib6_info **rt_arr,
54135460
unsigned int nrt6)
@@ -5442,6 +5489,12 @@ static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
54425489
goto err_fib6_entry_create;
54435490
}
54445491

5492+
if (!mlxsw_sp_fib6_allow_replace(fib6_entry)) {
5493+
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
5494+
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
5495+
return 0;
5496+
}
5497+
54455498
replaced = fib_node->fib_entry;
54465499
err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib6_entry->common);
54475500
if (err)

tools/testing/selftests/drivers/net/mlxsw/fib.sh

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ ALL_TESTS="
1414
ipv4_plen
1515
ipv4_replay
1616
ipv4_flush
17+
ipv4_local_replace
1718
ipv6_add
1819
ipv6_metric
1920
ipv6_append_single
@@ -26,6 +27,7 @@ ALL_TESTS="
2627
ipv6_delete_multipath
2728
ipv6_replay_single
2829
ipv6_replay_multipath
30+
ipv6_local_replace
2931
"
3032
NUM_NETIFS=0
3133
source $lib_dir/lib.sh
@@ -89,6 +91,43 @@ ipv4_flush()
8991
fib_ipv4_flush_test "testns1"
9092
}
9193

94+
ipv4_local_replace()
95+
{
96+
local ns="testns1"
97+
98+
RET=0
99+
100+
ip -n $ns link add name dummy1 type dummy
101+
ip -n $ns link set dev dummy1 up
102+
103+
ip -n $ns route add table local 192.0.2.1/32 dev dummy1
104+
fib4_trap_check $ns "table local 192.0.2.1/32 dev dummy1" false
105+
check_err $? "Local table route not in hardware when should"
106+
107+
ip -n $ns route add table main 192.0.2.1/32 dev dummy1
108+
fib4_trap_check $ns "table main 192.0.2.1/32 dev dummy1" true
109+
check_err $? "Main table route in hardware when should not"
110+
111+
fib4_trap_check $ns "table local 192.0.2.1/32 dev dummy1" false
112+
check_err $? "Local table route was replaced when should not"
113+
114+
# Test that local routes can replace routes in main table.
115+
ip -n $ns route add table main 192.0.2.2/32 dev dummy1
116+
fib4_trap_check $ns "table main 192.0.2.2/32 dev dummy1" false
117+
check_err $? "Main table route not in hardware when should"
118+
119+
ip -n $ns route add table local 192.0.2.2/32 dev dummy1
120+
fib4_trap_check $ns "table local 192.0.2.2/32 dev dummy1" false
121+
check_err $? "Local table route did not replace route in main table when should"
122+
123+
fib4_trap_check $ns "table main 192.0.2.2/32 dev dummy1" true
124+
check_err $? "Main table route was not replaced when should"
125+
126+
log_test "IPv4 local table route replacement"
127+
128+
ip -n $ns link del dev dummy1
129+
}
130+
92131
ipv6_add()
93132
{
94133
fib_ipv6_add_test "testns1"
@@ -149,6 +188,43 @@ ipv6_replay_multipath()
149188
fib_ipv6_replay_multipath_test "testns1" "$DEVLINK_DEV"
150189
}
151190

191+
ipv6_local_replace()
192+
{
193+
local ns="testns1"
194+
195+
RET=0
196+
197+
ip -n $ns link add name dummy1 type dummy
198+
ip -n $ns link set dev dummy1 up
199+
200+
ip -n $ns route add table local 2001:db8:1::1/128 dev dummy1
201+
fib6_trap_check $ns "table local 2001:db8:1::1/128 dev dummy1" false
202+
check_err $? "Local table route not in hardware when should"
203+
204+
ip -n $ns route add table main 2001:db8:1::1/128 dev dummy1
205+
fib6_trap_check $ns "table main 2001:db8:1::1/128 dev dummy1" true
206+
check_err $? "Main table route in hardware when should not"
207+
208+
fib6_trap_check $ns "table local 2001:db8:1::1/128 dev dummy1" false
209+
check_err $? "Local table route was replaced when should not"
210+
211+
# Test that local routes can replace routes in main table.
212+
ip -n $ns route add table main 2001:db8:1::2/128 dev dummy1
213+
fib6_trap_check $ns "table main 2001:db8:1::2/128 dev dummy1" false
214+
check_err $? "Main table route not in hardware when should"
215+
216+
ip -n $ns route add table local 2001:db8:1::2/128 dev dummy1
217+
fib6_trap_check $ns "table local 2001:db8:1::2/128 dev dummy1" false
218+
check_err $? "Local route route did not replace route in main table when should"
219+
220+
fib6_trap_check $ns "table main 2001:db8:1::2/128 dev dummy1" true
221+
check_err $? "Main table route was not replaced when should"
222+
223+
log_test "IPv6 local table route replacement"
224+
225+
ip -n $ns link del dev dummy1
226+
}
227+
152228
setup_prepare()
153229
{
154230
ip netns add testns1

0 commit comments

Comments
 (0)