Skip to content

Commit

Permalink
genetlink: use idr to track families
Browse files Browse the repository at this point in the history
Since generic netlink family IDs are small integers, allocated
densely, IDR is an ideal match for lookups. Replace the existing
hand-written hash-table with IDR for allocation and lookup.

This lets the families only be written to once, during register,
since the list_head can be removed and removal of a family won't
cause any writes.

It also slightly reduces the code size (by about 1.3k on x86-64).

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
jmberg-intel authored and davem330 committed Oct 27, 2016
1 parent 489111e commit 2ae0f17
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 181 deletions.
31 changes: 15 additions & 16 deletions include/net/genetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ struct genl_info;
* generic netlink family is removed while there are still open
* sockets.
* @attrbuf: buffer to store parsed attributes (private)
* @family_list: family list (private)
* @mcgrps: multicast groups used by this family
* @n_mcgrps: number of multicast groups
* @mcgrp_offset: starting number of multicast group IDs in this family
Expand Down Expand Up @@ -70,11 +69,10 @@ struct genl_family {
unsigned int n_ops;
unsigned int n_mcgrps;
unsigned int mcgrp_offset; /* private */
struct list_head family_list; /* private */
struct module *module;
};

struct nlattr **genl_family_attrbuf(struct genl_family *family);
struct nlattr **genl_family_attrbuf(const struct genl_family *family);

/**
* struct genl_info - receiving information
Expand Down Expand Up @@ -134,12 +132,12 @@ struct genl_ops {
};

int genl_register_family(struct genl_family *family);
int genl_unregister_family(struct genl_family *family);
void genl_notify(struct genl_family *family, struct sk_buff *skb,
int genl_unregister_family(const struct genl_family *family);
void genl_notify(const struct genl_family *family, struct sk_buff *skb,
struct genl_info *info, u32 group, gfp_t flags);

void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
struct genl_family *family, int flags, u8 cmd);
const struct genl_family *family, int flags, u8 cmd);

/**
* genlmsg_nlhdr - Obtain netlink header from user specified header
Expand All @@ -148,8 +146,8 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
*
* Returns pointer to netlink header.
*/
static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr,
struct genl_family *family)
static inline struct nlmsghdr *
genlmsg_nlhdr(void *user_hdr, const struct genl_family *family)
{
return (struct nlmsghdr *)((char *)user_hdr -
family->hdrsize -
Expand Down Expand Up @@ -185,7 +183,7 @@ static inline int genlmsg_parse(const struct nlmsghdr *nlh,
*/
static inline void genl_dump_check_consistent(struct netlink_callback *cb,
void *user_hdr,
struct genl_family *family)
const struct genl_family *family)
{
nl_dump_check_consistent(cb, genlmsg_nlhdr(user_hdr, family));
}
Expand All @@ -202,7 +200,7 @@ static inline void genl_dump_check_consistent(struct netlink_callback *cb,
*/
static inline void *genlmsg_put_reply(struct sk_buff *skb,
struct genl_info *info,
struct genl_family *family,
const struct genl_family *family,
int flags, u8 cmd)
{
return genlmsg_put(skb, info->snd_portid, info->snd_seq, family,
Expand Down Expand Up @@ -239,7 +237,7 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
* @group: offset of multicast group in groups array
* @flags: allocation flags
*/
static inline int genlmsg_multicast_netns(struct genl_family *family,
static inline int genlmsg_multicast_netns(const struct genl_family *family,
struct net *net, struct sk_buff *skb,
u32 portid, unsigned int group, gfp_t flags)
{
Expand All @@ -257,7 +255,7 @@ static inline int genlmsg_multicast_netns(struct genl_family *family,
* @group: offset of multicast group in groups array
* @flags: allocation flags
*/
static inline int genlmsg_multicast(struct genl_family *family,
static inline int genlmsg_multicast(const struct genl_family *family,
struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags)
{
Expand All @@ -275,7 +273,7 @@ static inline int genlmsg_multicast(struct genl_family *family,
*
* This function must hold the RTNL or rcu_read_lock().
*/
int genlmsg_multicast_allns(struct genl_family *family,
int genlmsg_multicast_allns(const struct genl_family *family,
struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags);

Expand Down Expand Up @@ -359,16 +357,17 @@ static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
* This function returns the number of broadcast listeners that have set the
* NETLINK_RECV_NO_ENOBUFS socket option.
*/
static inline int genl_set_err(struct genl_family *family, struct net *net,
u32 portid, u32 group, int code)
static inline int genl_set_err(const struct genl_family *family,
struct net *net, u32 portid,
u32 group, int code)
{
if (WARN_ON_ONCE(group >= family->n_mcgrps))
return -EINVAL;
group = family->mcgrp_offset + group;
return netlink_set_err(net->genl_sock, portid, group, code);
}

static inline int genl_has_listeners(struct genl_family *family,
static inline int genl_has_listeners(const struct genl_family *family,
struct net *net, unsigned int group)
{
if (WARN_ON_ONCE(group >= family->n_mcgrps))
Expand Down
2 changes: 2 additions & 0 deletions include/uapi/linux/genetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ struct genlmsghdr {
#define GENL_ID_CTRL NLMSG_MIN_TYPE
#define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1)
#define GENL_ID_PMCRAID (NLMSG_MIN_TYPE + 2)
/* must be last reserved + 1 */
#define GENL_START_ALLOC (NLMSG_MIN_TYPE + 3)

/**************************************************************************
* Controller
Expand Down
Loading

0 comments on commit 2ae0f17

Please sign in to comment.