Commit 7cfcbc75 authored by Arkadi Sharshevsky's avatar Arkadi Sharshevsky Committed by David S. Miller

mlxsw: spectrum_router: Add support for setting counters on neighbors

Add support for setting counters on neighbors based on dpipe's host table
counter status. This patch also adds the ability for getting the counter
value, which will be used by the dpipe host table implementation in the
next patches.
Signed-off-by: default avatarArkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6bba7e20
...@@ -5054,6 +5054,14 @@ static inline void mlxsw_reg_rauht_pack6(char *payload, ...@@ -5054,6 +5054,14 @@ static inline void mlxsw_reg_rauht_pack6(char *payload,
mlxsw_reg_rauht_dip6_memcpy_to(payload, dip); mlxsw_reg_rauht_dip6_memcpy_to(payload, dip);
} }
static inline void mlxsw_reg_rauht_pack_counter(char *payload,
u64 counter_index)
{
mlxsw_reg_rauht_counter_index_set(payload, counter_index);
mlxsw_reg_rauht_counter_set_type_set(payload,
MLXSW_REG_FLOW_COUNTER_SET_TYPE_PACKETS_BYTES);
}
/* RALEU - Router Algorithmic LPM ECMP Update Register /* RALEU - Router Algorithmic LPM ECMP Update Register
* --------------------------------------------------- * ---------------------------------------------------
* The register enables updating the ECMP section in the action for multiple * The register enables updating the ECMP section in the action for multiple
......
...@@ -386,7 +386,9 @@ int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp, ...@@ -386,7 +386,9 @@ int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp,
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mgpc), mgpc_pl); err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mgpc), mgpc_pl);
if (err) if (err)
return err; return err;
if (packets)
*packets = mlxsw_reg_mgpc_packet_counter_get(mgpc_pl); *packets = mlxsw_reg_mgpc_packet_counter_get(mgpc_pl);
if (bytes)
*bytes = mlxsw_reg_mgpc_byte_counter_get(mgpc_pl); *bytes = mlxsw_reg_mgpc_byte_counter_get(mgpc_pl);
return 0; return 0;
} }
......
...@@ -901,6 +901,8 @@ struct mlxsw_sp_neigh_entry { ...@@ -901,6 +901,8 @@ struct mlxsw_sp_neigh_entry {
* this neigh entry * this neigh entry
*/ */
struct list_head nexthop_neighs_list_node; struct list_head nexthop_neighs_list_node;
unsigned int counter_index;
bool counter_valid;
}; };
static const struct rhashtable_params mlxsw_sp_neigh_ht_params = { static const struct rhashtable_params mlxsw_sp_neigh_ht_params = {
...@@ -945,6 +947,17 @@ u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry) ...@@ -945,6 +947,17 @@ u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
return ntohl(*((__be32 *) n->primary_key)); return ntohl(*((__be32 *) n->primary_key));
} }
int mlxsw_sp_neigh_counter_get(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_neigh_entry *neigh_entry,
u64 *p_counter)
{
if (!neigh_entry->counter_valid)
return -EINVAL;
return mlxsw_sp_flow_counter_get(mlxsw_sp, neigh_entry->counter_index,
p_counter, NULL);
}
static struct mlxsw_sp_neigh_entry * static struct mlxsw_sp_neigh_entry *
mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n,
u16 rif) u16 rif)
...@@ -985,6 +998,41 @@ mlxsw_sp_neigh_entry_remove(struct mlxsw_sp *mlxsw_sp, ...@@ -985,6 +998,41 @@ mlxsw_sp_neigh_entry_remove(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_neigh_ht_params); mlxsw_sp_neigh_ht_params);
} }
static bool
mlxsw_sp_neigh4_counter_should_alloc(struct mlxsw_sp *mlxsw_sp)
{
struct devlink *devlink;
devlink = priv_to_devlink(mlxsw_sp->core);
return devlink_dpipe_table_counter_enabled(devlink,
MLXSW_SP_DPIPE_TABLE_NAME_HOST4);
}
static void
mlxsw_sp_neigh_counter_alloc(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_neigh_entry *neigh_entry)
{
if (mlxsw_sp_neigh_entry_type(neigh_entry) != AF_INET ||
!mlxsw_sp_neigh4_counter_should_alloc(mlxsw_sp))
return;
if (mlxsw_sp_flow_counter_alloc(mlxsw_sp, &neigh_entry->counter_index))
return;
neigh_entry->counter_valid = true;
}
static void
mlxsw_sp_neigh_counter_free(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_neigh_entry *neigh_entry)
{
if (!neigh_entry->counter_valid)
return;
mlxsw_sp_flow_counter_free(mlxsw_sp,
neigh_entry->counter_index);
neigh_entry->counter_valid = false;
}
static struct mlxsw_sp_neigh_entry * static struct mlxsw_sp_neigh_entry *
mlxsw_sp_neigh_entry_create(struct mlxsw_sp *mlxsw_sp, struct neighbour *n) mlxsw_sp_neigh_entry_create(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
{ {
...@@ -1004,6 +1052,7 @@ mlxsw_sp_neigh_entry_create(struct mlxsw_sp *mlxsw_sp, struct neighbour *n) ...@@ -1004,6 +1052,7 @@ mlxsw_sp_neigh_entry_create(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
if (err) if (err)
goto err_neigh_entry_insert; goto err_neigh_entry_insert;
mlxsw_sp_neigh_counter_alloc(mlxsw_sp, neigh_entry);
list_add(&neigh_entry->rif_list_node, &rif->neigh_list); list_add(&neigh_entry->rif_list_node, &rif->neigh_list);
return neigh_entry; return neigh_entry;
...@@ -1018,6 +1067,7 @@ mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp *mlxsw_sp, ...@@ -1018,6 +1067,7 @@ mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_neigh_entry *neigh_entry) struct mlxsw_sp_neigh_entry *neigh_entry)
{ {
list_del(&neigh_entry->rif_list_node); list_del(&neigh_entry->rif_list_node);
mlxsw_sp_neigh_counter_free(mlxsw_sp, neigh_entry);
mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry); mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry);
mlxsw_sp_neigh_entry_free(neigh_entry); mlxsw_sp_neigh_entry_free(neigh_entry);
} }
...@@ -1323,6 +1373,9 @@ mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp *mlxsw_sp, ...@@ -1323,6 +1373,9 @@ mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp *mlxsw_sp,
mlxsw_reg_rauht_pack4(rauht_pl, op, neigh_entry->rif, neigh_entry->ha, mlxsw_reg_rauht_pack4(rauht_pl, op, neigh_entry->rif, neigh_entry->ha,
dip); dip);
if (neigh_entry->counter_valid)
mlxsw_reg_rauht_pack_counter(rauht_pl,
neigh_entry->counter_index);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
} }
...@@ -1337,6 +1390,9 @@ mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp *mlxsw_sp, ...@@ -1337,6 +1390,9 @@ mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp *mlxsw_sp,
mlxsw_reg_rauht_pack6(rauht_pl, op, neigh_entry->rif, neigh_entry->ha, mlxsw_reg_rauht_pack6(rauht_pl, op, neigh_entry->rif, neigh_entry->ha,
dip); dip);
if (neigh_entry->counter_valid)
mlxsw_reg_rauht_pack_counter(rauht_pl,
neigh_entry->counter_index);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
} }
......
...@@ -69,5 +69,8 @@ u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry); ...@@ -69,5 +69,8 @@ u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry);
#define mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) \ #define mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) \
for (neigh_entry = mlxsw_sp_rif_neigh_next(rif, NULL); neigh_entry; \ for (neigh_entry = mlxsw_sp_rif_neigh_next(rif, NULL); neigh_entry; \
neigh_entry = mlxsw_sp_rif_neigh_next(rif, neigh_entry)) neigh_entry = mlxsw_sp_rif_neigh_next(rif, neigh_entry))
int mlxsw_sp_neigh_counter_get(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_neigh_entry *neigh_entry,
u64 *p_counter);
#endif /* _MLXSW_ROUTER_H_*/ #endif /* _MLXSW_ROUTER_H_*/
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