Skip to content

Commit

Permalink
Merge branch 'genetlink-support-per-command-policy-dump'
Browse files Browse the repository at this point in the history
Jakub Kicinski says:

====================
genetlink: support per-command policy dump

The objective of this series is to dump ethtool policies
to be able to tell which flags are supported by the kernel.
Current release adds ETHTOOL_FLAG_STATS for dumping extra
stats, but because of strict checking we need to make sure
that the flag is actually supported before setting it in
a request.

Ethtool policies are per command, and so far only dumping
family policies was supported.

The series adds new set of "light" ops to genl families which
don't have all the callbacks, and won't have the policy.
Most of families are then moved to these ops. This gives
us 4096B in savings on an allyesconfig build (not counting
the growth that would have happened when policy is added):

     text       data       bss        dec       hex
244415581  227958581  78372980  550747142  20d3bc06
244415581  227962677  78372980  550751238  20d3cc06

Next 5 patches deal the dumping per-op policy.

v3:

The actually patch to dump per-op policy was taken out and
will come in a series from Johannes, to make sure uAPI is
consistent from the start.

For dump-specific policies I think it should be fine to add
a new pair of members to the "full" ops, and not overthink it.

v2:
 - remove the stale comment in taskstats
 - split patch 8 -> 8, 9
 - now the getfamily policy is also in the op
 - make cmd u32
v1:
 - replace remaining uses of "light" with "small"
 - fix dump (ops can't be on the stack there)
 - coding changes in patch 4
 - new patch 7
 - don't echo op in responses - to make dump all easier

Dave - this series will cause a very trivial conflict with
the patch I sent to net. Both sides add some kdoc to struct
genl_ops so we'll need to keep it all.  I'm sending this
already because I also need to restructure ethool policies
in time for 5.10 if we want to use it for the stats flag.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Oct 3, 2020
2 parents 5a38b4f + a4bb4f5 commit 678cdd4
Show file tree
Hide file tree
Showing 36 changed files with 334 additions and 244 deletions.
6 changes: 3 additions & 3 deletions drivers/block/nbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2183,7 +2183,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
return ret;
}

static const struct genl_ops nbd_connect_genl_ops[] = {
static const struct genl_small_ops nbd_connect_genl_ops[] = {
{
.cmd = NBD_CMD_CONNECT,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Expand Down Expand Up @@ -2215,8 +2215,8 @@ static struct genl_family nbd_genl_family __ro_after_init = {
.name = NBD_GENL_FAMILY_NAME,
.version = NBD_GENL_VERSION,
.module = THIS_MODULE,
.ops = nbd_connect_genl_ops,
.n_ops = ARRAY_SIZE(nbd_connect_genl_ops),
.small_ops = nbd_connect_genl_ops,
.n_small_ops = ARRAY_SIZE(nbd_connect_genl_ops),
.maxattr = NBD_ATTR_MAX,
.policy = nbd_attr_policy,
.mcgrps = nbd_mcast_grps,
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/gtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1339,7 +1339,7 @@ static const struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = {
[GTPA_O_TEI] = { .type = NLA_U32, },
};

static const struct genl_ops gtp_genl_ops[] = {
static const struct genl_small_ops gtp_genl_ops[] = {
{
.cmd = GTP_CMD_NEWPDP,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Expand Down Expand Up @@ -1369,8 +1369,8 @@ static struct genl_family gtp_genl_family __ro_after_init = {
.policy = gtp_genl_policy,
.netnsok = true,
.module = THIS_MODULE,
.ops = gtp_genl_ops,
.n_ops = ARRAY_SIZE(gtp_genl_ops),
.small_ops = gtp_genl_ops,
.n_small_ops = ARRAY_SIZE(gtp_genl_ops),
.mcgrps = gtp_genl_mcgrps,
.n_mcgrps = ARRAY_SIZE(gtp_genl_mcgrps),
};
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/ieee802154/mac802154_hwsim.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ static const struct nla_policy hwsim_genl_policy[MAC802154_HWSIM_ATTR_MAX + 1] =
};

/* Generic Netlink operations array */
static const struct genl_ops hwsim_nl_ops[] = {
static const struct genl_small_ops hwsim_nl_ops[] = {
{
.cmd = MAC802154_HWSIM_CMD_NEW_RADIO,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Expand Down Expand Up @@ -628,8 +628,8 @@ static struct genl_family hwsim_genl_family __ro_after_init = {
.maxattr = MAC802154_HWSIM_ATTR_MAX,
.policy = hwsim_genl_policy,
.module = THIS_MODULE,
.ops = hwsim_nl_ops,
.n_ops = ARRAY_SIZE(hwsim_nl_ops),
.small_ops = hwsim_nl_ops,
.n_small_ops = ARRAY_SIZE(hwsim_nl_ops),
.mcgrps = hwsim_mcgrps,
.n_mcgrps = ARRAY_SIZE(hwsim_mcgrps),
};
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/macsec.c
Original file line number Diff line number Diff line change
Expand Up @@ -3285,7 +3285,7 @@ static int macsec_dump_txsc(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len;
}

static const struct genl_ops macsec_genl_ops[] = {
static const struct genl_small_ops macsec_genl_ops[] = {
{
.cmd = MACSEC_CMD_GET_TXSC,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Expand Down Expand Up @@ -3361,8 +3361,8 @@ static struct genl_family macsec_fam __ro_after_init = {
.policy = macsec_genl_policy,
.netnsok = true,
.module = THIS_MODULE,
.ops = macsec_genl_ops,
.n_ops = ARRAY_SIZE(macsec_genl_ops),
.small_ops = macsec_genl_ops,
.n_small_ops = ARRAY_SIZE(macsec_genl_ops),
};

static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/team/team.c
Original file line number Diff line number Diff line change
Expand Up @@ -2795,7 +2795,7 @@ static int team_nl_cmd_port_list_get(struct sk_buff *skb,
return err;
}

static const struct genl_ops team_nl_ops[] = {
static const struct genl_small_ops team_nl_ops[] = {
{
.cmd = TEAM_CMD_NOOP,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Expand Down Expand Up @@ -2832,8 +2832,8 @@ static struct genl_family team_nl_family __ro_after_init = {
.policy = team_nl_policy,
.netnsok = true,
.module = THIS_MODULE,
.ops = team_nl_ops,
.n_ops = ARRAY_SIZE(team_nl_ops),
.small_ops = team_nl_ops,
.n_small_ops = ARRAY_SIZE(team_nl_ops),
.mcgrps = team_nl_mcgrps,
.n_mcgrps = ARRAY_SIZE(team_nl_mcgrps),
};
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/wireless/mac80211_hwsim.c
Original file line number Diff line number Diff line change
Expand Up @@ -3964,7 +3964,7 @@ static int hwsim_dump_radio_nl(struct sk_buff *skb,
}

/* Generic Netlink operations array */
static const struct genl_ops hwsim_ops[] = {
static const struct genl_small_ops hwsim_ops[] = {
{
.cmd = HWSIM_CMD_REGISTER,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Expand Down Expand Up @@ -4008,8 +4008,8 @@ static struct genl_family hwsim_genl_family __ro_after_init = {
.policy = hwsim_genl_policy,
.netnsok = true,
.module = THIS_MODULE,
.ops = hwsim_ops,
.n_ops = ARRAY_SIZE(hwsim_ops),
.small_ops = hwsim_ops,
.n_small_ops = ARRAY_SIZE(hwsim_ops),
.mcgrps = hwsim_mcgrps,
.n_mcgrps = ARRAY_SIZE(hwsim_mcgrps),
};
Expand Down
6 changes: 3 additions & 3 deletions drivers/target/target_core_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ static int tcmu_genl_set_features(struct sk_buff *skb, struct genl_info *info)
return 0;
}

static const struct genl_ops tcmu_genl_ops[] = {
static const struct genl_small_ops tcmu_genl_ops[] = {
{
.cmd = TCMU_CMD_SET_FEATURES,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Expand Down Expand Up @@ -474,8 +474,8 @@ static struct genl_family tcmu_genl_family __ro_after_init = {
.mcgrps = tcmu_mcgrps,
.n_mcgrps = ARRAY_SIZE(tcmu_mcgrps),
.netnsok = true,
.ops = tcmu_genl_ops,
.n_ops = ARRAY_SIZE(tcmu_genl_ops),
.small_ops = tcmu_genl_ops,
.n_small_ops = ARRAY_SIZE(tcmu_genl_ops),
};

#define tcmu_cmd_set_dbi_cur(cmd, index) ((cmd)->dbi_cur = (index))
Expand Down
8 changes: 4 additions & 4 deletions drivers/thermal/thermal_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ static int thermal_genl_cmd_dumpit(struct sk_buff *skb,
{
struct param p = { .msg = skb };
const struct genl_dumpit_info *info = genl_dumpit_info(cb);
int cmd = info->ops->cmd;
int cmd = info->op.cmd;
int ret;
void *hdr;

Expand Down Expand Up @@ -601,7 +601,7 @@ static int thermal_genl_cmd_doit(struct sk_buff *skb,
return ret;
}

static const struct genl_ops thermal_genl_ops[] = {
static const struct genl_small_ops thermal_genl_ops[] = {
{
.cmd = THERMAL_GENL_CMD_TZ_GET_ID,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Expand Down Expand Up @@ -635,8 +635,8 @@ static struct genl_family thermal_gnl_family __ro_after_init = {
.version = THERMAL_GENL_VERSION,
.maxattr = THERMAL_GENL_ATTR_MAX,
.policy = thermal_genl_policy,
.ops = thermal_genl_ops,
.n_ops = ARRAY_SIZE(thermal_genl_ops),
.small_ops = thermal_genl_ops,
.n_small_ops = ARRAY_SIZE(thermal_genl_ops),
.mcgrps = thermal_genl_mcgrps,
.n_mcgrps = ARRAY_SIZE(thermal_genl_mcgrps),
};
Expand Down
6 changes: 3 additions & 3 deletions fs/dlm/netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ static int user_cmd(struct sk_buff *skb, struct genl_info *info)
return 0;
}

static const struct genl_ops dlm_nl_ops[] = {
static const struct genl_small_ops dlm_nl_ops[] = {
{
.cmd = DLM_CMD_HELLO,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Expand All @@ -73,8 +73,8 @@ static const struct genl_ops dlm_nl_ops[] = {
static struct genl_family family __ro_after_init = {
.name = DLM_GENL_NAME,
.version = DLM_GENL_VERSION,
.ops = dlm_nl_ops,
.n_ops = ARRAY_SIZE(dlm_nl_ops),
.small_ops = dlm_nl_ops,
.n_small_ops = ARRAY_SIZE(dlm_nl_ops),
.module = THIS_MODULE,
};

Expand Down
67 changes: 48 additions & 19 deletions include/net/genetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,21 @@ struct genl_info;
* (private)
* @ops: the operations supported by this family
* @n_ops: number of operations supported by this family
* @small_ops: the small-struct operations supported by this family
* @n_small_ops: number of small-struct operations supported by this family
*/
struct genl_family {
int id; /* private */
unsigned int hdrsize;
char name[GENL_NAMSIZ];
unsigned int version;
unsigned int maxattr;
bool netnsok;
bool parallel_ops;
unsigned int mcgrp_offset; /* private */
u8 netnsok:1;
u8 parallel_ops:1;
u8 n_ops;
u8 n_small_ops;
u8 n_mcgrps;
const struct nla_policy *policy;
int (*pre_doit)(const struct genl_ops *ops,
struct sk_buff *skb,
Expand All @@ -58,10 +64,8 @@ struct genl_family {
struct sk_buff *skb,
struct genl_info *info);
const struct genl_ops * ops;
const struct genl_small_ops *small_ops;
const struct genl_multicast_group *mcgrps;
unsigned int n_ops;
unsigned int n_mcgrps;
unsigned int mcgrp_offset; /* private */
struct module *module;
};

Expand Down Expand Up @@ -108,28 +112,33 @@ enum genl_validate_flags {
};

/**
* struct genl_info - info that is available during dumpit op call
* @family: generic netlink family - for internal genl code usage
* @ops: generic netlink ops - for internal genl code usage
* @attrs: netlink attributes
* struct genl_small_ops - generic netlink operations (small version)
* @cmd: command identifier
* @internal_flags: flags used by the family
* @flags: flags
* @validate: validation flags from enum genl_validate_flags
* @doit: standard command callback
* @dumpit: callback for dumpers
*
* This is a cut-down version of struct genl_ops for users who don't need
* most of the ancillary infra and want to save space.
*/
struct genl_dumpit_info {
const struct genl_family *family;
const struct genl_ops *ops;
struct nlattr **attrs;
struct genl_small_ops {
int (*doit)(struct sk_buff *skb, struct genl_info *info);
int (*dumpit)(struct sk_buff *skb, struct netlink_callback *cb);
u8 cmd;
u8 internal_flags;
u8 flags;
u8 validate;
};

static inline const struct genl_dumpit_info *
genl_dumpit_info(struct netlink_callback *cb)
{
return cb->data;
}

/**
* struct genl_ops - generic netlink operations
* @cmd: command identifier
* @internal_flags: flags used by the family
* @flags: flags
* @maxattr: maximum number of attributes supported
* @policy: netlink policy (takes precedence over family policy)
* @doit: standard command callback
* @start: start callback for dumps
* @dumpit: callback for dumpers
Expand All @@ -142,12 +151,32 @@ struct genl_ops {
int (*dumpit)(struct sk_buff *skb,
struct netlink_callback *cb);
int (*done)(struct netlink_callback *cb);
const struct nla_policy *policy;
unsigned int maxattr;
u8 cmd;
u8 internal_flags;
u8 flags;
u8 validate;
};

/**
* struct genl_info - info that is available during dumpit op call
* @family: generic netlink family - for internal genl code usage
* @ops: generic netlink ops - for internal genl code usage
* @attrs: netlink attributes
*/
struct genl_dumpit_info {
const struct genl_family *family;
struct genl_ops op;
struct nlattr **attrs;
};

static inline const struct genl_dumpit_info *
genl_dumpit_info(struct netlink_callback *cb)
{
return cb->data;
}

int genl_register_family(struct genl_family *family);
int genl_unregister_family(const struct genl_family *family);
void genl_notify(const struct genl_family *family, struct sk_buff *skb,
Expand Down
11 changes: 7 additions & 4 deletions include/net/netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -1935,11 +1935,14 @@ void nla_get_range_unsigned(const struct nla_policy *pt,
void nla_get_range_signed(const struct nla_policy *pt,
struct netlink_range_validation_signed *range);

struct netlink_policy_dump_state;

int netlink_policy_dump_start(const struct nla_policy *policy,
unsigned int maxtype,
unsigned long *state);
bool netlink_policy_dump_loop(unsigned long state);
int netlink_policy_dump_write(struct sk_buff *skb, unsigned long state);
void netlink_policy_dump_free(unsigned long state);
struct netlink_policy_dump_state **state);
bool netlink_policy_dump_loop(struct netlink_policy_dump_state *state);
int netlink_policy_dump_write(struct sk_buff *skb,
struct netlink_policy_dump_state *state);
void netlink_policy_dump_free(struct netlink_policy_dump_state *state);

#endif
40 changes: 7 additions & 33 deletions kernel/taskstats.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,13 @@ struct kmem_cache *taskstats_cache;

static struct genl_family family;

static const struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] = {
static const struct nla_policy taskstats_cmd_get_policy[] = {
[TASKSTATS_CMD_ATTR_PID] = { .type = NLA_U32 },
[TASKSTATS_CMD_ATTR_TGID] = { .type = NLA_U32 },
[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING },
[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },};

/*
* We have to use TASKSTATS_CMD_ATTR_MAX here, it is the maxattr in the family.
* Make sure they are always aligned.
*/
static const struct nla_policy cgroupstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] = {
static const struct nla_policy cgroupstats_cmd_get_policy[] = {
[CGROUPSTATS_CMD_ATTR_FD] = { .type = NLA_U32 },
};

Expand Down Expand Up @@ -649,47 +645,25 @@ static const struct genl_ops taskstats_ops[] = {
.cmd = TASKSTATS_CMD_GET,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = taskstats_user_cmd,
/* policy enforced later */
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_HASPOL,
.policy = taskstats_cmd_get_policy,
.maxattr = ARRAY_SIZE(taskstats_cmd_get_policy) - 1,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = CGROUPSTATS_CMD_GET,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = cgroupstats_user_cmd,
/* policy enforced later */
.flags = GENL_CMD_CAP_HASPOL,
.policy = cgroupstats_cmd_get_policy,
.maxattr = ARRAY_SIZE(cgroupstats_cmd_get_policy) - 1,
},
};

static int taskstats_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info)
{
const struct nla_policy *policy = NULL;

switch (ops->cmd) {
case TASKSTATS_CMD_GET:
policy = taskstats_cmd_get_policy;
break;
case CGROUPSTATS_CMD_GET:
policy = cgroupstats_cmd_get_policy;
break;
default:
return -EINVAL;
}

return nlmsg_validate_deprecated(info->nlhdr, GENL_HDRLEN,
TASKSTATS_CMD_ATTR_MAX, policy,
info->extack);
}

static struct genl_family family __ro_after_init = {
.name = TASKSTATS_GENL_NAME,
.version = TASKSTATS_GENL_VERSION,
.maxattr = TASKSTATS_CMD_ATTR_MAX,
.module = THIS_MODULE,
.ops = taskstats_ops,
.n_ops = ARRAY_SIZE(taskstats_ops),
.pre_doit = taskstats_pre_doit,
};

/* Needed early in initialization */
Expand Down
Loading

0 comments on commit 678cdd4

Please sign in to comment.