博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vpp中plugin的api编程(2) - VPE vs. Plugin Messages id
阅读量:7071 次
发布时间:2019-06-28

本文共 6864 字,大约阅读时间需要 22 分钟。

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,必须加上基址才能使用。

staticvoid 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 
    23 /* We'll want to know how many messages IDs we need... */24 VL_MSG_FIRST_AVAILABLE,25 } vl_msg_id_t;26 #undef vl_msg_id
+ acl_all_api_h.h  所有acl api有关头文件都放在这里,统一管理    包含了acl.api.h```c 16 #include 
17 18 #ifdef vl_printfun 19 #include
20 #endif
  • acl.api.h
    由acl.api生成的文件,按顺序排布了VL_API_XXX
    18 /****** Message ID / handler enum ******/19 20 #ifdef vl_msg_id21 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函数获得```cu16vl_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 
    19 20 #define vl_msg_id(n,h) n,21 typedef enum22 {23 VL_ILLEGAL_MESSAGE_ID = 0,24 #include
    25 VL_MSG_FIRST_AVAILABLE,26 } vl_msg_id_t;27 #undef vl_msg_id28 29 #endif /* included_vnet_msg_enum_h */
+ vnet_all_api_h.h  所有vnet的模块都在里面```c28 #ifndef included_from_layer_3 29 #include 
30 #endif /* included_from_layer_3 */ 31 32 #include
33 #include
34 #include
35 #include
36 #include
37 #include
38 #include
39 #include
40 #include
41 #include
42 #include
43 #include
44 #include
45 #include
46 #include
47 #include
48 #include
  • ipsec.api.h
    ipsec所需的msg id
    18 /****** Message ID / handler enum ******/19 20 #ifdef vl_msg_id21 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就创建好了

转载于:https://blog.51cto.com/zhangchixiang/2128871

你可能感兴趣的文章
实现SPF垃圾邮件防护功能
查看>>
Slave IO: Yes Slave SQL: No Seconds Behind Mast...
查看>>
eclipse 使用Maven deploy命令部署构建到Nexus上
查看>>
大型系统中使用JMS优化技巧–Sun OpenMQ
查看>>
正则表达式-断言
查看>>
用git合并分支时,如何保持某些文件不被合并
查看>>
局部代码块、构造代码块、静态代码块
查看>>
聚类分析 ---- K-Means算法
查看>>
C語言最新標準-C11 「轉」
查看>>
SaltStack数据系统-Grains详解
查看>>
课程第三天内容《基础交换 三 》
查看>>
Spring(八):缓存
查看>>
全局函数指针作为模板参数
查看>>
URL access forbidden for unknown reason svn: acces
查看>>
kafka基本命令启动和测试
查看>>
你真的已经搞懂JavaScript了吗?
查看>>
个性化PS1变量
查看>>
IOS之UIWebView的使用
查看>>
分布式系统事务一致性解决方案
查看>>
ubuntu下nvm,node以及npm的安装与使用
查看>>