mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-04 20:36:40 +07:00
Merge branch 'mlxsw-ipv4-host-dpipe-table'
Jiri Pirko says: ==================== mlxsw: Add IPv4 host dpipe table Arkadi says: This patchset adds IPv4 host dpipe table support. This will provide the ability to observe the hardware offloaded IPv4 neighbors. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
fb3bbbda5f
@ -5000,6 +5000,15 @@ enum mlxsw_reg_rauht_trap_id {
|
||||
*/
|
||||
MLXSW_ITEM32(reg, rauht, trap_id, 0x60, 0, 9);
|
||||
|
||||
enum mlxsw_reg_flow_counter_set_type {
|
||||
/* No count */
|
||||
MLXSW_REG_FLOW_COUNTER_SET_TYPE_NO_COUNT = 0x00,
|
||||
/* Count packets and bytes */
|
||||
MLXSW_REG_FLOW_COUNTER_SET_TYPE_PACKETS_BYTES = 0x03,
|
||||
/* Count only packets */
|
||||
MLXSW_REG_FLOW_COUNTER_SET_TYPE_PACKETS = 0x05,
|
||||
};
|
||||
|
||||
/* reg_rauht_counter_set_type
|
||||
* Counter set type for flow counters
|
||||
* Access: RW
|
||||
@ -5045,6 +5054,14 @@ static inline void mlxsw_reg_rauht_pack6(char *payload,
|
||||
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
|
||||
* ---------------------------------------------------
|
||||
* The register enables updating the ECMP section in the action for multiple
|
||||
@ -6041,15 +6058,6 @@ static inline void mlxsw_reg_mpsc_pack(char *payload, u8 local_port, bool e,
|
||||
|
||||
MLXSW_REG_DEFINE(mgpc, MLXSW_REG_MGPC_ID, MLXSW_REG_MGPC_LEN);
|
||||
|
||||
enum mlxsw_reg_mgpc_counter_set_type {
|
||||
/* No count */
|
||||
MLXSW_REG_MGPC_COUNTER_SET_TYPE_NO_COUT = 0x00,
|
||||
/* Count packets and bytes */
|
||||
MLXSW_REG_MGPC_COUNTER_SET_TYPE_PACKETS_BYTES = 0x03,
|
||||
/* Count only packets */
|
||||
MLXSW_REG_MGPC_COUNTER_SET_TYPE_PACKETS = 0x05,
|
||||
};
|
||||
|
||||
/* reg_mgpc_counter_set_type
|
||||
* Counter set type.
|
||||
* Access: OP
|
||||
@ -6089,7 +6097,7 @@ MLXSW_ITEM64(reg, mgpc, packet_counter, 0x10, 0, 64);
|
||||
|
||||
static inline void mlxsw_reg_mgpc_pack(char *payload, u32 counter_index,
|
||||
enum mlxsw_reg_mgpc_opcode opcode,
|
||||
enum mlxsw_reg_mgpc_counter_set_type set_type)
|
||||
enum mlxsw_reg_flow_counter_set_type set_type)
|
||||
{
|
||||
MLXSW_REG_ZERO(mgpc, payload);
|
||||
mlxsw_reg_mgpc_counter_index_set(payload, counter_index);
|
||||
|
@ -382,12 +382,14 @@ int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp,
|
||||
int err;
|
||||
|
||||
mlxsw_reg_mgpc_pack(mgpc_pl, counter_index, MLXSW_REG_MGPC_OPCODE_NOP,
|
||||
MLXSW_REG_MGPC_COUNTER_SET_TYPE_PACKETS_BYTES);
|
||||
MLXSW_REG_FLOW_COUNTER_SET_TYPE_PACKETS_BYTES);
|
||||
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mgpc), mgpc_pl);
|
||||
if (err)
|
||||
return err;
|
||||
*packets = mlxsw_reg_mgpc_packet_counter_get(mgpc_pl);
|
||||
*bytes = mlxsw_reg_mgpc_byte_counter_get(mgpc_pl);
|
||||
if (packets)
|
||||
*packets = mlxsw_reg_mgpc_packet_counter_get(mgpc_pl);
|
||||
if (bytes)
|
||||
*bytes = mlxsw_reg_mgpc_byte_counter_get(mgpc_pl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -397,7 +399,7 @@ static int mlxsw_sp_flow_counter_clear(struct mlxsw_sp *mlxsw_sp,
|
||||
char mgpc_pl[MLXSW_REG_MGPC_LEN];
|
||||
|
||||
mlxsw_reg_mgpc_pack(mgpc_pl, counter_index, MLXSW_REG_MGPC_OPCODE_CLEAR,
|
||||
MLXSW_REG_MGPC_COUNTER_SET_TYPE_PACKETS_BYTES);
|
||||
MLXSW_REG_FLOW_COUNTER_SET_TYPE_PACKETS_BYTES);
|
||||
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mgpc), mgpc_pl);
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,8 @@ static struct devlink_dpipe_header mlxsw_sp_dpipe_header_metadata = {
|
||||
|
||||
static struct devlink_dpipe_header *mlxsw_dpipe_headers[] = {
|
||||
&mlxsw_sp_dpipe_header_metadata,
|
||||
&devlink_dpipe_header_ethernet,
|
||||
&devlink_dpipe_header_ipv4,
|
||||
};
|
||||
|
||||
static struct devlink_dpipe_headers mlxsw_sp_dpipe_headers = {
|
||||
@ -114,26 +116,6 @@ static int mlxsw_sp_dpipe_table_erif_matches_dump(void *priv,
|
||||
return devlink_dpipe_match_put(skb, &match);
|
||||
}
|
||||
|
||||
static void mlxsw_sp_erif_entry_clear(struct devlink_dpipe_entry *entry)
|
||||
{
|
||||
unsigned int value_count, value_index;
|
||||
struct devlink_dpipe_value *value;
|
||||
|
||||
value = entry->action_values;
|
||||
value_count = entry->action_values_count;
|
||||
for (value_index = 0; value_index < value_count; value_index++) {
|
||||
kfree(value[value_index].value);
|
||||
kfree(value[value_index].mask);
|
||||
}
|
||||
|
||||
value = entry->match_values;
|
||||
value_count = entry->match_values_count;
|
||||
for (value_index = 0; value_index < value_count; value_index++) {
|
||||
kfree(value[value_index].value);
|
||||
kfree(value[value_index].mask);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_erif_match_action_prepare(struct devlink_dpipe_match *match,
|
||||
struct devlink_dpipe_action *action)
|
||||
@ -215,8 +197,8 @@ static int mlxsw_sp_erif_entry_get(struct mlxsw_sp *mlxsw_sp,
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_table_erif_entries_dump(void *priv, bool counters_enabled,
|
||||
struct devlink_dpipe_dump_ctx *dump_ctx)
|
||||
mlxsw_sp_dpipe_table_erif_entries_dump(void *priv, bool counters_enabled,
|
||||
struct devlink_dpipe_dump_ctx *dump_ctx)
|
||||
{
|
||||
struct devlink_dpipe_value match_value, action_value;
|
||||
struct devlink_dpipe_action action = {0};
|
||||
@ -270,16 +252,16 @@ mlxsw_sp_table_erif_entries_dump(void *priv, bool counters_enabled,
|
||||
goto start_again;
|
||||
rtnl_unlock();
|
||||
|
||||
mlxsw_sp_erif_entry_clear(&entry);
|
||||
devlink_dpipe_entry_clear(&entry);
|
||||
return 0;
|
||||
err_entry_append:
|
||||
err_entry_get:
|
||||
rtnl_unlock();
|
||||
mlxsw_sp_erif_entry_clear(&entry);
|
||||
devlink_dpipe_entry_clear(&entry);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_table_erif_counters_update(void *priv, bool enable)
|
||||
static int mlxsw_sp_dpipe_table_erif_counters_update(void *priv, bool enable)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = priv;
|
||||
int i;
|
||||
@ -301,24 +283,29 @@ static int mlxsw_sp_table_erif_counters_update(void *priv, bool enable)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 mlxsw_sp_dpipe_table_erif_size_get(void *priv)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = priv;
|
||||
|
||||
return MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
|
||||
}
|
||||
|
||||
static struct devlink_dpipe_table_ops mlxsw_sp_erif_ops = {
|
||||
.matches_dump = mlxsw_sp_dpipe_table_erif_matches_dump,
|
||||
.actions_dump = mlxsw_sp_dpipe_table_erif_actions_dump,
|
||||
.entries_dump = mlxsw_sp_table_erif_entries_dump,
|
||||
.counters_set_update = mlxsw_sp_table_erif_counters_update,
|
||||
.entries_dump = mlxsw_sp_dpipe_table_erif_entries_dump,
|
||||
.counters_set_update = mlxsw_sp_dpipe_table_erif_counters_update,
|
||||
.size_get = mlxsw_sp_dpipe_table_erif_size_get,
|
||||
};
|
||||
|
||||
static int mlxsw_sp_dpipe_erif_table_init(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
||||
u64 table_size;
|
||||
|
||||
table_size = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
|
||||
return devlink_dpipe_table_register(devlink,
|
||||
MLXSW_SP_DPIPE_TABLE_NAME_ERIF,
|
||||
&mlxsw_sp_erif_ops,
|
||||
mlxsw_sp, table_size,
|
||||
false);
|
||||
mlxsw_sp, false);
|
||||
}
|
||||
|
||||
static void mlxsw_sp_dpipe_erif_table_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
@ -328,6 +315,379 @@ static void mlxsw_sp_dpipe_erif_table_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
devlink_dpipe_table_unregister(devlink, MLXSW_SP_DPIPE_TABLE_NAME_ERIF);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_dpipe_table_host_matches_dump(struct sk_buff *skb, int type)
|
||||
{
|
||||
struct devlink_dpipe_match match = {0};
|
||||
int err;
|
||||
|
||||
match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
|
||||
match.header = &mlxsw_sp_dpipe_header_metadata;
|
||||
match.field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT;
|
||||
|
||||
err = devlink_dpipe_match_put(skb, &match);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
|
||||
match.header = &devlink_dpipe_header_ipv4;
|
||||
match.field_id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP;
|
||||
|
||||
return devlink_dpipe_match_put(skb, &match);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_dpipe_table_host4_matches_dump(void *priv, struct sk_buff *skb)
|
||||
{
|
||||
return mlxsw_sp_dpipe_table_host_matches_dump(skb, AF_INET);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_dpipe_table_host4_actions_dump(void *priv, struct sk_buff *skb)
|
||||
{
|
||||
struct devlink_dpipe_action action = {0};
|
||||
|
||||
action.type = DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY;
|
||||
action.header = &devlink_dpipe_header_ethernet;
|
||||
action.field_id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC;
|
||||
|
||||
return devlink_dpipe_action_put(skb, &action);
|
||||
}
|
||||
|
||||
enum mlxsw_sp_dpipe_table_host_match {
|
||||
MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF,
|
||||
MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP,
|
||||
MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT,
|
||||
};
|
||||
|
||||
static void
|
||||
mlxsw_sp_dpipe_table_host_match_action_prepare(struct devlink_dpipe_match *matches,
|
||||
struct devlink_dpipe_action *action,
|
||||
int type)
|
||||
{
|
||||
struct devlink_dpipe_match *match;
|
||||
|
||||
match = &matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF];
|
||||
match->type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
|
||||
match->header = &mlxsw_sp_dpipe_header_metadata;
|
||||
match->field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT;
|
||||
|
||||
match = &matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
|
||||
match->type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
|
||||
match->header = &devlink_dpipe_header_ipv4;
|
||||
match->field_id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP;
|
||||
|
||||
action->type = DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY;
|
||||
action->header = &devlink_dpipe_header_ethernet;
|
||||
action->field_id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC;
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_dpipe_table_host_entry_prepare(struct devlink_dpipe_entry *entry,
|
||||
struct devlink_dpipe_value *match_values,
|
||||
struct devlink_dpipe_match *matches,
|
||||
struct devlink_dpipe_value *action_value,
|
||||
struct devlink_dpipe_action *action,
|
||||
int type)
|
||||
{
|
||||
struct devlink_dpipe_value *match_value;
|
||||
struct devlink_dpipe_match *match;
|
||||
|
||||
entry->match_values = match_values;
|
||||
entry->match_values_count = MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT;
|
||||
|
||||
entry->action_values = action_value;
|
||||
entry->action_values_count = 1;
|
||||
|
||||
match = &matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF];
|
||||
match_value = &match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF];
|
||||
|
||||
match_value->match = match;
|
||||
match_value->value_size = sizeof(u32);
|
||||
match_value->value = kmalloc(match_value->value_size, GFP_KERNEL);
|
||||
if (!match_value->value)
|
||||
return -ENOMEM;
|
||||
|
||||
match = &matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
|
||||
match_value = &match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
|
||||
|
||||
match_value->match = match;
|
||||
match_value->value_size = sizeof(u32);
|
||||
match_value->value = kmalloc(match_value->value_size, GFP_KERNEL);
|
||||
if (!match_value->value)
|
||||
return -ENOMEM;
|
||||
|
||||
action_value->action = action;
|
||||
action_value->value_size = sizeof(u64);
|
||||
action_value->value = kmalloc(action_value->value_size, GFP_KERNEL);
|
||||
if (!action_value->value)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
__mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry *entry,
|
||||
struct mlxsw_sp_rif *rif,
|
||||
unsigned char *ha, u32 dip)
|
||||
{
|
||||
struct devlink_dpipe_value *value;
|
||||
u32 *rif_value;
|
||||
u32 *dip_value;
|
||||
u8 *ha_value;
|
||||
|
||||
/* Set Match RIF index */
|
||||
value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF];
|
||||
|
||||
rif_value = value->value;
|
||||
*rif_value = mlxsw_sp_rif_index(rif);
|
||||
value->mapping_value = mlxsw_sp_rif_dev_ifindex(rif);
|
||||
value->mapping_valid = true;
|
||||
|
||||
/* Set Match DIP */
|
||||
value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
|
||||
|
||||
dip_value = value->value;
|
||||
*dip_value = dip;
|
||||
|
||||
/* Set Action DMAC */
|
||||
value = entry->action_values;
|
||||
ha_value = value->value;
|
||||
ether_addr_copy(ha_value, ha);
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry *entry,
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry,
|
||||
struct mlxsw_sp_rif *rif)
|
||||
{
|
||||
unsigned char *ha;
|
||||
u32 dip;
|
||||
|
||||
ha = mlxsw_sp_neigh_entry_ha(neigh_entry);
|
||||
dip = mlxsw_sp_neigh4_entry_dip(neigh_entry);
|
||||
__mlxsw_sp_dpipe_table_host4_entry_fill(entry, rif, ha, dip);
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_dpipe_table_host_entry_fill(struct mlxsw_sp *mlxsw_sp,
|
||||
struct devlink_dpipe_entry *entry,
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry,
|
||||
struct mlxsw_sp_rif *rif,
|
||||
int type)
|
||||
{
|
||||
int err;
|
||||
|
||||
mlxsw_sp_dpipe_table_host4_entry_fill(entry, neigh_entry, rif);
|
||||
err = mlxsw_sp_neigh_counter_get(mlxsw_sp, neigh_entry,
|
||||
&entry->counter);
|
||||
if (!err)
|
||||
entry->counter_valid = true;
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_dpipe_table_host_entries_get(struct mlxsw_sp *mlxsw_sp,
|
||||
struct devlink_dpipe_entry *entry,
|
||||
bool counters_enabled,
|
||||
struct devlink_dpipe_dump_ctx *dump_ctx,
|
||||
int type)
|
||||
{
|
||||
int rif_neigh_count = 0;
|
||||
int rif_neigh_skip = 0;
|
||||
int neigh_count = 0;
|
||||
int rif_count;
|
||||
int i, j;
|
||||
int err;
|
||||
|
||||
rtnl_lock();
|
||||
i = 0;
|
||||
rif_count = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
|
||||
start_again:
|
||||
err = devlink_dpipe_entry_ctx_prepare(dump_ctx);
|
||||
if (err)
|
||||
goto err_ctx_prepare;
|
||||
j = 0;
|
||||
rif_neigh_skip = rif_neigh_count;
|
||||
for (; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
|
||||
struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry;
|
||||
|
||||
if (!rif)
|
||||
continue;
|
||||
|
||||
rif_neigh_count = 0;
|
||||
mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {
|
||||
if (rif_neigh_count < rif_neigh_skip)
|
||||
goto skip;
|
||||
|
||||
mlxsw_sp_dpipe_table_host_entry_fill(mlxsw_sp, entry,
|
||||
neigh_entry, rif,
|
||||
type);
|
||||
entry->index = neigh_count;
|
||||
err = devlink_dpipe_entry_ctx_append(dump_ctx, entry);
|
||||
if (err) {
|
||||
if (err == -EMSGSIZE) {
|
||||
if (!j)
|
||||
goto err_entry_append;
|
||||
else
|
||||
goto out;
|
||||
}
|
||||
goto err_entry_append;
|
||||
}
|
||||
neigh_count++;
|
||||
j++;
|
||||
skip:
|
||||
rif_neigh_count++;
|
||||
}
|
||||
rif_neigh_skip = 0;
|
||||
}
|
||||
out:
|
||||
devlink_dpipe_entry_ctx_close(dump_ctx);
|
||||
if (i != rif_count)
|
||||
goto start_again;
|
||||
|
||||
rtnl_unlock();
|
||||
return 0;
|
||||
|
||||
err_ctx_prepare:
|
||||
err_entry_append:
|
||||
rtnl_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_dpipe_table_host_entries_dump(struct mlxsw_sp *mlxsw_sp,
|
||||
bool counters_enabled,
|
||||
struct devlink_dpipe_dump_ctx *dump_ctx,
|
||||
int type)
|
||||
{
|
||||
struct devlink_dpipe_value match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT];
|
||||
struct devlink_dpipe_match matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT];
|
||||
struct devlink_dpipe_value action_value;
|
||||
struct devlink_dpipe_action action = {0};
|
||||
struct devlink_dpipe_entry entry = {0};
|
||||
int err;
|
||||
|
||||
memset(matches, 0, MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT *
|
||||
sizeof(matches[0]));
|
||||
memset(match_values, 0, MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT *
|
||||
sizeof(match_values[0]));
|
||||
memset(&action_value, 0, sizeof(action_value));
|
||||
|
||||
mlxsw_sp_dpipe_table_host_match_action_prepare(matches, &action, type);
|
||||
err = mlxsw_sp_dpipe_table_host_entry_prepare(&entry, match_values,
|
||||
matches, &action_value,
|
||||
&action, type);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mlxsw_sp_dpipe_table_host_entries_get(mlxsw_sp, &entry,
|
||||
counters_enabled, dump_ctx,
|
||||
type);
|
||||
out:
|
||||
devlink_dpipe_entry_clear(&entry);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_dpipe_table_host4_entries_dump(void *priv, bool counters_enabled,
|
||||
struct devlink_dpipe_dump_ctx *dump_ctx)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = priv;
|
||||
|
||||
return mlxsw_sp_dpipe_table_host_entries_dump(mlxsw_sp,
|
||||
counters_enabled,
|
||||
dump_ctx, AF_INET);
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_dpipe_table_host_counters_update(struct mlxsw_sp *mlxsw_sp,
|
||||
bool enable, int type)
|
||||
{
|
||||
int i;
|
||||
|
||||
rtnl_lock();
|
||||
for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
|
||||
struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry;
|
||||
|
||||
if (!rif)
|
||||
continue;
|
||||
mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {
|
||||
if (mlxsw_sp_neigh_entry_type(neigh_entry) != type)
|
||||
continue;
|
||||
mlxsw_sp_neigh_entry_counter_update(mlxsw_sp,
|
||||
neigh_entry,
|
||||
enable);
|
||||
}
|
||||
}
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static int mlxsw_sp_dpipe_table_host4_counters_update(void *priv, bool enable)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = priv;
|
||||
|
||||
mlxsw_sp_dpipe_table_host_counters_update(mlxsw_sp, enable, AF_INET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64
|
||||
mlxsw_sp_dpipe_table_host_size_get(struct mlxsw_sp *mlxsw_sp, int type)
|
||||
{
|
||||
u64 size = 0;
|
||||
int i;
|
||||
|
||||
rtnl_lock();
|
||||
for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
|
||||
struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry;
|
||||
|
||||
if (!rif)
|
||||
continue;
|
||||
mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {
|
||||
if (mlxsw_sp_neigh_entry_type(neigh_entry) != type)
|
||||
continue;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
rtnl_unlock();
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static u64 mlxsw_sp_dpipe_table_host4_size_get(void *priv)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = priv;
|
||||
|
||||
return mlxsw_sp_dpipe_table_host_size_get(mlxsw_sp, AF_INET);
|
||||
}
|
||||
|
||||
static struct devlink_dpipe_table_ops mlxsw_sp_host4_ops = {
|
||||
.matches_dump = mlxsw_sp_dpipe_table_host4_matches_dump,
|
||||
.actions_dump = mlxsw_sp_dpipe_table_host4_actions_dump,
|
||||
.entries_dump = mlxsw_sp_dpipe_table_host4_entries_dump,
|
||||
.counters_set_update = mlxsw_sp_dpipe_table_host4_counters_update,
|
||||
.size_get = mlxsw_sp_dpipe_table_host4_size_get,
|
||||
};
|
||||
|
||||
static int mlxsw_sp_dpipe_host4_table_init(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
||||
|
||||
return devlink_dpipe_table_register(devlink,
|
||||
MLXSW_SP_DPIPE_TABLE_NAME_HOST4,
|
||||
&mlxsw_sp_host4_ops,
|
||||
mlxsw_sp, false);
|
||||
}
|
||||
|
||||
static void mlxsw_sp_dpipe_host4_table_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
||||
|
||||
devlink_dpipe_table_unregister(devlink,
|
||||
MLXSW_SP_DPIPE_TABLE_NAME_HOST4);
|
||||
}
|
||||
|
||||
int mlxsw_sp_dpipe_init(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
||||
@ -339,10 +699,16 @@ int mlxsw_sp_dpipe_init(struct mlxsw_sp *mlxsw_sp)
|
||||
return err;
|
||||
err = mlxsw_sp_dpipe_erif_table_init(mlxsw_sp);
|
||||
if (err)
|
||||
goto err_erif_register;
|
||||
goto err_erif_table_init;
|
||||
|
||||
err = mlxsw_sp_dpipe_host4_table_init(mlxsw_sp);
|
||||
if (err)
|
||||
goto err_host4_table_init;
|
||||
return 0;
|
||||
|
||||
err_erif_register:
|
||||
err_host4_table_init:
|
||||
mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp);
|
||||
err_erif_table_init:
|
||||
devlink_dpipe_headers_unregister(priv_to_devlink(mlxsw_sp->core));
|
||||
return err;
|
||||
}
|
||||
@ -351,6 +717,7 @@ void mlxsw_sp_dpipe_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
||||
|
||||
mlxsw_sp_dpipe_host4_table_fini(mlxsw_sp);
|
||||
mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp);
|
||||
devlink_dpipe_headers_unregister(devlink);
|
||||
}
|
||||
|
@ -39,5 +39,6 @@ int mlxsw_sp_dpipe_init(struct mlxsw_sp *mlxsw_sp);
|
||||
void mlxsw_sp_dpipe_fini(struct mlxsw_sp *mlxsw_sp);
|
||||
|
||||
#define MLXSW_SP_DPIPE_TABLE_NAME_ERIF "mlxsw_erif"
|
||||
#define MLXSW_SP_DPIPE_TABLE_NAME_HOST4 "mlxsw_host4"
|
||||
|
||||
#endif /* _MLXSW_PIPELINE_H_*/
|
||||
|
@ -901,6 +901,8 @@ struct mlxsw_sp_neigh_entry {
|
||||
* this neigh entry
|
||||
*/
|
||||
struct list_head nexthop_neighs_list_node;
|
||||
unsigned int counter_index;
|
||||
bool counter_valid;
|
||||
};
|
||||
|
||||
static const struct rhashtable_params mlxsw_sp_neigh_ht_params = {
|
||||
@ -909,6 +911,53 @@ static const struct rhashtable_params mlxsw_sp_neigh_ht_params = {
|
||||
.key_len = sizeof(struct mlxsw_sp_neigh_key),
|
||||
};
|
||||
|
||||
struct mlxsw_sp_neigh_entry *
|
||||
mlxsw_sp_rif_neigh_next(struct mlxsw_sp_rif *rif,
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry)
|
||||
{
|
||||
if (!neigh_entry) {
|
||||
if (list_empty(&rif->neigh_list))
|
||||
return NULL;
|
||||
else
|
||||
return list_first_entry(&rif->neigh_list,
|
||||
typeof(*neigh_entry),
|
||||
rif_list_node);
|
||||
}
|
||||
if (neigh_entry->rif_list_node.next == &rif->neigh_list)
|
||||
return NULL;
|
||||
return list_next_entry(neigh_entry, rif_list_node);
|
||||
}
|
||||
|
||||
int mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry *neigh_entry)
|
||||
{
|
||||
return neigh_entry->key.n->tbl->family;
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
mlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry *neigh_entry)
|
||||
{
|
||||
return neigh_entry->ha;
|
||||
}
|
||||
|
||||
u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
|
||||
{
|
||||
struct neighbour *n;
|
||||
|
||||
n = neigh_entry->key.n;
|
||||
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 *
|
||||
mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n,
|
||||
u16 rif)
|
||||
@ -949,6 +998,41 @@ mlxsw_sp_neigh_entry_remove(struct mlxsw_sp *mlxsw_sp,
|
||||
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 *
|
||||
mlxsw_sp_neigh_entry_create(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
|
||||
{
|
||||
@ -968,6 +1052,7 @@ mlxsw_sp_neigh_entry_create(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
|
||||
if (err)
|
||||
goto err_neigh_entry_insert;
|
||||
|
||||
mlxsw_sp_neigh_counter_alloc(mlxsw_sp, neigh_entry);
|
||||
list_add(&neigh_entry->rif_list_node, &rif->neigh_list);
|
||||
|
||||
return neigh_entry;
|
||||
@ -982,6 +1067,7 @@ mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry)
|
||||
{
|
||||
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_free(neigh_entry);
|
||||
}
|
||||
@ -1287,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,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1301,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,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1337,6 +1429,18 @@ mlxsw_sp_neigh_entry_update(struct mlxsw_sp *mlxsw_sp,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry,
|
||||
bool adding)
|
||||
{
|
||||
if (adding)
|
||||
mlxsw_sp_neigh_counter_alloc(mlxsw_sp, neigh_entry);
|
||||
else
|
||||
mlxsw_sp_neigh_counter_free(mlxsw_sp, neigh_entry);
|
||||
mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, true);
|
||||
}
|
||||
|
||||
struct mlxsw_sp_neigh_event_work {
|
||||
struct work_struct work;
|
||||
struct mlxsw_sp *mlxsw_sp;
|
||||
|
@ -42,6 +42,8 @@ enum mlxsw_sp_rif_counter_dir {
|
||||
MLXSW_SP_RIF_COUNTER_EGRESS,
|
||||
};
|
||||
|
||||
struct mlxsw_sp_neigh_entry;
|
||||
|
||||
struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp,
|
||||
u16 rif_index);
|
||||
u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif);
|
||||
@ -56,5 +58,23 @@ void mlxsw_sp_rif_counter_free(struct mlxsw_sp *mlxsw_sp,
|
||||
int mlxsw_sp_rif_counter_alloc(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_rif *rif,
|
||||
enum mlxsw_sp_rif_counter_dir dir);
|
||||
struct mlxsw_sp_neigh_entry *
|
||||
mlxsw_sp_rif_neigh_next(struct mlxsw_sp_rif *rif,
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry);
|
||||
int mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry *neigh_entry);
|
||||
unsigned char *
|
||||
mlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry *neigh_entry);
|
||||
u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry);
|
||||
|
||||
#define mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) \
|
||||
for (neigh_entry = mlxsw_sp_rif_neigh_next(rif, NULL); 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);
|
||||
void
|
||||
mlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry,
|
||||
bool adding);
|
||||
|
||||
#endif /* _MLXSW_ROUTER_H_*/
|
||||
|
@ -178,7 +178,6 @@ struct devlink_dpipe_table_ops;
|
||||
* struct devlink_dpipe_table - table object
|
||||
* @priv: private
|
||||
* @name: table name
|
||||
* @size: maximum number of entries
|
||||
* @counters_enabled: indicates if counters are active
|
||||
* @counter_control_extern: indicates if counter control is in dpipe or
|
||||
* external tool
|
||||
@ -189,7 +188,6 @@ struct devlink_dpipe_table {
|
||||
void *priv;
|
||||
struct list_head list;
|
||||
const char *name;
|
||||
u64 size;
|
||||
bool counters_enabled;
|
||||
bool counter_control_extern;
|
||||
struct devlink_dpipe_table_ops *table_ops;
|
||||
@ -204,6 +202,7 @@ struct devlink_dpipe_table {
|
||||
* @counters_set_update - when changing the counter status hardware sync
|
||||
* maybe needed to allocate/free counter related
|
||||
* resources
|
||||
* @size_get - get size
|
||||
*/
|
||||
struct devlink_dpipe_table_ops {
|
||||
int (*actions_dump)(void *priv, struct sk_buff *skb);
|
||||
@ -211,6 +210,7 @@ struct devlink_dpipe_table_ops {
|
||||
int (*entries_dump)(void *priv, bool counters_enabled,
|
||||
struct devlink_dpipe_dump_ctx *dump_ctx);
|
||||
int (*counters_set_update)(void *priv, bool enable);
|
||||
u64 (*size_get)(void *priv);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -311,8 +311,7 @@ void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index);
|
||||
int devlink_dpipe_table_register(struct devlink *devlink,
|
||||
const char *table_name,
|
||||
struct devlink_dpipe_table_ops *table_ops,
|
||||
void *priv, u64 size,
|
||||
bool counter_control_extern);
|
||||
void *priv, bool counter_control_extern);
|
||||
void devlink_dpipe_table_unregister(struct devlink *devlink,
|
||||
const char *table_name);
|
||||
int devlink_dpipe_headers_register(struct devlink *devlink,
|
||||
@ -324,10 +323,13 @@ int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx);
|
||||
int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx,
|
||||
struct devlink_dpipe_entry *entry);
|
||||
int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx);
|
||||
void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry);
|
||||
int devlink_dpipe_action_put(struct sk_buff *skb,
|
||||
struct devlink_dpipe_action *action);
|
||||
int devlink_dpipe_match_put(struct sk_buff *skb,
|
||||
struct devlink_dpipe_match *match);
|
||||
extern struct devlink_dpipe_header devlink_dpipe_header_ethernet;
|
||||
extern struct devlink_dpipe_header devlink_dpipe_header_ipv4;
|
||||
|
||||
#else
|
||||
|
||||
@ -447,6 +449,11 @@ devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int
|
||||
devlink_dpipe_action_put(struct sk_buff *skb,
|
||||
struct devlink_dpipe_action *action)
|
||||
|
@ -226,4 +226,17 @@ enum devlink_dpipe_action_type {
|
||||
DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY,
|
||||
};
|
||||
|
||||
enum devlink_dpipe_field_ethernet_id {
|
||||
DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC,
|
||||
};
|
||||
|
||||
enum devlink_dpipe_field_ipv4_id {
|
||||
DEVLINK_DPIPE_FIELD_IPV4_DST_IP,
|
||||
};
|
||||
|
||||
enum devlink_dpipe_header_id {
|
||||
DEVLINK_DPIPE_HEADER_ETHERNET,
|
||||
DEVLINK_DPIPE_HEADER_IPV4,
|
||||
};
|
||||
|
||||
#endif /* _UAPI_LINUX_DEVLINK_H_ */
|
||||
|
@ -29,6 +29,40 @@
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/devlink.h>
|
||||
|
||||
static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = {
|
||||
{
|
||||
.name = "destination_mac",
|
||||
.id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC,
|
||||
.bitwidth = 48,
|
||||
},
|
||||
};
|
||||
|
||||
struct devlink_dpipe_header devlink_dpipe_header_ethernet = {
|
||||
.name = "ethernet",
|
||||
.id = DEVLINK_DPIPE_HEADER_ETHERNET,
|
||||
.fields = devlink_dpipe_fields_ethernet,
|
||||
.fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet),
|
||||
.global = true,
|
||||
};
|
||||
EXPORT_SYMBOL(devlink_dpipe_header_ethernet);
|
||||
|
||||
static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = {
|
||||
{
|
||||
.name = "destination ip",
|
||||
.id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP,
|
||||
.bitwidth = 32,
|
||||
},
|
||||
};
|
||||
|
||||
struct devlink_dpipe_header devlink_dpipe_header_ipv4 = {
|
||||
.name = "ipv4",
|
||||
.id = DEVLINK_DPIPE_HEADER_IPV4,
|
||||
.fields = devlink_dpipe_fields_ipv4,
|
||||
.fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4),
|
||||
.global = true,
|
||||
};
|
||||
EXPORT_SYMBOL(devlink_dpipe_header_ipv4);
|
||||
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg);
|
||||
|
||||
static LIST_HEAD(devlink_list);
|
||||
@ -1613,13 +1647,15 @@ static int devlink_dpipe_table_put(struct sk_buff *skb,
|
||||
struct devlink_dpipe_table *table)
|
||||
{
|
||||
struct nlattr *table_attr;
|
||||
u64 table_size;
|
||||
|
||||
table_size = table->table_ops->size_get(table->priv);
|
||||
table_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE);
|
||||
if (!table_attr)
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) ||
|
||||
nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table->size,
|
||||
nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size,
|
||||
DEVLINK_ATTR_PAD))
|
||||
goto nla_put_failure;
|
||||
if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED,
|
||||
@ -1960,6 +1996,28 @@ int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close);
|
||||
|
||||
void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry)
|
||||
|
||||
{
|
||||
unsigned int value_count, value_index;
|
||||
struct devlink_dpipe_value *value;
|
||||
|
||||
value = entry->action_values;
|
||||
value_count = entry->action_values_count;
|
||||
for (value_index = 0; value_index < value_count; value_index++) {
|
||||
kfree(value[value_index].value);
|
||||
kfree(value[value_index].mask);
|
||||
}
|
||||
|
||||
value = entry->match_values;
|
||||
value_count = entry->match_values_count;
|
||||
for (value_index = 0; value_index < value_count; value_index++) {
|
||||
kfree(value[value_index].value);
|
||||
kfree(value[value_index].mask);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(devlink_dpipe_entry_clear);
|
||||
|
||||
static int devlink_dpipe_entries_fill(struct genl_info *info,
|
||||
enum devlink_command cmd, int flags,
|
||||
struct devlink_dpipe_table *table)
|
||||
@ -2684,20 +2742,21 @@ EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled);
|
||||
* @table_name: table name
|
||||
* @table_ops: table ops
|
||||
* @priv: priv
|
||||
* @size: size
|
||||
* @counter_control_extern: external control for counters
|
||||
*/
|
||||
int devlink_dpipe_table_register(struct devlink *devlink,
|
||||
const char *table_name,
|
||||
struct devlink_dpipe_table_ops *table_ops,
|
||||
void *priv, u64 size,
|
||||
bool counter_control_extern)
|
||||
void *priv, bool counter_control_extern)
|
||||
{
|
||||
struct devlink_dpipe_table *table;
|
||||
|
||||
if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name))
|
||||
return -EEXIST;
|
||||
|
||||
if (WARN_ON(!table_ops->size_get))
|
||||
return -EINVAL;
|
||||
|
||||
table = kzalloc(sizeof(*table), GFP_KERNEL);
|
||||
if (!table)
|
||||
return -ENOMEM;
|
||||
@ -2705,7 +2764,6 @@ int devlink_dpipe_table_register(struct devlink *devlink,
|
||||
table->name = table_name;
|
||||
table->table_ops = table_ops;
|
||||
table->priv = priv;
|
||||
table->size = size;
|
||||
table->counter_control_extern = counter_control_extern;
|
||||
|
||||
mutex_lock(&devlink_mutex);
|
||||
|
Loading…
Reference in New Issue
Block a user