From 4d394347340da48f7876be0dffae8955ec1f9392 Mon Sep 17 00:00:00 2001 From: Pratyush Kumar Khan Date: Wed, 1 Mar 2023 21:14:52 +0530 Subject: [PATCH] kParser: Multi-namespace support Add multi-namespace support to kParser Fixes: 2f909f2d49cc Signed-off-by: Pratyush Kumar Khan --- include/net/kparser.h | 83 ++++++- include/net/net_namespace.h | 4 + include/uapi/linux/kparser.h | 2 + net/kparser/kparser.h | 44 +++- net/kparser/kparser_cmds.c | 319 ++++++++++++++++++++++++-- net/kparser/kparser_cmds_ops.c | 132 ++++++----- net/kparser/kparser_datapath.c | 407 ++++++++++++++++++++++++++++++++- net/kparser/kparser_main.c | 53 +++-- 8 files changed, 927 insertions(+), 117 deletions(-) diff --git a/include/net/kparser.h b/include/net/kparser.h index 89575a5194..d2087603f5 100644 --- a/include/net/kparser.h +++ b/include/net/kparser.h @@ -32,6 +32,8 @@ * data path. * * return: kParser error code as defined in include/uapi/linux/kparser.h + * NOTE: This API supports multiple networking namespaces by using the skb's + * "struct net" member. */ extern int kparser_parse(struct sk_buff *skb, const struct kparser_hkey *kparser_key, @@ -96,12 +98,91 @@ extern const void *kparser_get_parser(const struct kparser_hkey *kparser_key, */ extern bool kparser_put_parser(const void *parser, bool avoid_ref); +/* __kparser_parse_ns(): Function to parse a void * packet buffer using a parser instance key + * + * The only difference between __kparser_parse_ns() and __kparser_parse() is, + * __kparser_parse_ns() supports multiple namespaces if "struct net" parameter + * is provided. If not, then there is no difference between these two APIs. + * + * net: the net structure from which namespace can be obtained using kernel API + * get_net(). If passed NULL, then no namespace will be used. + * parser: Non NULL kparser_get_parser() returned and cached opaque pointer + * referencing a valid parser instance. + * _hdr: input packet buffer + * parse_len: length of input packet buffer + * _metadata: User provided metadata buffer. It must be same as configured + * metadata objects in CLI. + * metadata_len: Total length of the user provided metadata buffer. + * + * return: kParser error code as defined in include/uapi/linux/kparser.h + */ +extern int __kparser_parse_ns(struct net *net, const void *parser, void *_hdr, + size_t parse_len, void *_metadata, size_t metadata_len); + +/* kparser_get_parser_ns(): Function to get an opaque reference of a parser instance and mark it + * immutable so that while actively using, it can not be deleted. The parser is identified by a key. + * It marks the associated parser and whole parse tree immutable so that when it is locked, it can + * not be deleted. + * + * The only difference between kparser_get_parser_ns() and kparser_get_parser() is, + * kparser_get_parser_ns() supports multiple namespaces if "struct net" parameter + * is provided. If not, then there is no difference between these two APIs. + * + * net: the net structure from which namespace can be obtained using kernel API + * get_net(). If passed NULL, then no namespace will be used. + * kparser_key: key of the associated kParser parser object which must be + * already created via CLI. + * avoid_ref: Set this flag in case caller wants to avoid holding the reference + * of the active parser object to save performance on the data path. + * But please be advised, caller should hold the reference of the + * parser object while using this data path. In this case, the CLI + * can be used in advance to get the reference, and caller will also + * need to release the reference via CLI once it is done with the + * data path. + * + * return: NULL if key not found, else an opaque parser instance pointer which + * can be used in the following APIs 3 and 4. + * + * NOTE: This call makes the whole parser tree immutable. If caller calls this + * more than once, later caller will need to release the same parser exactly that + * many times using the API kparser_put_parser(). + */ +extern const void *kparser_get_parser_ns(struct net *net, + const struct kparser_hkey *kparser_key, + bool avoid_ref); + +/* kparser_put_parser_ns(): Function to return and undo the read only operation done previously by + * kparser_get_parser(). The parser instance is identified by using a previously obtained opaque + * parser pointer via API kparser_get_parser(). This undo the immutable change so that any component + * of the whole parse tree can be deleted again. + * + * The only difference between kparser_put_parser_ns() and kparser_put_parser() is, + * kparser_put_parser_ns() supports multiple namespaces if "struct net" parameter + * is provided. If not, then there is no difference between these two APIs. + * + * net: the net structure from which namespace can be obtained using kernel API + * get_net(). If passed NULL, then no namespace will be used. + * parser: void *, Non NULL opaque pointer which was previously returned by kparser_get_parser(). + * Caller can use cached opaque pointer as long as system does not restart and kparser.ko is not + * reloaded. + * avoid_ref: Set this flag only when this was used in the prio call to + * kparser_get_parser(). Incorrect usage of this flag might cause + * error and make the parser state unstable. + * + * return: boolean, true if put operation is success, else false. + * + * NOTE: This call makes the whole parser tree deletable for the very last call. + */ +extern bool kparser_put_parser_ns(struct net *net, + const void *parser, bool avoid_ref); + /* net/core/filter.c's callback hook structure to use kParser APIs if kParser enabled */ struct get_kparser_funchooks { const void * (*kparser_get_parser_hook)(const struct kparser_hkey *kparser_key, bool avoid_ref); int (*__kparser_parse_hook)(const void *parser, void *_hdr, - size_t parse_len, void *_metadata, size_t metadata_len); + size_t parse_len, void *_metadata, + size_t metadata_len); bool (*kparser_put_parser_hook)(const void *parser, bool avoid_ref); }; diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 78beaa765c..3545c11710 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -188,6 +188,10 @@ struct net { #if IS_ENABLED(CONFIG_SMC) struct netns_smc smc; #endif + +#if IS_ENABLED(CONFIG_KPARSER) + void *kparser_ns; +#endif } __randomize_layout; #include diff --git a/include/uapi/linux/kparser.h b/include/uapi/linux/kparser.h index dad9621eef..ac2b40dc1f 100644 --- a/include/uapi/linux/kparser.h +++ b/include/uapi/linux/kparser.h @@ -205,6 +205,8 @@ struct kparser_conf_metadata { size_t add_off; struct kparser_hkey counterkey; struct kparser_hkey counter_data_key; + __u8 right_shift; + __u32 mask; }; /* *********************** metadata list/table *********************** */ diff --git a/net/kparser/kparser.h b/net/kparser/kparser.h index 836780e6aa..6ced4f64b5 100644 --- a/net/kparser/kparser.h +++ b/net/kparser/kparser.h @@ -277,19 +277,23 @@ static inline __u32 kparser_generic_obj_hashfn_id(const void *obj, __u32 key_len /* internal shared functions */ int kparser_init(void); int kparser_deinit(void); -int kparser_config_handler_add(const void *cmdarg, size_t cmdarglen, +int kparser_config_handler_add(void *netns, + const void *cmdarg, size_t cmdarglen, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, void *extack, int *err); -int kparser_config_handler_update(const void *cmdarg, size_t cmdarglen, +int kparser_config_handler_update(void *netns, + const void *cmdarg, size_t cmdarglen, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, void *extack, int *err); -int kparser_config_handler_read(const void *cmdarg, size_t cmdarglen, +int kparser_config_handler_read(void *netns, + const void *cmdarg, size_t cmdarglen, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, void *extack, int *err); -int kparser_config_handler_delete(const void *cmdarg, size_t cmdarglen, +int kparser_config_handler_delete(void *netns, + const void *cmdarg, size_t cmdarglen, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, void *extack, int *err); @@ -312,16 +316,17 @@ int kparser_namespace_insert(enum kparser_global_namespace_ids ns_id, struct rhash_head *obj_name); /* Generic kParser KMOD's netlink msg handler's definitions for create */ -typedef int kparser_obj_create_update(const struct kparser_conf_cmd *conf, +typedef int kparser_obj_create_update(void *netns, + const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, void *extack, int *err); /* Generic kParser KMOD's netlink msg handler's definitions for read and delete */ -typedef int kparser_obj_read_del(const struct kparser_hkey *key, - struct kparser_cmd_rsp_hdr **rsp, - size_t *rsp_len, __u8 recursive_read, - const char *op, void *extack, int *err); +typedef int kparser_obj_read_del(void *netns, const struct kparser_hkey *key, + struct kparser_cmd_rsp_hdr **rsp, + size_t *rsp_len, __u8 recursive_read, + const char *op, void *extack, int *err); /* Generic kParser KMOD's netlink msg handler's free callbacks */ typedef void kparser_free_obj(void *ptr, void *arg); int kparser_link_attach(const void *owner_obj, @@ -415,4 +420,25 @@ do { \ } \ while (0) +/* kParser KMOD's namespace definitions */ +struct kparser_mod_namespaces { + enum kparser_global_namespace_ids namespace_id; + const char *name; + struct kparser_htbl htbl_name; + struct kparser_htbl htbl_id; + kparser_obj_create_update *create_handler; + kparser_obj_create_update *update_handler; + kparser_obj_read_del *read_handler; + kparser_obj_read_del *del_handler; + kparser_free_obj *free_handler; + size_t bv_len; + unsigned long *bv; +}; + +struct kparser_ns_ds_ctx { + struct kparser_mod_namespaces **kparser_ns_ctx; +}; + +struct kparser_ns_ds_ctx * kparser_alloc_global_ns_ctx(void); + #endif /* __KPARSER_H */ diff --git a/net/kparser/kparser_cmds.c b/net/kparser/kparser_cmds.c index f1daeedb2a..f2d63e50a2 100644 --- a/net/kparser/kparser_cmds.c +++ b/net/kparser/kparser_cmds.c @@ -257,21 +257,6 @@ int kparser_link_detach(const void *obj, return 0; } -/* kParser KMOD's namespace definitions */ -struct kparser_mod_namespaces { - enum kparser_global_namespace_ids namespace_id; - const char *name; - struct kparser_htbl htbl_name; - struct kparser_htbl htbl_id; - kparser_obj_create_update *create_handler; - kparser_obj_create_update *update_handler; - kparser_obj_read_del *read_handler; - kparser_obj_read_del *del_handler; - kparser_free_obj *free_handler; - size_t bv_len; - unsigned long *bv; -}; - /* Statically define kParser KMOD's namespaces with all the parameters */ #define KPARSER_DEFINE_MOD_NAMESPACE(g_ns_obj, NSID, OBJ_NAME, FIELD, CREATE, \ READ, UPDATE, DELETE, FREE) \ @@ -490,6 +475,282 @@ static struct kparser_mod_namespaces *g_mod_namespaces[] = { [KPARSER_NS_MAX] = NULL, }; +/* runtime define kParser KMOD's namespaces with all the parameters */ +#define KPARSER_DEFINE_NS_MOD_NAMESPACE(ns_namespaces, ns_obj, NSID, OBJ_NAME, \ + FIELD, CREATE, READ, UPDATE, DELETE, \ + FREE) \ +do{ \ + ns_obj = kzalloc(sizeof(*ns_obj), GFP_KERNEL); \ + if (!ns_obj) { \ + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, \ + ":kzalloc failed for size:%lu\n", \ + sizeof(*ns_obj)); \ + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, "OUT: "); \ + return NULL; \ + } \ + ns_namespaces[NSID] = ns_obj; \ + ns_obj->namespace_id = NSID; \ + ns_obj->name = #NSID; \ + ns_obj->htbl_name.tbl_params.head_offset = offsetof(struct OBJ_NAME, \ + FIELD.ht_node_name);\ + ns_obj->htbl_name.tbl_params.key_offset = offsetof(struct OBJ_NAME, \ + FIELD.key.name); \ + ns_obj->htbl_name.tbl_params.key_len = sizeof(((struct kparser_hkey \ + *)0)->name); \ + ns_obj->htbl_name.tbl_params.automatic_shrinking = true; \ + ns_obj->htbl_name.tbl_params.hashfn = kparser_generic_hash_fn_name; \ + ns_obj->htbl_name.tbl_params.obj_hashfn = \ + kparser_generic_obj_hashfn_name; \ + ns_obj->htbl_name.tbl_params.obj_cmpfn = kparser_cmp_fn_name; \ + \ + ns_obj->htbl_id.tbl_params.head_offset = offsetof(struct OBJ_NAME, \ + FIELD.ht_node_id); \ + ns_obj->htbl_id.tbl_params.key_offset = offsetof(struct OBJ_NAME, \ + FIELD.key.id); \ + ns_obj->htbl_id.tbl_params.key_len = sizeof(((struct kparser_hkey \ + *)0)->id); \ + ns_obj->htbl_id.tbl_params.automatic_shrinking = true; \ + ns_obj->htbl_id.tbl_params.hashfn = kparser_generic_hash_fn_id; \ + ns_obj->htbl_id.tbl_params.obj_hashfn = \ + kparser_generic_obj_hashfn_id; \ + ns_obj->htbl_id.tbl_params.obj_cmpfn = kparser_cmp_fn_id; \ + ns_obj->create_handler = CREATE; \ + ns_obj->read_handler = READ; \ + ns_obj->update_handler = UPDATE; \ + ns_obj->del_handler = DELETE; \ + ns_obj->free_handler = FREE; \ +} while(0) + +struct kparser_ns_ds_ctx * kparser_alloc_global_ns_ctx(void) +{ + struct kparser_mod_namespaces **kparser_ns_namespaces; + struct kparser_mod_namespaces *kparser_ns_obj; + struct kparser_ns_ds_ctx *ctx_ret; + int i, err; + + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, "IN: "); + + ctx_ret = kzalloc(sizeof(*ctx_ret), GFP_KERNEL); + if (!ctx_ret) { + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, + ":kzalloc failed for ctx_ret"); + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, "OUT: "); + return NULL; + } + + kparser_ns_namespaces = kzalloc(sizeof(struct kparser_mod_namespaces *) + * + (KPARSER_NS_MAX - KPARSER_NS_INVALID + 1), + GFP_KERNEL); + if (!kparser_ns_namespaces) { + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, + ":kzalloc failed for" + " kparser_ns_namespaces"); + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, "OUT: "); + return NULL; + } + + ctx_ret->kparser_ns_ctx = kparser_ns_namespaces; + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_CONDEXPRS, + kparser_glue_condexpr_expr, + glue, + kparser_create_cond_exprs, + kparser_read_cond_exprs, + NULL, NULL, NULL); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_CONDEXPRS_TABLE, + kparser_glue_condexpr_table, + glue, + kparser_create_cond_table, + kparser_read_cond_table, + NULL, NULL, NULL); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_CONDEXPRS_TABLES, + kparser_glue_condexpr_tables, + glue, + kparser_create_cond_tables, + kparser_read_cond_tables, + NULL, NULL, NULL); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_COUNTER, + kparser_glue_counter, + glue, + kparser_create_counter, + kparser_read_counter, + NULL, NULL, NULL); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_COUNTER_TABLE, + kparser_glue_counter_table, + glue, + kparser_create_counter_table, + kparser_read_counter_table, + NULL, NULL, NULL); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_METADATA, + kparser_glue_metadata_extract, + glue, + kparser_create_metadata, + kparser_read_metadata, + NULL, + kparser_del_metadata, + kparser_free_metadata); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_METALIST, + kparser_glue_metadata_table, + glue, + kparser_create_metalist, + kparser_read_metalist, + NULL, + kparser_del_metalist, + kparser_free_metalist); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_NODE_PARSE, + kparser_glue_glue_parse_node, + glue.glue, + kparser_create_parse_node, + kparser_read_parse_node, + NULL, + kparser_del_parse_node, + kparser_free_node); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_PROTO_TABLE, + kparser_glue_protocol_table, + glue, + kparser_create_proto_table, + kparser_read_proto_table, + NULL, + kparser_del_proto_table, + kparser_free_proto_tbl); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_TLV_NODE_PARSE, + kparser_glue_parse_tlv_node, + glue.glue, + kparser_create_parse_tlv_node, + kparser_read_parse_tlv_node, + NULL, NULL, NULL); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_TLV_PROTO_TABLE, + kparser_glue_proto_tlvs_table, + glue, + kparser_create_tlv_proto_table, + kparser_read_tlv_proto_table, + NULL, NULL, NULL); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_FLAG_FIELD, + kparser_glue_flag_field, + glue, + kparser_create_flag_field, + kparser_read_flag_field, + NULL, NULL, NULL); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_FLAG_FIELD_TABLE, + kparser_glue_flag_fields, + glue, + kparser_create_flag_field_table, + kparser_read_flag_field_table, + NULL, NULL, NULL); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_FLAG_FIELD_NODE_PARSE, + kparser_glue_flag_field_node, + glue.glue, + kparser_create_parse_flag_field_node, + kparser_read_parse_flag_field_node, + NULL, NULL, NULL); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_FLAG_FIELD_PROTO_TABLE, + kparser_glue_proto_flag_fields_table, + glue, + kparser_create_flag_field_proto_table, + kparser_read_flag_field_proto_table, + NULL, NULL, NULL); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_PARSER, + kparser_glue_parser, + glue, + kparser_create_parser, + kparser_read_parser, + NULL, + kparser_del_parser, + kparser_free_parser); + + KPARSER_DEFINE_NS_MOD_NAMESPACE(kparser_ns_namespaces, kparser_ns_obj, + KPARSER_NS_OP_PARSER_LOCK_UNLOCK, + kparser_glue_parser, + glue, + kparser_parser_lock, + NULL, NULL, + kparser_parser_unlock, + NULL); + + for (i = 0; i < (sizeof(g_mod_namespaces) / + sizeof(g_mod_namespaces[0])); i++) { + if (!kparser_ns_namespaces[i]) + continue; + + err = rhashtable_init(&kparser_ns_namespaces[i]->htbl_name.tbl, + &kparser_ns_namespaces[i]->htbl_name.tbl_params); + if (err) { + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, + "rhashtable_init() failed"); + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, "OUT: "); + return NULL; + } + + err = rhashtable_init(&kparser_ns_namespaces[i]->htbl_id.tbl, + &kparser_ns_namespaces[i]->htbl_id.tbl_params); + if (err) { + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, + "rhashtable_init() failed"); + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, "OUT: "); + return NULL; + } + + kparser_ns_namespaces[i]->bv_len = + ((KPARSER_KMOD_ID_MAX - KPARSER_KMOD_ID_MIN) / + BITS_PER_TYPE(unsigned long)) + 1; + + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, + "bv_len:%lu, total_bytes:%lu, range:[%d:%d]\n", + kparser_ns_namespaces[i]->bv_len, + sizeof(unsigned long) * + kparser_ns_namespaces[i]->bv_len, + KPARSER_KMOD_ID_MAX, KPARSER_KMOD_ID_MIN); + + kparser_ns_namespaces[i]->bv = kcalloc(kparser_ns_namespaces[i]->bv_len, + sizeof(unsigned long), + GFP_KERNEL); + + if (!kparser_ns_namespaces[i]->bv) { + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, "kzalloc() failed"); + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, "OUT: "); + return NULL; + } + + memset(kparser_ns_namespaces[i]->bv, 0xff, + kparser_ns_namespaces[i]->bv_len * sizeof(unsigned long)); + } + + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, "OUT: "); + return ctx_ret; +} + /* Function to allocate autogen IDs for hash keys if user did not allocate themselves * TODO: free ids */ @@ -834,7 +1095,8 @@ do { \ while (0) /* netlink msg processors for create */ -int kparser_config_handler_add(const void *cmdarg, size_t cmdarglen, +int kparser_config_handler_add(void *netns, + const void *cmdarg, size_t cmdarglen, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, void *extack, int *err) @@ -849,7 +1111,7 @@ int kparser_config_handler_add(const void *cmdarg, size_t cmdarglen, if (!g_mod_namespaces[conf->namespace_id]->create_handler) return KPARSER_ATTR_UNSPEC; - return g_mod_namespaces[conf->namespace_id]->create_handler(conf, cmdarglen, + return g_mod_namespaces[conf->namespace_id]->create_handler(netns, conf, cmdarglen, rsp, rsp_len, "create", @@ -857,7 +1119,8 @@ int kparser_config_handler_add(const void *cmdarg, size_t cmdarglen, } /* netlink msg processors for update */ -int kparser_config_handler_update(const void *cmdarg, size_t cmdarglen, +int kparser_config_handler_update(void *netns, + const void *cmdarg, size_t cmdarglen, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, void *extack, int *err) { @@ -871,7 +1134,7 @@ int kparser_config_handler_update(const void *cmdarg, size_t cmdarglen, if (!g_mod_namespaces[conf->namespace_id]->update_handler) return KPARSER_ATTR_UNSPEC; - return g_mod_namespaces[conf->namespace_id]->update_handler(conf, cmdarglen, + return g_mod_namespaces[conf->namespace_id]->update_handler(netns, conf, cmdarglen, rsp, rsp_len, "update", @@ -879,7 +1142,8 @@ int kparser_config_handler_update(const void *cmdarg, size_t cmdarglen, } /* netlink msg processors for read */ -int kparser_config_handler_read(const void *cmdarg, size_t cmdarglen, +int kparser_config_handler_read(void *netns, + const void *cmdarg, size_t cmdarglen, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, void *extack, int *err) { @@ -893,12 +1157,15 @@ int kparser_config_handler_read(const void *cmdarg, size_t cmdarglen, if (!g_mod_namespaces[conf->namespace_id]->read_handler) return KPARSER_ATTR_UNSPEC; - return g_mod_namespaces[conf->namespace_id]->read_handler(&conf->obj_key, rsp, rsp_len, - conf->recursive_read_delete, "read", extack, err); + return g_mod_namespaces[conf->namespace_id]->read_handler(netns, + &conf->obj_key, rsp, rsp_len, + conf->recursive_read_delete, + "read", extack, err); } /* netlink msg processors for delete */ -int kparser_config_handler_delete(const void *cmdarg, size_t cmdarglen, +int kparser_config_handler_delete(void *netns, + const void *cmdarg, size_t cmdarglen, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, void *extack, int *err) { @@ -912,6 +1179,8 @@ int kparser_config_handler_delete(const void *cmdarg, size_t cmdarglen, if (!g_mod_namespaces[conf->namespace_id]->del_handler) return KPARSER_ATTR_UNSPEC; - return g_mod_namespaces[conf->namespace_id]->del_handler(&conf->obj_key, rsp, rsp_len, - conf->recursive_read_delete, "delete", extack, err); + return g_mod_namespaces[conf->namespace_id]->del_handler(netns, + &conf->obj_key, rsp, rsp_len, + conf->recursive_read_delete, + "delete", extack, err); } diff --git a/net/kparser/kparser_cmds_ops.c b/net/kparser/kparser_cmds_ops.c index b642a8d14e..3f8fbf31e4 100644 --- a/net/kparser/kparser_cmds_ops.c +++ b/net/kparser/kparser_cmds_ops.c @@ -27,7 +27,7 @@ void *kparser_fast_lookup_array[KPARSER_PARSER_FAST_LOOKUP_RSVD_ID_STOP - /* common pre-process code for create handlers */ static inline bool -kparser_cmd_create_pre_process(const char *op, +kparser_cmd_create_pre_process(void *netns, const char *op, const struct kparser_conf_cmd *conf, const struct kparser_hkey *argkey, struct kparser_hkey *newkey, void **kobj, size_t kobjsize, struct kparser_cmd_rsp_hdr *rsp, @@ -90,7 +90,8 @@ kparser_cmd_create_pre_process(const char *op, * NOTE: All handlers startting from here must hold mutex kparser_config_lock * before any work can be done and must release that mutex before return. */ -int kparser_create_cond_exprs(const struct kparser_conf_cmd *conf, +int kparser_create_cond_exprs(void *netns, + const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -106,7 +107,8 @@ int kparser_create_cond_exprs(const struct kparser_conf_cmd *conf, arg = &conf->cond_conf; - if (!kparser_cmd_create_pre_process(op, conf, &arg->key, &key, + if (!kparser_cmd_create_pre_process(netns, + op, conf, &arg->key, &key, (void **)&kobj, sizeof(*kobj), *rsp, offsetof(struct kparser_glue_condexpr_expr, @@ -131,7 +133,7 @@ int kparser_create_cond_exprs(const struct kparser_conf_cmd *conf, } /* read handler for object conditionals */ -int kparser_read_cond_exprs(const struct kparser_hkey *key, +int kparser_read_cond_exprs(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -167,7 +169,7 @@ int kparser_read_cond_exprs(const struct kparser_hkey *key, } /* create handler for object conditionals table entry */ -static bool kparser_create_cond_table_ent(const struct kparser_conf_table *arg, +static bool kparser_create_cond_table_ent(void *netns, const struct kparser_conf_table *arg, struct kparser_glue_condexpr_table **proto_table, struct kparser_cmd_rsp_hdr *rsp, const char *op, @@ -221,7 +223,7 @@ static bool kparser_create_cond_table_ent(const struct kparser_conf_table *arg, } /* create handler for object conditionals table */ -int kparser_create_cond_table(const struct kparser_conf_cmd *conf, +int kparser_create_cond_table(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -239,13 +241,14 @@ int kparser_create_cond_table(const struct kparser_conf_cmd *conf, /* create a table entry */ if (arg->add_entry) { - if (kparser_create_cond_table_ent(arg, &proto_table, *rsp, op, + if (kparser_create_cond_table_ent(netns, arg, &proto_table, *rsp, op, extack, err) == false) goto done; goto skip_table_create; } - if (!kparser_cmd_create_pre_process(op, conf, &arg->key, &key, + if (!kparser_cmd_create_pre_process(netns, + op, conf, &arg->key, &key, (void **)&proto_table, sizeof(*proto_table), *rsp, offsetof(struct kparser_glue_condexpr_table, @@ -279,7 +282,7 @@ int kparser_create_cond_table(const struct kparser_conf_cmd *conf, } /* read handler for object conditionals table */ -int kparser_read_cond_table(const struct kparser_hkey *key, +int kparser_read_cond_table(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -344,7 +347,7 @@ int kparser_read_cond_table(const struct kparser_hkey *key, } /* create handler for object conditionals table's list entry */ -static bool kparser_create_cond_tables_ent(const struct kparser_conf_table *arg, +static bool kparser_create_cond_tables_ent(void *netns, const struct kparser_conf_table *arg, struct kparser_glue_condexpr_tables **proto_table, struct kparser_cmd_rsp_hdr *rsp, const char *op, @@ -396,7 +399,7 @@ static bool kparser_create_cond_tables_ent(const struct kparser_conf_table *arg, } /* create handler for object conditionals table's list */ -int kparser_create_cond_tables(const struct kparser_conf_cmd *conf, +int kparser_create_cond_tables(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -414,13 +417,14 @@ int kparser_create_cond_tables(const struct kparser_conf_cmd *conf, /* create a table entry */ if (arg->add_entry) { - if (kparser_create_cond_tables_ent(arg, &proto_table, *rsp, op, + if (kparser_create_cond_tables_ent(netns, arg, &proto_table, *rsp, op, extack, err) == false) goto done; goto skip_table_create; } - if (!kparser_cmd_create_pre_process(op, conf, &arg->key, &key, + if (!kparser_cmd_create_pre_process(netns, + op, conf, &arg->key, &key, (void **)&proto_table, sizeof(*proto_table), *rsp, offsetof(struct kparser_glue_condexpr_tables, @@ -452,7 +456,7 @@ int kparser_create_cond_tables(const struct kparser_conf_cmd *conf, } /* read handler for object conditionals table's list */ -int kparser_read_cond_tables(const struct kparser_hkey *key, +int kparser_read_cond_tables(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -516,7 +520,7 @@ int kparser_read_cond_tables(const struct kparser_hkey *key, } /* create handler for object counter */ -int kparser_create_counter(const struct kparser_conf_cmd *conf, +int kparser_create_counter(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -616,7 +620,7 @@ int kparser_create_counter(const struct kparser_conf_cmd *conf, } /* read handler for object counter */ -int kparser_read_counter(const struct kparser_hkey *key, +int kparser_read_counter(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -651,7 +655,7 @@ int kparser_read_counter(const struct kparser_hkey *key, } /* create handler for object counter table */ -int kparser_create_counter_table(const struct kparser_conf_cmd *conf, +int kparser_create_counter_table(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -763,7 +767,7 @@ int kparser_create_counter_table(const struct kparser_conf_cmd *conf, } /* read handler for object counter table */ -int kparser_read_counter_table(const struct kparser_hkey *key, +int kparser_read_counter_table(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -822,7 +826,7 @@ int kparser_read_counter_table(const struct kparser_hkey *key, } /* create handler for object metadata */ -int kparser_create_metadata(const struct kparser_conf_cmd *conf, +int kparser_create_metadata(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -935,7 +939,7 @@ int kparser_create_metadata(const struct kparser_conf_cmd *conf, } /* read handler for object metadata */ -int kparser_read_metadata(const struct kparser_hkey *key, +int kparser_read_metadata(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -971,7 +975,7 @@ int kparser_read_metadata(const struct kparser_hkey *key, } /* delete handler for object metadata */ -int kparser_del_metadata(const struct kparser_hkey *key, +int kparser_del_metadata(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -1034,7 +1038,7 @@ void kparser_free_metadata(void *ptr, void *arg) } /* create handler for object metadata list */ -int kparser_create_metalist(const struct kparser_conf_cmd *conf, +int kparser_create_metalist(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -1205,7 +1209,7 @@ int kparser_create_metalist(const struct kparser_conf_cmd *conf, } /* read handler for object metadata list */ -int kparser_read_metalist(const struct kparser_hkey *key, +int kparser_read_metalist(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -1265,7 +1269,7 @@ int kparser_read_metalist(const struct kparser_hkey *key, } /* delete handler for object metadata list */ -int kparser_del_metalist(const struct kparser_hkey *key, +int kparser_del_metalist(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -1547,7 +1551,7 @@ static inline bool kparser_conf_node_convert(const struct kparser_conf_node *con } /* create handler for object parse node */ -int kparser_create_parse_node(const struct kparser_conf_cmd *conf, +int kparser_create_parse_node(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -1672,7 +1676,7 @@ int kparser_create_parse_node(const struct kparser_conf_cmd *conf, } /* read handler for object parse node */ -int kparser_read_parse_node(const struct kparser_hkey *key, +int kparser_read_parse_node(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -1708,7 +1712,7 @@ int kparser_read_parse_node(const struct kparser_hkey *key, } /* delete handler for object parse node */ -int kparser_del_parse_node(const struct kparser_hkey *key, +int kparser_del_parse_node(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -1859,7 +1863,7 @@ static bool kparser_create_proto_table_ent(const struct kparser_conf_table *arg, } /* create handler for object protocol table */ -int kparser_create_proto_table(const struct kparser_conf_cmd *conf, +int kparser_create_proto_table(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -1950,7 +1954,7 @@ int kparser_create_proto_table(const struct kparser_conf_cmd *conf, } /* read handler for object protocol table */ -int kparser_read_proto_table(const struct kparser_hkey *key, +int kparser_read_proto_table(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -2016,7 +2020,7 @@ int kparser_read_proto_table(const struct kparser_hkey *key, } /* delete handler for object protocol table */ -int kparser_del_proto_table(const struct kparser_hkey *key, +int kparser_del_proto_table(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -2186,7 +2190,7 @@ static inline bool kparser_conf_tlv_node_convert(const struct kparser_conf_node_ } /* create handler for object tlv node */ -int kparser_create_parse_tlv_node(const struct kparser_conf_cmd *conf, +int kparser_create_parse_tlv_node(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -2272,7 +2276,7 @@ int kparser_create_parse_tlv_node(const struct kparser_conf_cmd *conf, } /* read handler for object tlv node */ -int kparser_read_parse_tlv_node(const struct kparser_hkey *key, +int kparser_read_parse_tlv_node(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -2366,7 +2370,7 @@ static bool kparser_create_tlv_proto_table_ent(const struct kparser_conf_table * } /* create handler for object tlv proto table */ -int kparser_create_tlv_proto_table(const struct kparser_conf_cmd *conf, +int kparser_create_tlv_proto_table(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -2455,7 +2459,7 @@ int kparser_create_tlv_proto_table(const struct kparser_conf_cmd *conf, } /* read handler for object tlv proto table */ -int kparser_read_tlv_proto_table(const struct kparser_hkey *key, +int kparser_read_tlv_proto_table(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -2521,7 +2525,7 @@ int kparser_read_tlv_proto_table(const struct kparser_hkey *key, } /* create handler for object flag field */ -int kparser_create_flag_field(const struct kparser_conf_cmd *conf, +int kparser_create_flag_field(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -2601,7 +2605,7 @@ int kparser_create_flag_field(const struct kparser_conf_cmd *conf, } /* read handler for object flag field */ -int kparser_read_flag_field(const struct kparser_hkey *key, +int kparser_read_flag_field(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -2720,7 +2724,7 @@ static bool kparser_create_flag_field_table_ent(const struct kparser_conf_table } /* create handler for object flag field */ -int kparser_create_flag_field_table(const struct kparser_conf_cmd *conf, +int kparser_create_flag_field_table(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -2807,7 +2811,7 @@ int kparser_create_flag_field_table(const struct kparser_conf_cmd *conf, } /* read handler for object flag field */ -int kparser_read_flag_field_table(const struct kparser_hkey *key, +int kparser_read_flag_field_table(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -2898,7 +2902,7 @@ kparser_create_parse_flag_field_node_convert(const struct kparser_conf_node_pars } /* create handler for object flag field node */ -int kparser_create_parse_flag_field_node(const struct kparser_conf_cmd *conf, +int kparser_create_parse_flag_field_node(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -2983,7 +2987,7 @@ int kparser_create_parse_flag_field_node(const struct kparser_conf_cmd *conf, } /* read handler for object flag field node */ -int kparser_read_parse_flag_field_node(const struct kparser_hkey *key, +int kparser_read_parse_flag_field_node(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -3080,7 +3084,7 @@ kparser_create_flag_field_proto_table_ent(const struct kparser_conf_table *arg, } /* create handler for object flag field proto table */ -int kparser_create_flag_field_proto_table(const struct kparser_conf_cmd *conf, +int kparser_create_flag_field_proto_table(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -3170,7 +3174,7 @@ int kparser_create_flag_field_proto_table(const struct kparser_conf_cmd *conf, } /* read handler for object flag field proto table */ -int kparser_read_flag_field_proto_table(const struct kparser_hkey *key, +int kparser_read_flag_field_proto_table(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -3270,7 +3274,7 @@ static inline bool kparser_parser_convert(const struct kparser_conf_parser *conf } /* create handler for object parser */ -int kparser_create_parser(const struct kparser_conf_cmd *conf, +int kparser_create_parser(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -3308,7 +3312,8 @@ int kparser_create_parser(const struct kparser_conf_cmd *conf, goto done; } - if (!kparser_cmd_create_pre_process(op, conf, &arg->key, &key, + if (!kparser_cmd_create_pre_process(netns, + op, conf, &arg->key, &key, (void **)&kparser, sizeof(*kparser), *rsp, offsetof(struct kparser_glue_parser, glue), extack, err)) @@ -3387,13 +3392,15 @@ int kparser_create_parser(const struct kparser_conf_cmd *conf, return KPARSER_ATTR_RSP(KPARSER_NS_PARSER); } -static bool kparser_dump_protocol_table(const struct kparser_proto_table *obj, +static bool kparser_dump_protocol_table(void *netns, + const struct kparser_proto_table *obj, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, void *extack, int *err); /* dump metadata list to netlink msg rsp */ -static bool kparser_dump_metadata_table(const struct kparser_metadata_table *obj, +static bool kparser_dump_metadata_table(void *netns, + const struct kparser_metadata_table *obj, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, void *extack, int *err) @@ -3420,7 +3427,8 @@ static bool kparser_dump_metadata_table(const struct kparser_metadata_table *obj /* NOTE: TODO: kparser_config_lock should not be released and reacquired here. Fix later. */ mutex_unlock(&kparser_config_lock); - rc = kparser_read_metalist(&glue_obj->glue.key, + rc = kparser_read_metalist(netns, + &glue_obj->glue.key, &new_rsp, &new_rsp_len, false, "read", extack, err); mutex_lock(&kparser_config_lock); @@ -3448,7 +3456,7 @@ static bool kparser_dump_metadata_table(const struct kparser_metadata_table *obj } /* dump parse node to netlink msg rsp */ -static bool kparser_dump_parse_node(const struct kparser_parse_node *obj, +static bool kparser_dump_parse_node(void *netns, const struct kparser_parse_node *obj, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, void *extack, int *err) @@ -3474,7 +3482,7 @@ static bool kparser_dump_parse_node(const struct kparser_parse_node *obj, /* NOTE: TODO: kparser_config_lock should not be released and reacquired here. Fix later. */ mutex_unlock(&kparser_config_lock); - rc = kparser_read_parse_node(&glue_obj->glue.glue.key, + rc = kparser_read_parse_node(netns, &glue_obj->glue.glue.key, &new_rsp, &new_rsp_len, false, "read", extack, err); mutex_lock(&kparser_config_lock); @@ -3494,11 +3502,11 @@ static bool kparser_dump_parse_node(const struct kparser_parse_node *obj, kparser_free(new_rsp); new_rsp = NULL; - if (!kparser_dump_protocol_table(obj->proto_table, rsp, rsp_len, extack, + if (!kparser_dump_protocol_table(netns, obj->proto_table, rsp, rsp_len, extack, err)) goto error; - if (!kparser_dump_metadata_table(obj->metadata_table, rsp, rsp_len, + if (!kparser_dump_metadata_table(netns, obj->metadata_table, rsp, rsp_len, extack, err)) goto error; @@ -3510,7 +3518,8 @@ static bool kparser_dump_parse_node(const struct kparser_parse_node *obj, } /* dump protocol table to netlink msg rsp */ -static bool kparser_dump_protocol_table(const struct kparser_proto_table *obj, +static bool kparser_dump_protocol_table(void *netns, + const struct kparser_proto_table *obj, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, void *extack, int *err) @@ -3537,7 +3546,7 @@ static bool kparser_dump_protocol_table(const struct kparser_proto_table *obj, /* NOTE: TODO: kparser_config_lock should not be released and reacquired here. Fix later. */ mutex_unlock(&kparser_config_lock); - rc = kparser_read_proto_table(&glue_obj->glue.key, + rc = kparser_read_proto_table(netns, &glue_obj->glue.key, &new_rsp, &new_rsp_len, false, "read", extack, err); mutex_lock(&kparser_config_lock); @@ -3558,7 +3567,8 @@ static bool kparser_dump_protocol_table(const struct kparser_proto_table *obj, new_rsp = NULL; for (i = 0; i < glue_obj->proto_table.num_ents; i++) - if (!kparser_dump_parse_node(glue_obj->proto_table.entries[i].node, + if (!kparser_dump_parse_node(netns, + glue_obj->proto_table.entries[i].node, rsp, rsp_len, extack, err)) goto error; @@ -3570,7 +3580,7 @@ static bool kparser_dump_protocol_table(const struct kparser_proto_table *obj, } /* dump parser to netlink msg rsp */ -static bool kparser_dump_parser(const struct kparser_glue_parser *kparser, +static bool kparser_dump_parser(void *netns, const struct kparser_glue_parser *kparser, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, void *extack, int *err) @@ -3581,7 +3591,7 @@ static bool kparser_dump_parser(const struct kparser_glue_parser *kparser, kparser_start_new_tree_traversal(); - if (!kparser_dump_parse_node(kparser->parser.root_node, rsp, rsp_len, + if (!kparser_dump_parse_node(netns, kparser->parser.root_node, rsp, rsp_len, extack, err)) goto error; @@ -3591,7 +3601,7 @@ static bool kparser_dump_parser(const struct kparser_glue_parser *kparser, } /* read handler for object parser */ -int kparser_read_parser(const struct kparser_hkey *key, +int kparser_read_parser(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -3621,7 +3631,7 @@ int kparser_read_parser(const struct kparser_hkey *key, (*rsp)->object.parser_conf = kparser->glue.config.parser_conf; if (recursive_read && - kparser_dump_parser(kparser, rsp, rsp_len, extack, err) == false) + kparser_dump_parser(netns, kparser, rsp, rsp_len, extack, err) == false) KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, "kparser_dump_parser failed"); done: @@ -3632,7 +3642,7 @@ int kparser_read_parser(const struct kparser_hkey *key, } /* delete handler for object parser */ -int kparser_del_parser(const struct kparser_hkey *key, +int kparser_del_parser(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, @@ -3698,7 +3708,7 @@ void kparser_free_parser(void *ptr, void *arg) } /* handler for object parser lock */ -int kparser_parser_lock(const struct kparser_conf_cmd *conf, +int kparser_parser_lock(void *netns, const struct kparser_conf_cmd *conf, size_t conf_len, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, const char *op, @@ -3737,7 +3747,7 @@ int kparser_parser_lock(const struct kparser_conf_cmd *conf, } /* handler for object parser unlock */ -int kparser_parser_unlock(const struct kparser_hkey *key, +int kparser_parser_unlock(void *netns, const struct kparser_hkey *key, struct kparser_cmd_rsp_hdr **rsp, size_t *rsp_len, __u8 recursive_read, const char *op, diff --git a/net/kparser/kparser_datapath.c b/net/kparser/kparser_datapath.c index 556d3d0557..997d7e6a25 100644 --- a/net/kparser/kparser_datapath.c +++ b/net/kparser/kparser_datapath.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "kparser.h" #include "kparser_condexpr.h" @@ -1125,10 +1126,12 @@ int kparser_parse(struct sk_buff *skb, { struct kparser_glue_parser *k_prsr; struct kparser_parser *parser; + struct net *net = NULL; + void *netns = NULL; void *data, *ptr; + __u32 dflags = 0; size_t pktlen; int err; - __u32 dflags = 0; data = skb_mac_header(skb); pktlen = skb_mac_header_len(skb) + skb->len; @@ -1138,11 +1141,16 @@ int kparser_parse(struct sk_buff *skb, pktlen = skb_mac_header_len(skb) + skb->len; } + err = skb_linearize(skb); if (err < 0) return err; WARN_ON(skb->data_len); + net = get_net(sock_net(skb->sk)); + if (net) + netns = net->kparser_ns; + /* TODO: do this pullup inside the loop of ___kparser_parse(), when * parse_len < hdr_len * if (pktlen > KPARSER_MAX_SKB_PACKET_LEN) { @@ -1161,6 +1169,8 @@ int kparser_parse(struct sk_buff *skb, if (kparser_key) KPARSER_KMOD_DEBUG_PRINT(dflags, "parser {%s:%u} is not found\n", kparser_key->name, kparser_key->id); + if (net) + put_net(net); return -EINVAL; } @@ -1180,16 +1190,21 @@ int kparser_parse(struct sk_buff *skb, rcu_read_unlock(); if (likely(!avoid_ref)) kparser_ref_put(&k_prsr->glue.refcount); + if (net) + put_net(net); return -ENOENT; } - err = __kparser_parse(parser, data, pktlen, _metadata, metadata_len); + err = __kparser_parse_ns(net, parser, data, pktlen, _metadata, metadata_len); rcu_read_unlock(); if (likely(!avoid_ref)) kparser_ref_put(&k_prsr->glue.refcount); + if (net) + put_net(net); + return err; } EXPORT_SYMBOL(kparser_parse); @@ -1264,3 +1279,391 @@ bool kparser_put_parser(const void *obj, bool avoid_ref) return true; } EXPORT_SYMBOL(kparser_put_parser); + +/* These are namespace supported versions but otherwise identical APIs of the + * above + */ +int __kparser_parse_ns(struct net *net, const void *obj, void *_hdr, + size_t parse_len, void *_metadata, size_t metadata_len) +{ + const struct kparser_parse_node *next_parse_node, *atencap_node; + const struct kparser_parse_node *parse_node, *wildcard_node; + struct kparser_ctrl_data ctrl = { .ret = KPARSER_OKAY }; + const struct kparser_metadata_table *metadata_table; + const struct kparser_proto_table *proto_table; + const struct kparser_proto_node *proto_node; + const struct kparser_parser *parser = obj; + int type = -1, i, ret, framescnt; + struct kparser_counters *cntrs; + void *_frame, *_obj_ref = NULL; + const void *base_hdr = _hdr; + ssize_t hdr_offset = 0; + ssize_t hdr_len, res; + __u32 frame_num = 0; + __u32 dflags = 0; + bool currencap; + + if (parser && parser->config.max_encaps > framescnt) + framescnt = parser->config.max_encaps; + + if (!parser || !_metadata || metadata_len == 0 || !_hdr || parse_len == 0 || + (((framescnt * parser->config.frame_size) + + parser->config.metameta_size) > metadata_len)) { + KPARSER_KMOD_DEBUG_PRINT(dflags, + "one or more empty/invalid param(s)\n"); + return -EINVAL; + } + + if (parser->kparser_start_signature != KPARSERSTARTSIGNATURE || + parser->kparser_end_signature != KPARSERENDSIGNATURE) { + KPARSER_KMOD_DEBUG_PRINT(dflags, + "%s:corrupted kparser signature:start:0x%02x, end:0x%02x\n", + __func__, parser->kparser_start_signature, parser->kparser_end_signature); + return -EINVAL; + } + + if (parse_len < parser->config.metameta_size) { + KPARSER_KMOD_DEBUG_PRINT(dflags, + "parse buf err, parse_len:%lu, mmd_len:%lu\n", + parse_len, parser->config.metameta_size); + return -EINVAL; + } + + _frame = _metadata + parser->config.metameta_size; + dflags = parser->config.flags; + + if (dflags & KPARSER_F_DEBUG_DATAPATH) { + /* This code is required for regression tests also */ + pr_alert("kParserdump:len:%lu\n", parse_len); + print_hex_dump_bytes("kParserdump:rcvd_pkt:", + DUMP_PREFIX_OFFSET, _hdr, parse_len); + } + + ctrl.hdr_base = _hdr; + ctrl.node_cnt = 0; + ctrl.encap_levels = 0; + + cntrs = rcu_dereference(parser->cntrs); + if (cntrs) { + /* Initialize parser counters */ + memset(cntrs, 0, sizeof(parser->cntrs_len)); + } + + parse_node = rcu_dereference(parser->root_node); + if (!parse_node) { + KPARSER_KMOD_DEBUG_PRINT(dflags, + "root node missing,parser:%s\n", + parser->name); + return -ENOENT; + } + + /* Main parsing loop. The loop normal teminates when we encounter a + * leaf protocol node, an error condition, hitting limit on layers of + * encapsulation, protocol condition to stop (i.e. flags that + * indicate to stop at flow label or hitting fragment), or + * unknown protocol result in table lookup for next node. + */ + do { + KPARSER_KMOD_DEBUG_PRINT(dflags, + "Parsing node:%s\n", + parse_node->name); + currencap = false; + proto_node = &parse_node->proto_node; + hdr_len = proto_node->min_len; + + if (++ctrl.node_cnt > parser->config.max_nodes) { + ctrl.ret = KPARSER_STOP_MAX_NODES; + goto parser_out; + } + /* Protocol node length checks */ + KPARSER_KMOD_DEBUG_PRINT(dflags, + "kParser parsing %s\n", + parse_node->name); + /* when SKB is passed, if parse_len < hdr_len, then + * try to do skb_pullup(hdr_len) here. reset parse_len based on + * new parse_len, reset data ptr. Do this inside this loop. + */ + if (parse_len < hdr_len) { + ctrl.ret = KPARSER_STOP_LENGTH; + goto parser_out; + } + + do { + if (!proto_node->ops.len_parameterized) + break; + + hdr_len = eval_parameterized_len(&proto_node->ops.pflen, _hdr); + + KPARSER_KMOD_DEBUG_PRINT(dflags, + "eval_hdr_len:%ld min_len:%lu\n", + hdr_len, proto_node->min_len); + + if (hdr_len < proto_node->min_len) { + ctrl.ret = hdr_len < 0 ? hdr_len : KPARSER_STOP_LENGTH; + goto parser_out; + } + if (parse_len < hdr_len) { + ctrl.ret = KPARSER_STOP_LENGTH; + goto parser_out; + } + } while (0); + + hdr_offset = _hdr - base_hdr; + ctrl.pkt_len = parse_len; + + /* Callback processing order + * 1) Extract Metadata + * 2) Process TLVs + * 2.a) Extract metadata from TLVs + * 2.b) Process TLVs + * 3) Process protocol + */ + + metadata_table = rcu_dereference(parse_node->metadata_table); + /* Extract metadata, per node processing */ + if (metadata_table) { + ctrl.ret = extract_metadata_table(dflags, + parser, + metadata_table, + _hdr, hdr_len, hdr_offset, + _metadata, _frame, &ctrl); + if (ctrl.ret != KPARSER_OKAY) + goto parser_out; + } + + /* Process node type */ + switch (parse_node->node_type) { + case KPARSER_NODE_TYPE_PLAIN: + default: + break; + case KPARSER_NODE_TYPE_TLVS: + /* Process TLV nodes */ + ctrl.ret = kparser_parse_tlvs(dflags, parser, + parse_node, + _obj_ref, _hdr, hdr_len, + hdr_offset, _metadata, + _frame, &ctrl); +check_processing_return: + switch (ctrl.ret) { + case KPARSER_STOP_OKAY: + goto parser_out; + case KPARSER_OKAY: + break; /* Go to the next node */ + case KPARSER_STOP_NODE_OKAY: + /* Note KPARSER_STOP_NODE_OKAY means that + * post loop processing is not + * performed + */ + ctrl.ret = KPARSER_OKAY; + goto after_post_processing; + case KPARSER_STOP_SUB_NODE_OKAY: + ctrl.ret = KPARSER_OKAY; + break; /* Just go to next node */ + default: + goto parser_out; + } + break; + case KPARSER_NODE_TYPE_FLAG_FIELDS: + /* Process flag-fields */ + res = kparser_parse_flag_fields(dflags, parser, + parse_node, + _obj_ref, + _hdr, hdr_len, + hdr_offset, + _metadata, + _frame, + &ctrl, parse_len); + if (res < 0) { + ctrl.ret = res; + goto check_processing_return; + } + hdr_len += res; + } + +after_post_processing: + /* Proceed to next protocol layer */ + + proto_table = rcu_dereference(parse_node->proto_table); + wildcard_node = rcu_dereference(parse_node->wildcard_node); + if (!proto_table && !wildcard_node) { + /* Leaf parse node */ + KPARSER_KMOD_DEBUG_PRINT(dflags, "Leaf node"); + goto parser_out; + } + + if (proto_table) { + do { + if (proto_node->ops.cond_exprs_parameterized) { + ctrl.ret = + eval_cond_exprs(dflags, + &proto_node->ops.cond_exprs, + _hdr); + if (ctrl.ret != KPARSER_OKAY) + goto parser_out; + } + + if (!proto_table) + break; + type = + eval_parameterized_next_proto(dflags, + &proto_node->ops.pfnext_proto, + _hdr); + KPARSER_KMOD_DEBUG_PRINT(dflags, + "nxt_proto key:%x\n", + type); + if (type < 0) { + ctrl.ret = type; + goto parser_out; + } + + /* Get next node */ + next_parse_node = lookup_node(dflags, + type, + proto_table, + ¤cap); + + if (next_parse_node) + goto found_next; + } while (0); + } + + /* Try wildcard node. Either table lookup failed to find a + * node or there is only a wildcard + */ + if (wildcard_node) { + /* Perform default processing in a wildcard node */ + next_parse_node = wildcard_node; + } else { + /* Return default code. Parsing will stop + * with the inidicated code + */ + ctrl.ret = parse_node->unknown_ret; + goto parser_out; + } + +found_next: + /* Found next protocol node, set up to process */ + if (!proto_node->overlay) { + /* Move over current header */ + _hdr += hdr_len; + parse_len -= hdr_len; + } + + parse_node = next_parse_node; + if (currencap || proto_node->encap) { + /* Check is there is an atencap_node configured for + * the parser + */ + atencap_node = rcu_dereference(parser->atencap_node); + if (atencap_node) { + ret = __kparser_run_exit_node(dflags, + parser, + atencap_node, + _obj_ref, + _hdr, hdr_offset, + hdr_len, + _metadata, _frame, + &ctrl); + if (ret != KPARSER_OKAY) + goto parser_out; + } + + /* New encapsulation layer. Check against + * number of encap layers allowed and also + * if we need a new metadata frame. + */ + if (++ctrl.encap_levels > parser->config.max_encaps) { + ctrl.ret = KPARSER_STOP_ENCAP_DEPTH; + goto parser_out; + } + + if (frame_num < parser->config.max_frames) { + _frame += parser->config.frame_size; + frame_num++; + } + + /* Check if parser has counters that need to be reset + * at encap + */ + if (parser->cntrs) + for (i = 0; i < KPARSER_CNTR_NUM_CNTRS; i++) + if (parser->cntrs_conf.cntrs[i].reset_on_encap) + cntrs->cntr[i] = 0; + } + + } while (1); + +parser_out: + /* Convert PANDA_OKAY to PANDA_STOP_OKAY if parser is exiting normally. + * This means that okay_node will see PANDA_STOP_OKAY in ctrl.ret + */ + ctrl.ret = ctrl.ret == KPARSER_OKAY ? KPARSER_STOP_OKAY : ctrl.ret; + + parse_node = (ctrl.ret == KPARSER_OKAY || KPARSER_IS_OK_CODE(ctrl.ret)) ? + rcu_dereference(parser->okay_node) : rcu_dereference(parser->fail_node); + + if (!parse_node) { + if (dflags & KPARSER_F_DEBUG_DATAPATH) { + /* This code is required for regression tests also */ + pr_alert("kParserdump:metadata_len:%lu\n", metadata_len); + print_hex_dump_bytes("kParserdump:md:", + DUMP_PREFIX_OFFSET, + _metadata, metadata_len); + } + return ctrl.ret; + } + + /* Run an exit parse node. This is either the okay node or the fail + * node that is set in parser config + */ + ret = __kparser_run_exit_node(dflags, parser, parse_node, _obj_ref, + _hdr, hdr_offset, hdr_len, + _metadata, _frame, &ctrl); + if (ret != KPARSER_OKAY) + ctrl.ret = (ctrl.ret == KPARSER_STOP_OKAY) ? ret : ctrl.ret; + + if (dflags & KPARSER_F_DEBUG_DATAPATH) { + /* This code is required for regression tests also */ + pr_alert("kParserdump:metadata_len:%lu\n", metadata_len); + print_hex_dump_bytes("kParserdump:md:", DUMP_PREFIX_OFFSET, + _metadata, metadata_len); + } + + return ctrl.ret; +} +EXPORT_SYMBOL(__kparser_parse_ns); + +const void *kparser_get_parser_ns(struct net *net, + const struct kparser_hkey *kparser_key, + bool avoid_ref) +{ + struct kparser_glue_parser *k_prsr; + + k_prsr = kparser_get_parser_ctx(kparser_key); + if (!k_prsr) + return NULL; + + if (likely(!avoid_ref)) + kparser_ref_get(&k_prsr->glue.refcount); + + return &k_prsr->parser; +} +EXPORT_SYMBOL(kparser_get_parser_ns); + +bool kparser_put_parser_ns(struct net *net, const void *obj, bool avoid_ref) +{ + const struct kparser_parser *parser = obj; + struct kparser_glue_parser *k_parser; + + if (!parser) + return false; + + if (likely(!avoid_ref)) { + k_parser = container_of(parser, struct kparser_glue_parser, + parser); + kparser_ref_put(&k_parser->glue.refcount); + } + + return true; +} +EXPORT_SYMBOL(kparser_put_parser_ns); diff --git a/net/kparser/kparser_main.c b/net/kparser/kparser_main.c index 8a100e1917..89e7c3d410 100644 --- a/net/kparser/kparser_main.c +++ b/net/kparser/kparser_main.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "kparser.h" @@ -60,55 +61,55 @@ static int kparser_cli_cmd_handler(struct sk_buff *skb, struct genl_info *info); static const struct nla_policy kparser_nl_policy[KPARSER_ATTR_MAX] = { NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_CONDEXPRS, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_CONDEXPRS_TABLE, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_CONDEXPRS_TABLES, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_COUNTER, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_COUNTER_TABLE, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_METADATA, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_METALIST, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_NODE_PARSE, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_PROTO_TABLE, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_TLV_NODE_PARSE, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_TLV_PROTO_TABLE, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_FLAG_FIELD, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_FLAG_FIELD_TABLE, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_FLAG_FIELD_NODE_PARSE, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_FLAG_FIELD_PROTO_TABLE, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_PARSER, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), NS_DEFINE_POLICY_ATTR_ENTRY(KPARSER_NS_OP_PARSER_LOCK_UNLOCK, kparser_conf_cmd, - kparser_cmd_rsp_hdr), + kparser_cmd_rsp_hdr), }; /* define netlink operations and family */ @@ -186,7 +187,8 @@ static int kparser_send_cmd_rsp(int cmd, int attrtype, return ret; } -typedef int kparser_ops(const void *, size_t, struct kparser_cmd_rsp_hdr **, +typedef int kparser_ops(void *netns, const void *, size_t, + struct kparser_cmd_rsp_hdr **, size_t *, void *extack, int *err); /* define netlink msg processors */ @@ -222,6 +224,8 @@ static kparser_ops *kparser_ns_op_handler[KPARSER_ATTR_MAX] = { static int kparser_cli_cmd_handler(struct sk_buff *skb, struct genl_info *info) { struct kparser_cmd_rsp_hdr *rsp = NULL; + struct net *net = NULL; + void *netns = NULL; size_t rsp_len = 0; int ret_attr_id; int attr_idx; @@ -229,11 +233,19 @@ static int kparser_cli_cmd_handler(struct sk_buff *skb, struct genl_info *info) KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, "IN: "); + net = get_net(sock_net(skb->sk)); + if (net) + netns = net->kparser_ns; + + if (netns == NULL) + netns = kparser_alloc_global_ns_ctx(); + for (attr_idx = KPARSER_ATTR_UNSPEC + 1; attr_idx < KPARSER_ATTR_MAX; attr_idx++) { if (!info->attrs[attr_idx] || !kparser_ns_op_handler[attr_idx]) continue; - ret_attr_id = kparser_ns_op_handler[attr_idx](nla_data(info->attrs[attr_idx]), + ret_attr_id = kparser_ns_op_handler[attr_idx](netns, + nla_data(info->attrs[attr_idx]), nla_len(info->attrs[attr_idx]), &rsp, &rsp_len, info->extack, &err); @@ -264,6 +276,9 @@ static int kparser_cli_cmd_handler(struct sk_buff *skb, struct genl_info *info) if (rsp) kfree(rsp); + if (net) + put_net(net); + KPARSER_KMOD_DEBUG_PRINT(KPARSER_F_DEBUG_CLI, "OUT: "); return rc;