Commit fb3bbbda authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents a5e2da6e a481d713
...@@ -5000,6 +5000,15 @@ enum mlxsw_reg_rauht_trap_id { ...@@ -5000,6 +5000,15 @@ enum mlxsw_reg_rauht_trap_id {
*/ */
MLXSW_ITEM32(reg, rauht, trap_id, 0x60, 0, 9); 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 /* reg_rauht_counter_set_type
* Counter set type for flow counters * Counter set type for flow counters
* Access: RW * Access: RW
...@@ -5045,6 +5054,14 @@ static inline void mlxsw_reg_rauht_pack6(char *payload, ...@@ -5045,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
...@@ -6041,15 +6058,6 @@ static inline void mlxsw_reg_mpsc_pack(char *payload, u8 local_port, bool e, ...@@ -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); 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 /* reg_mgpc_counter_set_type
* Counter set type. * Counter set type.
* Access: OP * Access: OP
...@@ -6089,7 +6097,7 @@ MLXSW_ITEM64(reg, mgpc, packet_counter, 0x10, 0, 64); ...@@ -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, static inline void mlxsw_reg_mgpc_pack(char *payload, u32 counter_index,
enum mlxsw_reg_mgpc_opcode opcode, 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_ZERO(mgpc, payload);
mlxsw_reg_mgpc_counter_index_set(payload, counter_index); mlxsw_reg_mgpc_counter_index_set(payload, counter_index);
......
...@@ -382,11 +382,13 @@ int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp, ...@@ -382,11 +382,13 @@ int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp,
int err; int err;
mlxsw_reg_mgpc_pack(mgpc_pl, counter_index, MLXSW_REG_MGPC_OPCODE_NOP, 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); 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;
} }
...@@ -397,7 +399,7 @@ static int mlxsw_sp_flow_counter_clear(struct mlxsw_sp *mlxsw_sp, ...@@ -397,7 +399,7 @@ static int mlxsw_sp_flow_counter_clear(struct mlxsw_sp *mlxsw_sp,
char mgpc_pl[MLXSW_REG_MGPC_LEN]; char mgpc_pl[MLXSW_REG_MGPC_LEN];
mlxsw_reg_mgpc_pack(mgpc_pl, counter_index, MLXSW_REG_MGPC_OPCODE_CLEAR, 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); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mgpc), mgpc_pl);
} }
......
...@@ -39,5 +39,6 @@ int mlxsw_sp_dpipe_init(struct mlxsw_sp *mlxsw_sp); ...@@ -39,5 +39,6 @@ int mlxsw_sp_dpipe_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_dpipe_fini(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_ERIF "mlxsw_erif"
#define MLXSW_SP_DPIPE_TABLE_NAME_HOST4 "mlxsw_host4"
#endif /* _MLXSW_PIPELINE_H_*/ #endif /* _MLXSW_PIPELINE_H_*/
...@@ -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 = {
...@@ -909,6 +911,53 @@ 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), .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 * 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)
...@@ -949,6 +998,41 @@ mlxsw_sp_neigh_entry_remove(struct mlxsw_sp *mlxsw_sp, ...@@ -949,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)
{ {
...@@ -968,6 +1052,7 @@ 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) 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;
...@@ -982,6 +1067,7 @@ mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp *mlxsw_sp, ...@@ -982,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);
} }
...@@ -1287,6 +1373,9 @@ mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp *mlxsw_sp, ...@@ -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, 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);
} }
...@@ -1301,6 +1390,9 @@ mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp *mlxsw_sp, ...@@ -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, 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);
} }
...@@ -1337,6 +1429,18 @@ mlxsw_sp_neigh_entry_update(struct mlxsw_sp *mlxsw_sp, ...@@ -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 mlxsw_sp_neigh_event_work {
struct work_struct work; struct work_struct work;
struct mlxsw_sp *mlxsw_sp; struct mlxsw_sp *mlxsw_sp;
......
...@@ -42,6 +42,8 @@ enum mlxsw_sp_rif_counter_dir { ...@@ -42,6 +42,8 @@ enum mlxsw_sp_rif_counter_dir {
MLXSW_SP_RIF_COUNTER_EGRESS, 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, struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp,
u16 rif_index); u16 rif_index);
u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif); 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, ...@@ -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, int mlxsw_sp_rif_counter_alloc(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *rif, struct mlxsw_sp_rif *rif,
enum mlxsw_sp_rif_counter_dir dir); 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_*/ #endif /* _MLXSW_ROUTER_H_*/
...@@ -178,7 +178,6 @@ struct devlink_dpipe_table_ops; ...@@ -178,7 +178,6 @@ struct devlink_dpipe_table_ops;
* struct devlink_dpipe_table - table object * struct devlink_dpipe_table - table object
* @priv: private * @priv: private
* @name: table name * @name: table name
* @size: maximum number of entries
* @counters_enabled: indicates if counters are active * @counters_enabled: indicates if counters are active
* @counter_control_extern: indicates if counter control is in dpipe or * @counter_control_extern: indicates if counter control is in dpipe or
* external tool * external tool
...@@ -189,7 +188,6 @@ struct devlink_dpipe_table { ...@@ -189,7 +188,6 @@ struct devlink_dpipe_table {
void *priv; void *priv;
struct list_head list; struct list_head list;
const char *name; const char *name;
u64 size;
bool counters_enabled; bool counters_enabled;
bool counter_control_extern; bool counter_control_extern;
struct devlink_dpipe_table_ops *table_ops; struct devlink_dpipe_table_ops *table_ops;
...@@ -204,6 +202,7 @@ struct devlink_dpipe_table { ...@@ -204,6 +202,7 @@ struct devlink_dpipe_table {
* @counters_set_update - when changing the counter status hardware sync * @counters_set_update - when changing the counter status hardware sync
* maybe needed to allocate/free counter related * maybe needed to allocate/free counter related
* resources * resources
* @size_get - get size
*/ */
struct devlink_dpipe_table_ops { struct devlink_dpipe_table_ops {
int (*actions_dump)(void *priv, struct sk_buff *skb); int (*actions_dump)(void *priv, struct sk_buff *skb);
...@@ -211,6 +210,7 @@ struct devlink_dpipe_table_ops { ...@@ -211,6 +210,7 @@ struct devlink_dpipe_table_ops {
int (*entries_dump)(void *priv, bool counters_enabled, int (*entries_dump)(void *priv, bool counters_enabled,
struct devlink_dpipe_dump_ctx *dump_ctx); struct devlink_dpipe_dump_ctx *dump_ctx);
int (*counters_set_update)(void *priv, bool enable); 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); ...@@ -311,8 +311,7 @@ void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index);
int devlink_dpipe_table_register(struct devlink *devlink, int devlink_dpipe_table_register(struct devlink *devlink,
const char *table_name, const char *table_name,
struct devlink_dpipe_table_ops *table_ops, struct devlink_dpipe_table_ops *table_ops,
void *priv, u64 size, void *priv, bool counter_control_extern);
bool counter_control_extern);
void devlink_dpipe_table_unregister(struct devlink *devlink, void devlink_dpipe_table_unregister(struct devlink *devlink,
const char *table_name); const char *table_name);
int devlink_dpipe_headers_register(struct devlink *devlink, 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); ...@@ -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, int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx,
struct devlink_dpipe_entry *entry); struct devlink_dpipe_entry *entry);
int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx); 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, int devlink_dpipe_action_put(struct sk_buff *skb,
struct devlink_dpipe_action *action); struct devlink_dpipe_action *action);
int devlink_dpipe_match_put(struct sk_buff *skb, int devlink_dpipe_match_put(struct sk_buff *skb,
struct devlink_dpipe_match *match); struct devlink_dpipe_match *match);
extern struct devlink_dpipe_header devlink_dpipe_header_ethernet;
extern struct devlink_dpipe_header devlink_dpipe_header_ipv4;
#else #else
...@@ -447,6 +449,11 @@ devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx) ...@@ -447,6 +449,11 @@ devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx)
return 0; return 0;
} }
static inline void
devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry)
{
}
static inline int static inline int
devlink_dpipe_action_put(struct sk_buff *skb, devlink_dpipe_action_put(struct sk_buff *skb,
struct devlink_dpipe_action *action) struct devlink_dpipe_action *action)
......
...@@ -226,4 +226,17 @@ enum devlink_dpipe_action_type { ...@@ -226,4 +226,17 @@ enum devlink_dpipe_action_type {
DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY, 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_ */ #endif /* _UAPI_LINUX_DEVLINK_H_ */
...@@ -29,6 +29,40 @@ ...@@ -29,6 +29,40 @@
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/devlink.h> #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); EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg);
static LIST_HEAD(devlink_list); static LIST_HEAD(devlink_list);
...@@ -1613,13 +1647,15 @@ static int devlink_dpipe_table_put(struct sk_buff *skb, ...@@ -1613,13 +1647,15 @@ static int devlink_dpipe_table_put(struct sk_buff *skb,
struct devlink_dpipe_table *table) struct devlink_dpipe_table *table)
{ {
struct nlattr *table_attr; 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); table_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE);
if (!table_attr) if (!table_attr)
return -EMSGSIZE; return -EMSGSIZE;
if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) || 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)) DEVLINK_ATTR_PAD))
goto nla_put_failure; goto nla_put_failure;
if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED, 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) ...@@ -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); 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, static int devlink_dpipe_entries_fill(struct genl_info *info,
enum devlink_command cmd, int flags, enum devlink_command cmd, int flags,
struct devlink_dpipe_table *table) struct devlink_dpipe_table *table)
...@@ -2684,20 +2742,21 @@ EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled); ...@@ -2684,20 +2742,21 @@ EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled);
* @table_name: table name * @table_name: table name
* @table_ops: table ops * @table_ops: table ops
* @priv: priv * @priv: priv
* @size: size
* @counter_control_extern: external control for counters * @counter_control_extern: external control for counters
*/ */
int devlink_dpipe_table_register(struct devlink *devlink, int devlink_dpipe_table_register(struct devlink *devlink,
const char *table_name, const char *table_name,
struct devlink_dpipe_table_ops *table_ops, struct devlink_dpipe_table_ops *table_ops,
void *priv, u64 size, void *priv, bool counter_control_extern)
bool counter_control_extern)
{ {
struct devlink_dpipe_table *table; struct devlink_dpipe_table *table;
if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name)) if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name))
return -EEXIST; return -EEXIST;
if (WARN_ON(!table_ops->size_get))
return -EINVAL;
table = kzalloc(sizeof(*table), GFP_KERNEL); table = kzalloc(sizeof(*table), GFP_KERNEL);
if (!table) if (!table)
return -ENOMEM; return -ENOMEM;
...@@ -2705,7 +2764,6 @@ int devlink_dpipe_table_register(struct devlink *devlink, ...@@ -2705,7 +2764,6 @@ int devlink_dpipe_table_register(struct devlink *devlink,
table->name = table_name; table->name = table_name;
table->table_ops = table_ops; table->table_ops = table_ops;
table->priv = priv; table->priv = priv;
table->size = size;
table->counter_control_extern = counter_control_extern; table->counter_control_extern = counter_control_extern;
mutex_lock(&devlink_mutex); mutex_lock(&devlink_mutex);
......
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