]>
Commit | Line | Data |
---|---|---|
2ee025e9 GKH |
1 | From foo@baz Sat Mar 18 22:03:53 CST 2017 |
2 | From: Ido Schimmel <idosch@mellanox.com> | |
3 | Date: Tue, 28 Feb 2017 08:55:40 +0100 | |
4 | Subject: mlxsw: spectrum_router: Avoid potential packets loss | |
5 | ||
6 | From: Ido Schimmel <idosch@mellanox.com> | |
7 | ||
8 | ||
9 | [ Upstream commit f7df4923fa986247e93ec2cdff5ca168fff14dcf ] | |
10 | ||
11 | When the structure of the LPM tree changes (f.e., due to the addition of | |
12 | a new prefix), we unbind the old tree and then bind the new one. This | |
13 | may result in temporary packet loss. | |
14 | ||
15 | Instead, overwrite the old binding with the new one. | |
16 | ||
17 | Fixes: 6b75c4807db3 ("mlxsw: spectrum_router: Add virtual router management") | |
18 | Signed-off-by: Ido Schimmel <idosch@mellanox.com> | |
19 | Signed-off-by: Jiri Pirko <jiri@mellanox.com> | |
20 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
21 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
22 | --- | |
23 | drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 30 ++++++++++++------ | |
24 | 1 file changed, 20 insertions(+), 10 deletions(-) | |
25 | ||
26 | --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | |
27 | +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | |
28 | @@ -496,30 +496,40 @@ static int | |
29 | mlxsw_sp_vr_lpm_tree_check(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr, | |
30 | struct mlxsw_sp_prefix_usage *req_prefix_usage) | |
31 | { | |
32 | - struct mlxsw_sp_lpm_tree *lpm_tree; | |
33 | + struct mlxsw_sp_lpm_tree *lpm_tree = vr->lpm_tree; | |
34 | + struct mlxsw_sp_lpm_tree *new_tree; | |
35 | + int err; | |
36 | ||
37 | - if (mlxsw_sp_prefix_usage_eq(req_prefix_usage, | |
38 | - &vr->lpm_tree->prefix_usage)) | |
39 | + if (mlxsw_sp_prefix_usage_eq(req_prefix_usage, &lpm_tree->prefix_usage)) | |
40 | return 0; | |
41 | ||
42 | - lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, req_prefix_usage, | |
43 | + new_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, req_prefix_usage, | |
44 | vr->proto, false); | |
45 | - if (IS_ERR(lpm_tree)) { | |
46 | + if (IS_ERR(new_tree)) { | |
47 | /* We failed to get a tree according to the required | |
48 | * prefix usage. However, the current tree might be still good | |
49 | * for us if our requirement is subset of the prefixes used | |
50 | * in the tree. | |
51 | */ | |
52 | if (mlxsw_sp_prefix_usage_subset(req_prefix_usage, | |
53 | - &vr->lpm_tree->prefix_usage)) | |
54 | + &lpm_tree->prefix_usage)) | |
55 | return 0; | |
56 | - return PTR_ERR(lpm_tree); | |
57 | + return PTR_ERR(new_tree); | |
58 | } | |
59 | ||
60 | - mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp, vr); | |
61 | - mlxsw_sp_lpm_tree_put(mlxsw_sp, vr->lpm_tree); | |
62 | + /* Prevent packet loss by overwriting existing binding */ | |
63 | + vr->lpm_tree = new_tree; | |
64 | + err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, vr); | |
65 | + if (err) | |
66 | + goto err_tree_bind; | |
67 | + mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree); | |
68 | + | |
69 | + return 0; | |
70 | + | |
71 | +err_tree_bind: | |
72 | vr->lpm_tree = lpm_tree; | |
73 | - return mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, vr); | |
74 | + mlxsw_sp_lpm_tree_put(mlxsw_sp, new_tree); | |
75 | + return err; | |
76 | } | |
77 | ||
78 | static struct mlxsw_sp_vr *mlxsw_sp_vr_get(struct mlxsw_sp *mlxsw_sp, |