mirror of https://gitee.com/openkylin/linux.git
Merge branch 'mlxsw-spectrum_router-Cleanups'
Ido Schimmel says: ==================== mlxsw: spectrum_router: Cleanups This patch set removes from mlxsw code that is no longer necessary after the simplification of the IPv4 and IPv6 route offload API. The patches eliminate unnecessary code by taking advantage of the fact that mlxsw no longer needs to maintain a list of identical routes, following recent changes in route offload API. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
1f4f16fa19
|
@ -382,9 +382,10 @@ enum mlxsw_sp_fib_entry_type {
|
|||
};
|
||||
|
||||
struct mlxsw_sp_nexthop_group;
|
||||
struct mlxsw_sp_fib_entry;
|
||||
|
||||
struct mlxsw_sp_fib_node {
|
||||
struct list_head entry_list;
|
||||
struct mlxsw_sp_fib_entry *fib_entry;
|
||||
struct list_head list;
|
||||
struct rhash_head ht_node;
|
||||
struct mlxsw_sp_fib *fib;
|
||||
|
@ -397,7 +398,6 @@ struct mlxsw_sp_fib_entry_decap {
|
|||
};
|
||||
|
||||
struct mlxsw_sp_fib_entry {
|
||||
struct list_head list;
|
||||
struct mlxsw_sp_fib_node *fib_node;
|
||||
enum mlxsw_sp_fib_entry_type type;
|
||||
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,
|
|||
const union mlxsw_sp_l3addr *addr,
|
||||
enum mlxsw_sp_fib_entry_type type)
|
||||
{
|
||||
struct mlxsw_sp_fib_entry *fib_entry;
|
||||
struct mlxsw_sp_fib_node *fib_node;
|
||||
unsigned char addr_prefix_len;
|
||||
struct mlxsw_sp_fib *fib;
|
||||
|
@ -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,
|
||||
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 fib_entry;
|
||||
return fib_node->fib_entry;
|
||||
}
|
||||
|
||||
/* Given an IPIP entry, find the corresponding decap route. */
|
||||
|
@ -1209,7 +1203,6 @@ mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp *mlxsw_sp,
|
|||
{
|
||||
static struct mlxsw_sp_fib_node *fib_node;
|
||||
const struct mlxsw_sp_ipip_ops *ipip_ops;
|
||||
struct mlxsw_sp_fib_entry *fib_entry;
|
||||
unsigned char saddr_prefix_len;
|
||||
union mlxsw_sp_l3addr saddr;
|
||||
struct mlxsw_sp_fib *ul_fib;
|
||||
|
@ -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,
|
||||
saddr_prefix_len);
|
||||
if (!fib_node || list_empty(&fib_node->entry_list))
|
||||
if (!fib_node ||
|
||||
fib_node->fib_entry->type != MLXSW_SP_FIB_ENTRY_TYPE_TRAP)
|
||||
return NULL;
|
||||
|
||||
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 fib_entry;
|
||||
return fib_node->fib_entry;
|
||||
}
|
||||
|
||||
static struct mlxsw_sp_ipip_entry *
|
||||
|
@ -3231,10 +3220,6 @@ mlxsw_sp_nexthop_group_update(struct mlxsw_sp *mlxsw_sp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
static int
|
||||
mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_nexthop_group *nh_grp)
|
||||
|
@ -3243,9 +3228,6 @@ mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp *mlxsw_sp,
|
|||
int err;
|
||||
|
||||
list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) {
|
||||
if (!mlxsw_sp_fib_node_entry_is_first(fib_entry->fib_node,
|
||||
fib_entry))
|
||||
continue;
|
||||
err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -3263,12 +3245,8 @@ mlxsw_sp_nexthop_fib_entries_refresh(struct mlxsw_sp_nexthop_group *nh_grp)
|
|||
enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_WRITE;
|
||||
struct mlxsw_sp_fib_entry *fib_entry;
|
||||
|
||||
list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) {
|
||||
if (!mlxsw_sp_fib_node_entry_is_first(fib_entry->fib_node,
|
||||
fib_entry))
|
||||
continue;
|
||||
list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node)
|
||||
mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void mlxsw_sp_adj_grp_size_round_up(u16 *p_adj_grp_size)
|
||||
|
@ -4491,6 +4469,19 @@ mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_fib4_entry_type_unset(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_fib_entry *fib_entry)
|
||||
{
|
||||
switch (fib_entry->type) {
|
||||
case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
|
||||
mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, fib_entry);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct mlxsw_sp_fib4_entry *
|
||||
mlxsw_sp_fib4_entry_create(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_fib_node *fib_node,
|
||||
|
@ -4523,6 +4514,7 @@ mlxsw_sp_fib4_entry_create(struct mlxsw_sp *mlxsw_sp,
|
|||
return fib4_entry;
|
||||
|
||||
err_nexthop4_group_get:
|
||||
mlxsw_sp_fib4_entry_type_unset(mlxsw_sp, fib_entry);
|
||||
err_fib4_entry_type_set:
|
||||
kfree(fib4_entry);
|
||||
return ERR_PTR(err);
|
||||
|
@ -4532,6 +4524,7 @@ static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp *mlxsw_sp,
|
|||
struct mlxsw_sp_fib4_entry *fib4_entry)
|
||||
{
|
||||
mlxsw_sp_nexthop4_group_put(mlxsw_sp, &fib4_entry->common);
|
||||
mlxsw_sp_fib4_entry_type_unset(mlxsw_sp, &fib4_entry->common);
|
||||
kfree(fib4_entry);
|
||||
}
|
||||
|
||||
|
@ -4555,15 +4548,14 @@ mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp *mlxsw_sp,
|
|||
if (!fib_node)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(fib4_entry, &fib_node->entry_list, common.list) {
|
||||
if (fib4_entry->tb_id == fen_info->tb_id &&
|
||||
fib4_entry->tos == fen_info->tos &&
|
||||
fib4_entry->type == fen_info->type &&
|
||||
mlxsw_sp_nexthop4_group_fi(fib4_entry->common.nh_group) ==
|
||||
fen_info->fi) {
|
||||
return fib4_entry;
|
||||
}
|
||||
}
|
||||
fib4_entry = container_of(fib_node->fib_entry,
|
||||
struct mlxsw_sp_fib4_entry, common);
|
||||
if (fib4_entry->tb_id == fen_info->tb_id &&
|
||||
fib4_entry->tos == fen_info->tos &&
|
||||
fib4_entry->type == fen_info->type &&
|
||||
mlxsw_sp_nexthop4_group_fi(fib4_entry->common.nh_group) ==
|
||||
fen_info->fi)
|
||||
return fib4_entry;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -4611,7 +4603,6 @@ mlxsw_sp_fib_node_create(struct mlxsw_sp_fib *fib, const void *addr,
|
|||
if (!fib_node)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&fib_node->entry_list);
|
||||
list_add(&fib_node->list, &fib->node_list);
|
||||
memcpy(fib_node->key.addr, addr, addr_len);
|
||||
fib_node->key.prefix_len = prefix_len;
|
||||
|
@ -4622,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)
|
||||
{
|
||||
list_del(&fib_node->list);
|
||||
WARN_ON(!list_empty(&fib_node->entry_list));
|
||||
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,
|
||||
struct mlxsw_sp_fib_node *fib_node)
|
||||
{
|
||||
|
@ -4773,107 +4755,48 @@ static void mlxsw_sp_fib_node_put(struct mlxsw_sp *mlxsw_sp,
|
|||
{
|
||||
struct mlxsw_sp_vr *vr = fib_node->fib->vr;
|
||||
|
||||
if (!list_empty(&fib_node->entry_list))
|
||||
if (fib_node->fib_entry)
|
||||
return;
|
||||
mlxsw_sp_fib_node_fini(mlxsw_sp, fib_node);
|
||||
mlxsw_sp_fib_node_destroy(fib_node);
|
||||
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;
|
||||
|
||||
if (!mlxsw_sp_fib_node_entry_is_first(fib_node, fib_entry))
|
||||
return 0;
|
||||
|
||||
/* 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,
|
||||
static int mlxsw_sp_fib_node_entry_link(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;
|
||||
|
||||
/* Promote the next entry by overwriting the deleted entry */
|
||||
if (!list_is_singular(&fib_node->entry_list)) {
|
||||
struct mlxsw_sp_fib_entry *n = list_next_entry(fib_entry, list);
|
||||
enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_DELETE;
|
||||
|
||||
mlxsw_sp_fib_entry_update(mlxsw_sp, n);
|
||||
mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fib4_node_entry_link(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_fib4_entry *fib4_entry)
|
||||
{
|
||||
struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node;
|
||||
int err;
|
||||
|
||||
list_add(&fib4_entry->common.list, &fib_node->entry_list);
|
||||
fib_node->fib_entry = fib_entry;
|
||||
|
||||
err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib4_entry->common);
|
||||
err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
|
||||
if (err)
|
||||
goto err_fib_node_entry_add;
|
||||
goto err_fib_entry_update;
|
||||
|
||||
return 0;
|
||||
|
||||
err_fib_node_entry_add:
|
||||
list_del(&fib4_entry->common.list);
|
||||
err_fib_entry_update:
|
||||
fib_node->fib_entry = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_fib4_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_fib4_entry *fib4_entry)
|
||||
mlxsw_sp_fib_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_fib_entry *fib_entry)
|
||||
{
|
||||
mlxsw_sp_fib_node_entry_del(mlxsw_sp, &fib4_entry->common);
|
||||
list_del(&fib4_entry->common.list);
|
||||
struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
|
||||
|
||||
if (fib4_entry->common.type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP)
|
||||
mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, &fib4_entry->common);
|
||||
}
|
||||
|
||||
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_fib4_node_entry_unlink(mlxsw_sp, replaced);
|
||||
mlxsw_sp_fib4_entry_destroy(mlxsw_sp, replaced);
|
||||
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
|
||||
mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry);
|
||||
fib_node->fib_entry = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
|
||||
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;
|
||||
int err;
|
||||
|
||||
|
@ -4896,17 +4819,26 @@ mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
|
|||
goto err_fib4_entry_create;
|
||||
}
|
||||
|
||||
err = mlxsw_sp_fib4_node_entry_link(mlxsw_sp, fib4_entry);
|
||||
replaced = fib_node->fib_entry;
|
||||
err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib4_entry->common);
|
||||
if (err) {
|
||||
dev_warn(mlxsw_sp->bus_info->dev, "Failed to link FIB entry to node\n");
|
||||
goto err_fib4_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;
|
||||
|
||||
err_fib4_node_entry_link:
|
||||
err_fib_node_entry_link:
|
||||
fib_node->fib_entry = replaced;
|
||||
mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
|
||||
err_fib4_entry_create:
|
||||
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
|
||||
|
@ -4927,7 +4859,7 @@ static void mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp,
|
|||
return;
|
||||
fib_node = fib4_entry->common.fib_node;
|
||||
|
||||
mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, fib4_entry);
|
||||
mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &fib4_entry->common);
|
||||
mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
|
||||
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
|
||||
}
|
||||
|
@ -5213,16 +5145,16 @@ mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp,
|
|||
* currently associated with it in the device's table is that
|
||||
* 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)
|
||||
goto err_fib_node_entry_add;
|
||||
goto err_fib_entry_update;
|
||||
|
||||
if (list_empty(&old_nh_grp->fib_list))
|
||||
mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, old_nh_grp);
|
||||
|
||||
return 0;
|
||||
|
||||
err_fib_node_entry_add:
|
||||
err_fib_entry_update:
|
||||
mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
|
||||
err_nexthop6_group_get:
|
||||
list_add_tail(&fib6_entry->common.nexthop_group_node,
|
||||
|
@ -5386,33 +5318,6 @@ static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp *mlxsw_sp,
|
|||
kfree(fib6_entry);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fib6_node_entry_link(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_fib6_entry *fib6_entry)
|
||||
{
|
||||
struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
|
||||
int err;
|
||||
|
||||
list_add(&fib6_entry->common.list, &fib_node->entry_list);
|
||||
|
||||
err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib6_entry->common);
|
||||
if (err)
|
||||
goto err_fib_node_entry_add;
|
||||
|
||||
return 0;
|
||||
|
||||
err_fib_node_entry_add:
|
||||
list_del(&fib6_entry->common.list);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_fib6_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_fib6_entry *fib6_entry)
|
||||
{
|
||||
mlxsw_sp_fib_node_entry_del(mlxsw_sp, &fib6_entry->common);
|
||||
list_del(&fib6_entry->common.list);
|
||||
}
|
||||
|
||||
static struct mlxsw_sp_fib6_entry *
|
||||
mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct fib6_info *rt)
|
||||
|
@ -5420,6 +5325,7 @@ mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
|
|||
struct mlxsw_sp_fib6_entry *fib6_entry;
|
||||
struct mlxsw_sp_fib_node *fib_node;
|
||||
struct mlxsw_sp_fib *fib;
|
||||
struct fib6_info *cmp_rt;
|
||||
struct mlxsw_sp_vr *vr;
|
||||
|
||||
vr = mlxsw_sp_vr_find(mlxsw_sp, rt->fib6_table->tb6_id);
|
||||
|
@ -5433,40 +5339,23 @@ mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
|
|||
if (!fib_node)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
|
||||
struct fib6_info *iter_rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
|
||||
|
||||
if (rt->fib6_table->tb6_id == iter_rt->fib6_table->tb6_id &&
|
||||
rt->fib6_metric == iter_rt->fib6_metric &&
|
||||
mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt))
|
||||
return fib6_entry;
|
||||
}
|
||||
fib6_entry = container_of(fib_node->fib_entry,
|
||||
struct mlxsw_sp_fib6_entry, common);
|
||||
cmp_rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
|
||||
if (rt->fib6_table->tb6_id == cmp_rt->fib6_table->tb6_id &&
|
||||
rt->fib6_metric == cmp_rt->fib6_metric &&
|
||||
mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt))
|
||||
return fib6_entry;
|
||||
|
||||
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_fib6_node_entry_unlink(mlxsw_sp, replaced);
|
||||
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,
|
||||
struct fib6_info **rt_arr,
|
||||
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 fib6_info *rt = rt_arr[0];
|
||||
int err;
|
||||
|
@ -5495,15 +5384,24 @@ static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
|
|||
goto err_fib6_entry_create;
|
||||
}
|
||||
|
||||
err = mlxsw_sp_fib6_node_entry_link(mlxsw_sp, fib6_entry);
|
||||
replaced = fib_node->fib_entry;
|
||||
err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib6_entry->common);
|
||||
if (err)
|
||||
goto err_fib6_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;
|
||||
|
||||
err_fib6_node_entry_link:
|
||||
err_fib_node_entry_link:
|
||||
fib_node->fib_entry = replaced;
|
||||
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
|
||||
err_fib6_entry_create:
|
||||
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
|
||||
|
@ -5536,13 +5434,13 @@ static int mlxsw_sp_router_fib6_append(struct mlxsw_sp *mlxsw_sp,
|
|||
if (IS_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);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fib6_entry = list_first_entry(&fib_node->entry_list,
|
||||
struct mlxsw_sp_fib6_entry, common.list);
|
||||
fib6_entry = container_of(fib_node->fib_entry,
|
||||
struct mlxsw_sp_fib6_entry, common);
|
||||
err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt_arr,
|
||||
nrt6);
|
||||
if (err)
|
||||
|
@ -5589,7 +5487,7 @@ static void mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp,
|
|||
|
||||
fib_node = fib6_entry->common.fib_node;
|
||||
|
||||
mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, fib6_entry);
|
||||
mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &fib6_entry->common);
|
||||
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
|
||||
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
|
||||
}
|
||||
|
@ -5743,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,
|
||||
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_fib4_node_entry_unlink(mlxsw_sp, fib4_entry);
|
||||
mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
|
||||
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;
|
||||
}
|
||||
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_fib_node_put(mlxsw_sp, fib_node);
|
||||
}
|
||||
|
||||
static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp *mlxsw_sp,
|
||||
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_fib6_node_entry_unlink(mlxsw_sp, fib6_entry);
|
||||
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
|
||||
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
|
||||
if (do_break)
|
||||
break;
|
||||
}
|
||||
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_fib_node_put(mlxsw_sp, fib_node);
|
||||
}
|
||||
|
||||
static void mlxsw_sp_fib_node_flush(struct mlxsw_sp *mlxsw_sp,
|
||||
|
|
Loading…
Reference in New Issue