java 单机接口限流处理方案
416
2022-10-16
vpp中plugin的api编程(2) - VPE vs. Plugin Messages id
msgid是唯一识别api函数的标识,但是在使用的时候,plugin与vpe有一些区别,需要注意。 在代码中以VL_API_XXX来显示,具体的值是在编译的时候才确定的。
VPE注册时,使用的是全局宏,模块中第一个msg id不是0
static clib_error_t * ipsec_api_hookup (vlib_main_t * vm) { api_main_t *am = &api_main; #define _(N,n) \ vl_msg_api_set_handlers(VL_API_##N, #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ vl_api_##n##_t_print, \ sizeof(vl_api_##n##_t), 1); foreach_vpe_api_msg; #undef _ /* * Set up the (msg_name, crc, message-id) table */ setup_message_id_table (am); return 0; }
plugin注册时,使用的是基址+偏移,模块中的第一个msg_id是0,必须加上基址才能使用。
static void acl_vat_api_hookup (vat_main_t *vam) { acl_test_main_t * sm = &acl_test_main; /* Hook up handlers for replies from the data plane plug-in */ #define _(N,n) \ vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \ #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ vl_api_##n##_t_print, \ sizeof(vl_api_##n##_t), 1); foreach_vpe_api_reply_msg; #undef _ }
为什么会有这样的区别,我们来看一下。
plugin的message id
生成偏移
plugin是通过头文件包含的方式生成了偏移,即 VL_API_XXXX 以acl为例 是通过这3个.h来实现的。
acl_msg_enum.h -- 定义枚举结构,每个模块都是从0开始的 acl_all_api_h.h -- 所有acl api相关的.h文件都放在这里 acl.api.h -- acl使用的VL_API_XXX按顺序排布
acl_msg_enum.h 创建了枚举结构,包含了acl_all_api_h.h
20 #define vl_msg_id(n,h) n,
21 typedef enum {
22 #include
+ acl_all_api_h.h
所有acl api有关头文件都放在这里,统一管理
包含了acl.api.h
```c
16 #include
acl.api.h 由acl.api生成的文件,按顺序排布了VL_API_XXX 18 /****** Message ID / handler enum ******/ 19 20 #ifdef vl_msg_id 21 vl_msg_id(VL_API_ACL_ENABLE_CONFIG, vl_api_acl_enable_config_t_handler) 22 vl_msg_id(VL_API_ACL_ENABLE_CONFIG_REPLY, vl_api_acl_enable_config_reply_t_handler) 23 vl_msg_id(VL_API_ACL_PLUGIN_GET_VERSION, vl_api_acl_plugin_get_version_t_handler) 24 vl_msg_id(VL_API_ACL_PLUGIN_GET_VERSION_REPLY, vl_api_acl_plugin_get_version_reply_t_handler) 25 vl_msg_id(VL_API_ACL_PLUGIN_CONTROL_PING, vl_api_acl_plugin_control_ping_t_handler) 26 vl_msg_id(VL_API_ACL_PLUGIN_CONTROL_PING_REPLY, vl_api_acl_plugin_control_ping_reply_t_handler) 27 /* typeonly: acl_rule */ 28 /* typeonly: macip_acl_rule */ 29 vl_msg_id(VL_API_ACL_ADD_REPLACE, vl_api_acl_add_replace_t_handler) 30 vl_msg_id(VL_API_ACL_ADD_REPLACE_REPLY, vl_api_acl_add_replace_reply_t_handler) 31 vl_msg_id(VL_API_ACL_DEL, vl_api_acl_del_t_handler) 32 vl_msg_id(VL_API_ACL_DEL_REPLY, vl_api_acl_del_reply_t_handler) 33 vl_msg_id(VL_API_ACL_INTERFACE_ADD_DEL, vl_api_acl_interface_add_del_t_handler) 34 vl_msg_id(VL_API_ACL_INTERFACE_ADD_DEL_REPLY, vl_api_acl_interface_add_del_reply_t_handler) 35 vl_msg_id(VL_API_ACL_INTERFACE_SET_ACL_LIST, vl_api_acl_interface_set_acl_list_t_handler) ... 51 #endif
这样就生成了模块内api函数的偏移。 ### 获得基址 调用vl_msg_api_get_msg_ids函数获得 ```c u16 vl_msg_api_get_msg_ids (const char *name, int n) { api_main_t *am = &api_main; u8 *name_copy; vl_api_msg_range_t *rp; uword *p; u16 rv; if (am->msg_range_by_name == 0) am->msg_range_by_name = hash_create_string (0, sizeof (uword)); //获得干净的模块名(无数数字) name_copy = format (0, "%s%c", name, 0); //查看是否注册过 p = hash_get_mem (am->msg_range_by_name, name_copy); if (p) { clib_warning ("WARNING: duplicate message range registration for '%s'", name_copy); vec_free (name_copy); return ((u16) ~ 0); } //msg号的范围判断 if (n < 0 || n > 1024) { clib_warning ("WARNING: bad number of message-IDs (%d) requested by '%s'", n, name_copy); vec_free (name_copy); return ((u16) ~ 0); } //am->msg_ranges这个结构很重要,管理了所有的msg的范围 //获得rp vec_add2 (am->msg_ranges, rp, 1); //获取模块的msg_id。这个id是用全局的first_available_msg_id的 //每次加载一个模块后,就会增加响应的个数,这样就把所有的msg_id串起来了。 rv = rp->first_msg_id = am->first_available_msg_id; //增加全局msg_id个数,供下个模块使用 am->first_available_msg_id += n; rp->last_msg_id = am->first_available_msg_id - 1; rp->name = name_copy; //以名字为key,存入。clinet会用这个名字请求index hash_set_mem (am->msg_range_by_name, name_copy, rp - am->msg_ranges); return rv; }
使用
VPE下的message id
生成全局msg_id
VPE也是通过头文件包含的方式生成的 每个模块内部的第一个msg_id不是从0排布的,而是全局的,因为包含了所有的头文件
以ipsec为例 是通过这3个.h来实现的。 vnet_msg_enum.h -- 定义枚举结构 vnet_all_api_h.h -- 所有VPE api相关的.h文件都放在这里 ipsec.api.h -- ipsec使用的VL_API_XXX按顺序排布
vnet_msg_enum.h 定义的枚举结构,包含了vnet_all_api_h.h
18 #include
+ vnet_all_api_h.h
所有vnet的模块都在里面
```c
28 #ifndef included_from_layer_3
29 #include
ipsec.api.h ipsec所需的msg id 18 /****** Message ID / handler enum ******/ 19 20 #ifdef vl_msg_id 21 vl_msg_id(VL_API_IPSEC_SPD_ADD_DEL, vl_api_ipsec_spd_add_del_t_handler) 22 vl_msg_id(VL_API_IPSEC_SPD_ADD_DEL_REPLY, vl_api_ipsec_spd_add_del_reply_t_handler) 23 vl_msg_id(VL_API_IPSEC_INTERFACE_ADD_DEL_SPD, vl_api_ipsec_interface_add_del_spd_t_handler) 24 vl_msg_id(VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, vl_api_ipsec_interface_add_del_spd_reply_t_handler) 25 vl_msg_id(VL_API_IPSEC_SPD_ADD_DEL_ENTRY, vl_api_ipsec_spd_add_del_entry_t_handler) 26 vl_msg_id(VL_API_IPSEC_SPD_ADD_DEL_ENTRY_REPLY, vl_api_ipsec_spd_add_del_entry_reply_t_handler) 27 vl_msg_id(VL_API_IPSEC_SAD_ADD_DEL_ENTRY, vl_api_ipsec_sad_add_del_entry_t_handler) 28 vl_msg_id(VL_API_IPSEC_SAD_ADD_DEL_ENTRY_REPLY, vl_api_ipsec_sad_add_del_entry_reply_t_handler) 29 vl_msg_id(VL_API_IPSEC_SA_SET_KEY, vl_api_ipsec_sa_set_key_t_handler) 30 vl_msg_id(VL_API_IPSEC_SA_SET_KEY_REPLY, vl_api_ipsec_sa_set_key_reply_t_handler) 31 vl_msg_id(VL_API_IKEV2_PROFILE_ADD_DEL, vl_api_ikev2_profile_add_del_t_handler) 32 vl_msg_id(VL_API_IKEV2_PROFILE_ADD_DEL_REPLY, vl_api_ikev2_profile_add_del_reply_t_handler) 这样所有VPE有关全局的msg id就创建好了
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~