From e2c779b3c277c085fc0e1a3f5b00f0119430af74 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 12 Jan 2011 13:05:35 -0800 Subject: [PATCH] datapath: Backport genl_register_family_with_ops(). Besides the user introduced in this commit, the new Netlink-based datapath communication code will use this function. Signed-off-by: Ben Pfaff Acked-by: Jesse Gross Reported-by: Justin Pettit --- datapath/brcompat.c | 53 +++++++------------ datapath/linux-2.6/compat-2.6/genetlink.inc | 47 ++++++++++++++++ .../compat-2.6/include/net/genetlink.h | 5 ++ 3 files changed, 70 insertions(+), 35 deletions(-) diff --git a/datapath/brcompat.c b/datapath/brcompat.c index 43cbfb0d9..3e91dc5d4 100644 --- a/datapath/brcompat.c +++ b/datapath/brcompat.c @@ -396,14 +396,6 @@ nla_put_failure: return err; } -static struct genl_ops brc_genl_ops_query_dp = { - .cmd = BRC_GENL_C_QUERY_MC, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */ - .policy = NULL, - .doit = brc_genl_query, - .dumpit = NULL -}; - /* Attribute policy: what each attribute may contain. */ static struct nla_policy brc_genl_policy[BRC_GENL_A_MAX + 1] = { [BRC_GENL_A_ERR_CODE] = { .type = NLA_U32 }, @@ -449,20 +441,22 @@ static int brc_genl_dp_result(struct sk_buff *skb, struct genl_info *info) return err; } -static struct genl_ops brc_genl_ops_dp_result = { - .cmd = BRC_GENL_C_DP_RESULT, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */ - .policy = brc_genl_policy, - .doit = brc_genl_dp_result, - .dumpit = NULL -}; - -static struct genl_ops brc_genl_ops_set_proc = { - .cmd = BRC_GENL_C_SET_PROC, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */ - .policy = brc_genl_policy, - .doit = brc_genl_set_proc, - .dumpit = NULL +static struct genl_ops brc_genl_ops[] = { + { .cmd = BRC_GENL_C_QUERY_MC, + .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */ + .policy = NULL, + .doit = brc_genl_query, + }, + { .cmd = BRC_GENL_C_DP_RESULT, + .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */ + .policy = brc_genl_policy, + .doit = brc_genl_dp_result, + }, + { .cmd = BRC_GENL_C_SET_PROC, + .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */ + .policy = brc_genl_policy, + .doit = brc_genl_set_proc, + }, }; static struct sk_buff *brc_send_command(struct sk_buff *request, @@ -535,22 +529,11 @@ static int __init brc_init(void) /* Register generic netlink family to communicate changes to * userspace. */ - err = genl_register_family(&brc_genl_family); + err = genl_register_family_with_ops(&brc_genl_family, + brc_genl_ops, ARRAY_SIZE(brc_genl_ops)); if (err) goto error; - err = genl_register_ops(&brc_genl_family, &brc_genl_ops_query_dp); - if (err != 0) - goto err_unregister; - - err = genl_register_ops(&brc_genl_family, &brc_genl_ops_dp_result); - if (err != 0) - goto err_unregister; - - err = genl_register_ops(&brc_genl_family, &brc_genl_ops_set_proc); - if (err != 0) - goto err_unregister; - strcpy(brc_mc_group.name, "brcompat"); err = genl_register_mc_group(&brc_genl_family, &brc_mc_group); if (err < 0) diff --git a/datapath/linux-2.6/compat-2.6/genetlink.inc b/datapath/linux-2.6/compat-2.6/genetlink.inc index e6ebe2ff5..63760bbb9 100644 --- a/datapath/linux-2.6/compat-2.6/genetlink.inc +++ b/datapath/linux-2.6/compat-2.6/genetlink.inc @@ -24,3 +24,50 @@ int genl_register_mc_group(struct genl_family *family, return 0; } #endif /* kernel < 2.6.23 */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) +/** + * genl_register_family_with_ops - register a generic netlink family + * @family: generic netlink family + * @ops: operations to be registered + * @n_ops: number of elements to register + * + * Registers the specified family and operations from the specified table. + * Only one family may be registered with the same family name or identifier. + * + * The family id may equal GENL_ID_GENERATE causing an unique id to + * be automatically generated and assigned. + * + * Either a doit or dumpit callback must be specified for every registered + * operation or the function will fail. Only one operation structure per + * command identifier may be registered. + * + * See include/net/genetlink.h for more documenation on the operations + * structure. + * + * This is equivalent to calling genl_register_family() followed by + * genl_register_ops() for every operation entry in the table taking + * care to unregister the family on error path. + * + * Return 0 on success or a negative error code. + */ +int genl_register_family_with_ops(struct genl_family *family, + struct genl_ops *ops, size_t n_ops) +{ + int err, i; + + err = genl_register_family(family); + if (err) + return err; + + for (i = 0; i < n_ops; ++i, ++ops) { + err = genl_register_ops(family, ops); + if (err) + goto err_out; + } + return 0; +err_out: + genl_unregister_family(family); + return err; +} +#endif diff --git a/datapath/linux-2.6/compat-2.6/include/net/genetlink.h b/datapath/linux-2.6/compat-2.6/include/net/genetlink.h index 038fd464b..06a14c817 100644 --- a/datapath/linux-2.6/compat-2.6/include/net/genetlink.h +++ b/datapath/linux-2.6/compat-2.6/include/net/genetlink.h @@ -114,4 +114,9 @@ static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags) } #endif /* linux kernel < 2.6.20 */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) +int genl_register_family_with_ops(struct genl_family *family, + struct genl_ops *ops, size_t n_ops); +#endif + #endif /* genetlink.h */ -- 2.45.2