Commit 7c4a7ec8 authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller

mlxsw: spectrum_router: Remove FIB entry list from FIB node

As explained in previous patches, the driver no longer needs to maintain
a list of identical FIB entries (i.e, same {tb_id, prefix, prefix
length}) and therefore each FIB node can only store one FIB entry.

Remove the FIB entry list and simplify the code.
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b04720ae
...@@ -382,9 +382,10 @@ enum mlxsw_sp_fib_entry_type { ...@@ -382,9 +382,10 @@ enum mlxsw_sp_fib_entry_type {
}; };
struct mlxsw_sp_nexthop_group; struct mlxsw_sp_nexthop_group;
struct mlxsw_sp_fib_entry;
struct mlxsw_sp_fib_node { struct mlxsw_sp_fib_node {
struct list_head entry_list; struct mlxsw_sp_fib_entry *fib_entry;
struct list_head list; struct list_head list;
struct rhash_head ht_node; struct rhash_head ht_node;
struct mlxsw_sp_fib *fib; struct mlxsw_sp_fib *fib;
...@@ -397,7 +398,6 @@ struct mlxsw_sp_fib_entry_decap { ...@@ -397,7 +398,6 @@ struct mlxsw_sp_fib_entry_decap {
}; };
struct mlxsw_sp_fib_entry { struct mlxsw_sp_fib_entry {
struct list_head list;
struct mlxsw_sp_fib_node *fib_node; struct mlxsw_sp_fib_node *fib_node;
enum mlxsw_sp_fib_entry_type type; enum mlxsw_sp_fib_entry_type type;
struct list_head nexthop_group_node; struct list_head nexthop_group_node;
...@@ -1162,7 +1162,6 @@ mlxsw_sp_router_ip2me_fib_entry_find(struct mlxsw_sp *mlxsw_sp, u32 tb_id, ...@@ -1162,7 +1162,6 @@ mlxsw_sp_router_ip2me_fib_entry_find(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
const union mlxsw_sp_l3addr *addr, const union mlxsw_sp_l3addr *addr,
enum mlxsw_sp_fib_entry_type type) enum mlxsw_sp_fib_entry_type type)
{ {
struct mlxsw_sp_fib_entry *fib_entry;
struct mlxsw_sp_fib_node *fib_node; struct mlxsw_sp_fib_node *fib_node;
unsigned char addr_prefix_len; unsigned char addr_prefix_len;
struct mlxsw_sp_fib *fib; struct mlxsw_sp_fib *fib;
...@@ -1191,15 +1190,10 @@ mlxsw_sp_router_ip2me_fib_entry_find(struct mlxsw_sp *mlxsw_sp, u32 tb_id, ...@@ -1191,15 +1190,10 @@ mlxsw_sp_router_ip2me_fib_entry_find(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
fib_node = mlxsw_sp_fib_node_lookup(fib, addrp, addr_len, fib_node = mlxsw_sp_fib_node_lookup(fib, addrp, addr_len,
addr_prefix_len); addr_prefix_len);
if (!fib_node || list_empty(&fib_node->entry_list)) if (!fib_node || fib_node->fib_entry->type != type)
return NULL;
fib_entry = list_first_entry(&fib_node->entry_list,
struct mlxsw_sp_fib_entry, list);
if (fib_entry->type != type)
return NULL; return NULL;
return fib_entry; return fib_node->fib_entry;
} }
/* Given an IPIP entry, find the corresponding decap route. */ /* Given an IPIP entry, find the corresponding decap route. */
...@@ -1209,7 +1203,6 @@ mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp *mlxsw_sp, ...@@ -1209,7 +1203,6 @@ mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp *mlxsw_sp,
{ {
static struct mlxsw_sp_fib_node *fib_node; static struct mlxsw_sp_fib_node *fib_node;
const struct mlxsw_sp_ipip_ops *ipip_ops; const struct mlxsw_sp_ipip_ops *ipip_ops;
struct mlxsw_sp_fib_entry *fib_entry;
unsigned char saddr_prefix_len; unsigned char saddr_prefix_len;
union mlxsw_sp_l3addr saddr; union mlxsw_sp_l3addr saddr;
struct mlxsw_sp_fib *ul_fib; struct mlxsw_sp_fib *ul_fib;
...@@ -1244,15 +1237,11 @@ mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp *mlxsw_sp, ...@@ -1244,15 +1237,11 @@ mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp *mlxsw_sp,
fib_node = mlxsw_sp_fib_node_lookup(ul_fib, saddrp, saddr_len, fib_node = mlxsw_sp_fib_node_lookup(ul_fib, saddrp, saddr_len,
saddr_prefix_len); saddr_prefix_len);
if (!fib_node || list_empty(&fib_node->entry_list)) if (!fib_node ||
return NULL; fib_node->fib_entry->type != MLXSW_SP_FIB_ENTRY_TYPE_TRAP)
fib_entry = list_first_entry(&fib_node->entry_list,
struct mlxsw_sp_fib_entry, list);
if (fib_entry->type != MLXSW_SP_FIB_ENTRY_TYPE_TRAP)
return NULL; return NULL;
return fib_entry; return fib_node->fib_entry;
} }
static struct mlxsw_sp_ipip_entry * static struct mlxsw_sp_ipip_entry *
...@@ -4559,15 +4548,14 @@ mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp *mlxsw_sp, ...@@ -4559,15 +4548,14 @@ mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp *mlxsw_sp,
if (!fib_node) if (!fib_node)
return NULL; return NULL;
list_for_each_entry(fib4_entry, &fib_node->entry_list, common.list) { fib4_entry = container_of(fib_node->fib_entry,
struct mlxsw_sp_fib4_entry, common);
if (fib4_entry->tb_id == fen_info->tb_id && if (fib4_entry->tb_id == fen_info->tb_id &&
fib4_entry->tos == fen_info->tos && fib4_entry->tos == fen_info->tos &&
fib4_entry->type == fen_info->type && fib4_entry->type == fen_info->type &&
mlxsw_sp_nexthop4_group_fi(fib4_entry->common.nh_group) == mlxsw_sp_nexthop4_group_fi(fib4_entry->common.nh_group) ==
fen_info->fi) { fen_info->fi)
return fib4_entry; return fib4_entry;
}
}
return NULL; return NULL;
} }
...@@ -4615,7 +4603,6 @@ mlxsw_sp_fib_node_create(struct mlxsw_sp_fib *fib, const void *addr, ...@@ -4615,7 +4603,6 @@ mlxsw_sp_fib_node_create(struct mlxsw_sp_fib *fib, const void *addr,
if (!fib_node) if (!fib_node)
return NULL; return NULL;
INIT_LIST_HEAD(&fib_node->entry_list);
list_add(&fib_node->list, &fib->node_list); list_add(&fib_node->list, &fib->node_list);
memcpy(fib_node->key.addr, addr, addr_len); memcpy(fib_node->key.addr, addr, addr_len);
fib_node->key.prefix_len = prefix_len; fib_node->key.prefix_len = prefix_len;
...@@ -4626,18 +4613,9 @@ mlxsw_sp_fib_node_create(struct mlxsw_sp_fib *fib, const void *addr, ...@@ -4626,18 +4613,9 @@ mlxsw_sp_fib_node_create(struct mlxsw_sp_fib *fib, const void *addr,
static void mlxsw_sp_fib_node_destroy(struct mlxsw_sp_fib_node *fib_node) static void mlxsw_sp_fib_node_destroy(struct mlxsw_sp_fib_node *fib_node)
{ {
list_del(&fib_node->list); list_del(&fib_node->list);
WARN_ON(!list_empty(&fib_node->entry_list));
kfree(fib_node); kfree(fib_node);
} }
static bool
mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node *fib_node,
const struct mlxsw_sp_fib_entry *fib_entry)
{
return list_first_entry(&fib_node->entry_list,
struct mlxsw_sp_fib_entry, list) == fib_entry;
}
static int mlxsw_sp_fib_lpm_tree_link(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_fib_lpm_tree_link(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_node *fib_node) struct mlxsw_sp_fib_node *fib_node)
{ {
...@@ -4777,58 +4755,29 @@ static void mlxsw_sp_fib_node_put(struct mlxsw_sp *mlxsw_sp, ...@@ -4777,58 +4755,29 @@ static void mlxsw_sp_fib_node_put(struct mlxsw_sp *mlxsw_sp,
{ {
struct mlxsw_sp_vr *vr = fib_node->fib->vr; struct mlxsw_sp_vr *vr = fib_node->fib->vr;
if (!list_empty(&fib_node->entry_list)) if (fib_node->fib_entry)
return; return;
mlxsw_sp_fib_node_fini(mlxsw_sp, fib_node); mlxsw_sp_fib_node_fini(mlxsw_sp, fib_node);
mlxsw_sp_fib_node_destroy(fib_node); mlxsw_sp_fib_node_destroy(fib_node);
mlxsw_sp_vr_put(mlxsw_sp, vr); mlxsw_sp_vr_put(mlxsw_sp, vr);
} }
static int mlxsw_sp_fib_node_entry_add(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry *fib_entry)
{
struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
/* To prevent packet loss, overwrite the previously offloaded
* entry.
*/
if (!list_is_singular(&fib_node->entry_list)) {
enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_DELETE;
struct mlxsw_sp_fib_entry *n = list_next_entry(fib_entry, list);
mlxsw_sp_fib_entry_offload_refresh(n, op, 0);
}
return mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
}
static void mlxsw_sp_fib_node_entry_del(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry *fib_entry)
{
struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
if (!mlxsw_sp_fib_node_entry_is_first(fib_node, fib_entry))
return;
mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry);
}
static int mlxsw_sp_fib_node_entry_link(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_fib_node_entry_link(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry *fib_entry) struct mlxsw_sp_fib_entry *fib_entry)
{ {
struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node; struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
int err; int err;
list_add(&fib_entry->list, &fib_node->entry_list); fib_node->fib_entry = fib_entry;
err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, fib_entry); err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
if (err) if (err)
goto err_fib_node_entry_add; goto err_fib_entry_update;
return 0; return 0;
err_fib_node_entry_add: err_fib_entry_update:
list_del(&fib_entry->list); fib_node->fib_entry = NULL;
return err; return err;
} }
...@@ -4836,32 +4785,18 @@ static void ...@@ -4836,32 +4785,18 @@ static void
mlxsw_sp_fib_node_entry_unlink(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_fib_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry *fib_entry) struct mlxsw_sp_fib_entry *fib_entry)
{ {
mlxsw_sp_fib_node_entry_del(mlxsw_sp, fib_entry); struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
list_del(&fib_entry->list);
}
static void mlxsw_sp_fib4_entry_replace(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib4_entry *fib4_entry)
{
struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node;
struct mlxsw_sp_fib4_entry *replaced;
if (list_is_singular(&fib_node->entry_list))
return;
/* We inserted the new entry before replaced one */
replaced = list_next_entry(fib4_entry, common.list);
mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &replaced->common); mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry);
mlxsw_sp_fib4_entry_destroy(mlxsw_sp, replaced); fib_node->fib_entry = NULL;
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
} }
static int static int
mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
const struct fib_entry_notifier_info *fen_info) const struct fib_entry_notifier_info *fen_info)
{ {
struct mlxsw_sp_fib4_entry *fib4_entry; struct mlxsw_sp_fib4_entry *fib4_entry, *fib4_replaced;
struct mlxsw_sp_fib_entry *replaced;
struct mlxsw_sp_fib_node *fib_node; struct mlxsw_sp_fib_node *fib_node;
int err; int err;
...@@ -4884,17 +4819,26 @@ mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp, ...@@ -4884,17 +4819,26 @@ mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
goto err_fib4_entry_create; goto err_fib4_entry_create;
} }
replaced = fib_node->fib_entry;
err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib4_entry->common); err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib4_entry->common);
if (err) { if (err) {
dev_warn(mlxsw_sp->bus_info->dev, "Failed to link FIB entry to node\n"); dev_warn(mlxsw_sp->bus_info->dev, "Failed to link FIB entry to node\n");
goto err_fib_node_entry_link; goto err_fib_node_entry_link;
} }
mlxsw_sp_fib4_entry_replace(mlxsw_sp, fib4_entry); /* Nothing to replace */
if (!replaced)
return 0;
mlxsw_sp_fib_entry_offload_unset(replaced);
fib4_replaced = container_of(replaced, struct mlxsw_sp_fib4_entry,
common);
mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_replaced);
return 0; return 0;
err_fib_node_entry_link: err_fib_node_entry_link:
fib_node->fib_entry = replaced;
mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry); mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
err_fib4_entry_create: err_fib4_entry_create:
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
...@@ -5201,16 +5145,16 @@ mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp, ...@@ -5201,16 +5145,16 @@ mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp,
* currently associated with it in the device's table is that * currently associated with it in the device's table is that
* of the old group. Start using the new one instead. * of the old group. Start using the new one instead.
*/ */
err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib6_entry->common); err = mlxsw_sp_fib_entry_update(mlxsw_sp, &fib6_entry->common);
if (err) if (err)
goto err_fib_node_entry_add; goto err_fib_entry_update;
if (list_empty(&old_nh_grp->fib_list)) if (list_empty(&old_nh_grp->fib_list))
mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, old_nh_grp); mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, old_nh_grp);
return 0; return 0;
err_fib_node_entry_add: err_fib_entry_update:
mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common); mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
err_nexthop6_group_get: err_nexthop6_group_get:
list_add_tail(&fib6_entry->common.nexthop_group_node, list_add_tail(&fib6_entry->common.nexthop_group_node,
...@@ -5381,6 +5325,7 @@ mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp, ...@@ -5381,6 +5325,7 @@ mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib6_entry *fib6_entry; struct mlxsw_sp_fib6_entry *fib6_entry;
struct mlxsw_sp_fib_node *fib_node; struct mlxsw_sp_fib_node *fib_node;
struct mlxsw_sp_fib *fib; struct mlxsw_sp_fib *fib;
struct fib6_info *cmp_rt;
struct mlxsw_sp_vr *vr; struct mlxsw_sp_vr *vr;
vr = mlxsw_sp_vr_find(mlxsw_sp, rt->fib6_table->tb6_id); vr = mlxsw_sp_vr_find(mlxsw_sp, rt->fib6_table->tb6_id);
...@@ -5394,40 +5339,23 @@ mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp, ...@@ -5394,40 +5339,23 @@ mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
if (!fib_node) if (!fib_node)
return NULL; return NULL;
list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) { fib6_entry = container_of(fib_node->fib_entry,
struct fib6_info *iter_rt = mlxsw_sp_fib6_entry_rt(fib6_entry); struct mlxsw_sp_fib6_entry, common);
cmp_rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
if (rt->fib6_table->tb6_id == iter_rt->fib6_table->tb6_id && if (rt->fib6_table->tb6_id == cmp_rt->fib6_table->tb6_id &&
rt->fib6_metric == iter_rt->fib6_metric && rt->fib6_metric == cmp_rt->fib6_metric &&
mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt)) mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt))
return fib6_entry; return fib6_entry;
}
return NULL; return NULL;
} }
static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib6_entry *fib6_entry)
{
struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
struct mlxsw_sp_fib6_entry *replaced;
if (list_is_singular(&fib_node->entry_list))
return;
/* We inserted the new entry before replaced one */
replaced = list_next_entry(fib6_entry, common.list);
mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &replaced->common);
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, replaced);
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
}
static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
struct fib6_info **rt_arr, struct fib6_info **rt_arr,
unsigned int nrt6) unsigned int nrt6)
{ {
struct mlxsw_sp_fib6_entry *fib6_entry; struct mlxsw_sp_fib6_entry *fib6_entry, *fib6_replaced;
struct mlxsw_sp_fib_entry *replaced;
struct mlxsw_sp_fib_node *fib_node; struct mlxsw_sp_fib_node *fib_node;
struct fib6_info *rt = rt_arr[0]; struct fib6_info *rt = rt_arr[0];
int err; int err;
...@@ -5456,15 +5384,24 @@ static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp, ...@@ -5456,15 +5384,24 @@ static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
goto err_fib6_entry_create; goto err_fib6_entry_create;
} }
replaced = fib_node->fib_entry;
err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib6_entry->common); err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib6_entry->common);
if (err) if (err)
goto err_fib_node_entry_link; goto err_fib_node_entry_link;
mlxsw_sp_fib6_entry_replace(mlxsw_sp, fib6_entry); /* Nothing to replace */
if (!replaced)
return 0;
mlxsw_sp_fib_entry_offload_unset(replaced);
fib6_replaced = container_of(replaced, struct mlxsw_sp_fib6_entry,
common);
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_replaced);
return 0; return 0;
err_fib_node_entry_link: err_fib_node_entry_link:
fib_node->fib_entry = replaced;
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry); mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
err_fib6_entry_create: err_fib6_entry_create:
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
...@@ -5497,13 +5434,13 @@ static int mlxsw_sp_router_fib6_append(struct mlxsw_sp *mlxsw_sp, ...@@ -5497,13 +5434,13 @@ static int mlxsw_sp_router_fib6_append(struct mlxsw_sp *mlxsw_sp,
if (IS_ERR(fib_node)) if (IS_ERR(fib_node))
return PTR_ERR(fib_node); return PTR_ERR(fib_node);
if (WARN_ON_ONCE(list_empty(&fib_node->entry_list))) { if (WARN_ON_ONCE(!fib_node->fib_entry)) {
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
return -EINVAL; return -EINVAL;
} }
fib6_entry = list_first_entry(&fib_node->entry_list, fib6_entry = container_of(fib_node->fib_entry,
struct mlxsw_sp_fib6_entry, common.list); struct mlxsw_sp_fib6_entry, common);
err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt_arr, err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt_arr,
nrt6); nrt6);
if (err) if (err)
...@@ -5704,39 +5641,25 @@ static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp) ...@@ -5704,39 +5641,25 @@ static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp)
static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_node *fib_node) struct mlxsw_sp_fib_node *fib_node)
{ {
struct mlxsw_sp_fib4_entry *fib4_entry, *tmp; struct mlxsw_sp_fib4_entry *fib4_entry;
list_for_each_entry_safe(fib4_entry, tmp, &fib_node->entry_list,
common.list) {
bool do_break = &tmp->common.list == &fib_node->entry_list;
mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &fib4_entry->common); fib4_entry = container_of(fib_node->fib_entry,
struct mlxsw_sp_fib4_entry, common);
mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, fib_node->fib_entry);
mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry); mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
/* Break when entry list is empty and node was freed.
* Otherwise, we'll access freed memory in the next
* iteration.
*/
if (do_break)
break;
}
} }
static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_node *fib_node) struct mlxsw_sp_fib_node *fib_node)
{ {
struct mlxsw_sp_fib6_entry *fib6_entry, *tmp; struct mlxsw_sp_fib6_entry *fib6_entry;
list_for_each_entry_safe(fib6_entry, tmp, &fib_node->entry_list,
common.list) {
bool do_break = &tmp->common.list == &fib_node->entry_list;
mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &fib6_entry->common); fib6_entry = container_of(fib_node->fib_entry,
struct mlxsw_sp_fib6_entry, common);
mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, fib_node->fib_entry);
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry); mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
if (do_break)
break;
}
} }
static void mlxsw_sp_fib_node_flush(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_fib_node_flush(struct mlxsw_sp *mlxsw_sp,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment