devlink: Add devlink formatted message (fmsg) API

Devlink fmsg is a mechanism to pass descriptors between drivers and
devlink, in json-like format. The API allows the driver to add nested
attributes such as object, object pair and value array, in addition to
attributes such as name and value.

Driver can use this API to fill the fmsg context in a format which will be
translated by the devlink to the netlink message later.
There is no memory allocation in advance (other than the initial list
head), and it dynamically allocates messages descriptors and add them to
the list on the fly.

When it needs to send the data using SKBs to the netlink layer, it
fragments the data between different SKBs. In order to do this
fragmentation, it uses virtual nests attributes, to avoid actual
nesting use which cannot be divided between different SKBs.

Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
Reviewed-by: Moshe Shemesh <moshe@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Eran Ben Elisha 2019-02-07 11:36:32 +02:00 committed by David S. Miller
parent 8f28980561
commit 1db64e8733
3 changed files with 640 additions and 0 deletions

View file

@ -448,6 +448,8 @@ struct devlink_info_req;
typedef void devlink_snapshot_data_dest_t(const void *data);
struct devlink_fmsg;
struct devlink_ops {
int (*reload)(struct devlink *devlink, struct netlink_ext_ack *extack);
int (*port_type_set)(struct devlink_port *devlink_port,
@ -639,6 +641,37 @@ int devlink_info_version_running_put(struct devlink_info_req *req,
const char *version_name,
const char *version_value);
int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg);
int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg);
int devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name);
int devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg);
int devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg,
const char *name);
int devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg);
int devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value);
int devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value);
int devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value);
int devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value);
int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value);
int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value,
u16 value_len);
int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name,
bool value);
int devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name,
u8 value);
int devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name,
u32 value);
int devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name,
u64 value);
int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name,
const char *value);
int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name,
const void *value, u16 value_len);
#else
static inline struct devlink *devlink_alloc(const struct devlink_ops *ops,
@ -971,6 +1004,122 @@ devlink_info_version_running_put(struct devlink_info_req *req,
{
return 0;
}
static inline int
devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg)
{
return 0;
}
static inline int
devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg)
{
return 0;
}
static inline int
devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name)
{
return 0;
}
static inline int
devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg)
{
return 0;
}
static inline int
devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg,
const char *name)
{
return 0;
}
static inline int
devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg)
{
return 0;
}
static inline int
devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value)
{
return 0;
}
static inline int
devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value)
{
return 0;
}
static inline int
devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value)
{
return 0;
}
static inline int
devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value)
{
return 0;
}
static inline int
devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value)
{
return 0;
}
static inline int
devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value,
u16 value_len)
{
return 0;
}
static inline int
devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name,
bool value)
{
return 0;
}
static inline int
devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name,
u8 value)
{
return 0;
}
static inline int
devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name,
u32 value)
{
return 0;
}
static inline int
devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name,
u64 value)
{
return 0;
}
static inline int
devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name,
const char *value)
{
return 0;
}
static inline int
devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name,
const void *value, u16 value_len)
{
return 0;
}
#endif
#if IS_REACHABLE(CONFIG_NET_DEVLINK)