netopeer网络管理浅析简单介绍了基于netconf协议的netopeer项目是如何对实际设备进行管理的,基于对netopeer的学习,本节着手于对第二代netopeer2的研究,主要介绍netopeer2如何对实际设备进行管理,首先介绍如何读取当前linux系统的端口配置信息,实现类似于netopeer/transAPI/cfginterfaces/cfginterfaces-init的功能。

sysrepo简单使用中介绍了可以使用两种方式访问sysrepo数据库:独立进程形式和插件形式。

独立进程形式

使用独立进程形式可以更好地进行打印输出,调试代码,以方便项目开发。

首先在sysrepo/examples/plugin目录下,创建一个sr_interfaces.c文件,main函数中创建与sysrepo的连接,并开启一个会话,然后利用开启的会话,读取linux系统端口信息,并将端口信息注册到sysrepo数据库,具体如下:

int
main(int argc, char **argv)
{sr_conn_ctx_t *connection = NULL;sr_session_ctx_t *session = NULL;int rc = SR_ERR_OK;unsigned int dev_count;char **devices, *msg = NULL;int i;/* turn logging on */sr_log_stderr(SR_LL_WRN);/* connect to sysrepo */rc = sr_connect(0, &connection);if (rc != SR_ERR_OK) {goto cleanup;}/* start session */rc = sr_session_start(connection, SR_DS_RUNNING, &session);if (rc != SR_ERR_OK) {goto cleanup;}/* 获取linux系统端口*/devices = iface_get_ifcs(1, &dev_count, &msg);if(devices == NULL){goto cleanup;}for(i = 0; i < dev_count; i++){/* 解析端口信息,parse_iface_config函数的具体实现如下所示 */rc = parse_iface_config(session, devices[i], &msg);free(devices[i]);if(msg != NULL){free(msg);msg = NULL;}}free(devices);/* apply the change */rc = sr_apply_changes(session, 0, 0);if (rc != SR_ERR_OK) {goto cleanup;}cleanup:sr_disconnect(connection);return rc ? EXIT_FAILURE : EXIT_SUCCESS;
}

parse_iface_config函数的具体实现如下:

int parse_iface_config(sr_session_ctx_t *session, const char if_name, char **msg)
{int i, j, rc, len;unsigned int ipv4_enabled;char *tmp, *tmp2;struct ip_addrs ips;char xpath0[128], xpath[128], xpath_ip[128];char ianaift[64] = "iana-if-type:";char ipaddr[64];ips.count = 0;strcpy(xpath0, "/ietf-interfaces:interfaces/interface[name='");strcat(xpath0, if_name);strcat(xpath0, "']");printf("xpath0: %s\n", xpath0);/* 设置一个interface节点,节点的name值为if_name指针指向的值 */rc = sr_set_item_str(session, xpath0, NULL, NULL, SR_EDIT_DEFAULT);if(if_name < (char*)2 || (tmp2 = iface_get_type(if_name, msg)) == NULL){return -1;}memcpy(xpath, xpath0, sizeof(xpath0));strcat(xpath, "/type");strcat(ianaift, tmp2);rc = sr_set_item_str(session, xpath, ianaift, NULL, SR_EDIT_DEFAULT);free(tmp2);if((tmp = iface_get_enabled(1, if_name, msg)) == NULL){return -1;}memcpy(xpath, xpath0, sizeof(xpath0));strcat(xpath, "/enabled");rc = sr_set_item_str(session, xpath, tmp, NULL, SR_EDIT_DEFAULT);free(tmp);/* IPv4 */if((j = iface_get_ipv4_presence(1, if_name, msg)) == -1){return -1;}if(j){if((tmp = iface_get_ipv4_enabled(if_name, msg)) == NULL){return -1;}if(strcmp(tmp, "true") == 0){ipv4_enabled = 1;}else{ipv4_enabled = 0;}memcpy(xpath, xpath0, sizeof(xpath0));strcat(xpath, "/ietf-ip:ipv4/enabled");rc = sr_set_item_str(session, xpath, tmp, NULL, SR_EDIT_DEFAULT);free(tmp);if((tmp = iface_get_ipv4_forwarding(1, if_name, msg)) == NULL){return -1;}memcpy(xpath, xpath0, sizeof(xpath0));strcat(xpath, "/ietf-ip:ipv4/forwarding");rc = sr_set_item_str(session, xpath, tmp, NULL, SR_EDIT_DEFAULT);free(tmp);if((tmp = iface_get_ipv4_mtu(1, if_name, msg)) == NULL){return -1;}memcpy(xpath, xpath0, sizeof(xpath0));strcat(xpath, "/ietf-ip:ipv4/mtu");if(atoi(tmp) < 65536){rc = sr_set_item_str(session, xpath, tmp, NULL, SR_EDIT_DEFAULT);}free(tmp);if(ipv4_enabled){if(iface_get_ipv4_ipaddrs(1, if_name, &ips, msg) != 0){return -1;}for(j = 0; j < ips.count; ++j){len = strlen(ips.ip[j]);memcpy(ipaddr, ips.ip[j], len);ipaddr[len] = '\0';/* ipv4下添加一个address节点,节点的key属性ip的值为ipaddr */memcpy(xpath_ip, xpath0, sizeof(xpath0));strcat(xpath_ip, "/ietf-ip:ipv4/address[ip='");strcat(xpath_ip, ipaddr);strcat(xpath_ip, "']");rc = sr_set_item_str(session, xpath_ip, NULL, NULL, SR_EDIT_DEFAULT);printf("xpath_ip: %s\n", xpath_ip);memcpy(xpath, xpath_ip, sizeof(xpath_ip));strcat(xpath, "/prefix-length");rc = sr_set_item_str(session, xpath, ips.prefix_or_mac[j], NULL, SR_EDIT_DEFAULT);printf("xpath: %s\n", xpath);free(ips.ip[j]);free(ips.prefix_or_mac[j]);}if(ips.count != 0){free(ips.ip);free(ips.prefix_or_mac);ips.count = 0;}}}/* IPv6 */if((j = iface_get_ipv6_presence(1, if_name, msg)) == -1){return -1;}if(j){memcpy(xpath, xpath0, sizeof(xpath0));strcat(xpath, "/ietf-ip:ipv6/enabled");rc = sr_set_item_str(session, xpath, "true", NULL, SR_EDIT_DEFAULT);if((tmp = iface_get_ipv6_forwarding(1, if_name, msg)) == NULL){return -1;}memcpy(xpath, xpath0, sizeof(xpath0));strcat(xpath, "/ietf-ip:ipv6/forwarding");rc = sr_set_item_str(session, xpath, tmp, NULL, SR_EDIT_DEFAULT);free(tmp);if((tmp = iface_get_ipv6_mtu(1, if_name, msg)) == NULL){return -1;}memcpy(xpath, xpath0, sizeof(xpath0));strcat(xpath, "/ietf-ip:ipv6/mtu");if(strcmp("65535", tmp) < 0){printf("mtu is too high");}else{rc = sr_set_item_str(session, xpath, tmp, NULL, SR_EDIT_DEFAULT);}free(tmp);if(iface_get_ipv6_ipaddrs(1, if_name, &ips, msg) != 0){return -1;}for(j = 0; j < ips.count; ++j){len = strlen(ips.ip[j]);memcpy(ipaddr, ips.ip[j], len);ipaddr[len] = '\0';memcpy(xpath_ip, xpath0, sizeof(xpath0));strcat(xpath_ip, "/ietf-ip:ipv6/address[ip='");strcat(xpath_ip, ipaddr);strcat(xpath_ip, "']");rc = sr_set_item_str(session, xpath_ip, NULL, NULL, SR_EDIT_DEFAULT);printf("xpath_ip: %s\n", xpath_ip);memcpy(xpath, xpath_ip, sizeof(xpath_ip));strcat(xpath, "/prefix-length");rc = sr_set_item_str(session, xpath, ips.prefix_or_mac[j], NULL, SR_EDIT_DEFAULT);free(ips.ip[j]);free(ips.prefix_or_mac[j]);}if(ips.count != 0){free(ips.ip);free(ips.prefix_or_mac);ips.count = 0;}if(iface_get_ipv6_neighs(1, if_name, &ips, msg) != 0){return -1;}for(j = 0; j < ips.count; ++j){len = strlen(ips.ip[j]);memcpy(ipaddr, ips.ip[j], len);ipaddr[len] = '\0';memcpy(xpath_ip, xpath0, sizeof(xpath0));strcat(xpath_ip, "/ietf-ip:ipv6/neighbor[ip='");strcat(xpath_ip, ipaddr);strcat(xpath_ip, "']");rc = sr_set_item_str(session, xpath_ip, NULL, NULL, SR_EDIT_DEFAULT);memcpy(xpath, xpath_ip, sizeof(xpath_ip));strcat(xpath, "/link-layer-address");rc = sr_set_item_str(session, xpath, ips.prefix_or_mac[j], NULL, SR_EDIT_DEFAULT);free(ips.ip[j]);free(ips.prefix_or_mac[j]);}if(ips.count != 0){free(ips.ip);free(ips.prefix_or_mac);ips.count = 0;}if((tmp = iface_get_ipv6_dup_addr_det(1, if_name, msg)) == NULL){return -1;}memcpy(xpath, xpath0, sizeof(xpath0));strcat(xpath, "/ietf-ip:ipv6/dup-addr-detect-transmits");rc = sr_set_item_str(session, xpath, tmp, NULL, SR_EDIT_DEFAULT);free(tmp);if((tmp = iface_get_ipv6_creat_glob_addr(1, if_name, msg)) == NULL){return -1;}memcpy(xpath, xpath0, sizeof(xpath0));strcat(xpath, "/ietf-ip:ipv6/autoconf/create-global-address");rc = sr_set_item_str(session, xpath, tmp, NULL, SR_EDIT_DEFAULT);free(tmp);}return 0;
}

上述函数中用到的诸如iface_***函数均借鉴自netopeer/transAPI/cfginterfaces/目录下的iface_if.c中定义的函数,主要完成读取设备端口相关信息。

编译自己新增的函数方法为:在sysrepo/examples目录下的CMakeLists.txt文件中添加自己的函数,如:

add_executable(ietf-interfaces plugin/iface_if.c plugin/sr_interfaces.c)
target_link_libraries(ietf-interfaces sysrepo)

然后重新cmake .. && make,就会在sysrepo/build/examples目录下生成可执行程序。然后就可以运行自己的程序了。

在sysrepo/build/examples目录下执行:

[root@localhost examples]# ./application_changes_example ietf-interfaces
Application will watch for changes in "ietf-interfaces".========== READING RUNNING CONFIG: ==========/ietf-interfaces:interfaces (container)========== LISTENING FOR CHANGES ==========

可以看到,当前状态下没有任何信息。另启一个终端,执行命令

[root@localhost examples]# ./ietf-interfaces
xpath0: /ietf-interfaces:interfaces/interface[name='ens32']
xpath0: /ietf-interfaces:interfaces/interface[name='lo']
xpath_ip: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/address[ip='127.0.0.1']
xpath: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/address[ip='127.0.0.1']/prefix-length

终端打印输出是parse_iface_config函数中printf()函数的输出。

在监听端可以看到如下打印信息:

[root@localhost examples]# ./application_changes_example ietf-interfaces
Application will watch for changes in "ietf-interfaces".
[WRN]: Removing event pipe "sr_evpipe16" after a crashed subscription.========== READING RUNNING CONFIG: ==========/ietf-interfaces:interfaces (container)========== LISTENING FOR CHANGES ==================== EVENT change CHANGES: ====================================CREATED: /ietf-interfaces:interfaces/interface[name='ens32'] (list instance)
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/name = ens32
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/type = iana-if-type:ethernetCsmacd
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/enabled = false
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4 (container)
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/enabled = false
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/forwarding = false
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/mtu = 1500
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6 (container)
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/enabled = true
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/forwarding = false
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/mtu = 1500
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/dup-addr-detect-transmits = 1
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/autoconf (container)
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/autoconf/create-global-addresses = true
CREATED: /ietf-interfaces:interfaces/interface[name='lo'] (list instance)
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/name = lo
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/type = iana-if-type:softwareLoopback
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/enabled = true
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4 (container)
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/enabled = true
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/forwarding = false
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/address[ip='127.0.0.1'] (list instance)
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/address[ip='127.0.0.1']/ip = 127.0.0.1
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/address[ip='127.0.0.1']/prefix-length = 8
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6 (container)
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/enabled = true
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/forwarding = false
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/dup-addr-detect-transmits = 1
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/autoconf (container)
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/autoconf/create-global-addresses = true========== END OF CHANGES ================================================= EVENT done CHANGES: ====================================CREATED: /ietf-interfaces:interfaces/interface[name='ens32'] (list instance)
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/name = ens32
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/type = iana-if-type:ethernetCsmacd
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/enabled = false
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4 (container)
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/enabled = false
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/forwarding = false
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/mtu = 1500
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6 (container)
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/enabled = true
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/forwarding = false
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/mtu = 1500
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/dup-addr-detect-transmits = 1
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/autoconf (container)
CREATED: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/autoconf/create-global-addresses = true
CREATED: /ietf-interfaces:interfaces/interface[name='lo'] (list instance)
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/name = lo
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/type = iana-if-type:softwareLoopback
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/enabled = true
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4 (container)
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/enabled = true
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/forwarding = false
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/address[ip='127.0.0.1'] (list instance)
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/address[ip='127.0.0.1']/ip = 127.0.0.1
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/address[ip='127.0.0.1']/prefix-length = 8
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6 (container)
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/enabled = true
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/forwarding = false
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/dup-addr-detect-transmits = 1
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/autoconf (container)
CREATED: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/autoconf/create-global-addresses = true========== END OF CHANGES ================================================= CONFIG HAS CHANGED, CURRENT RUNNING CONFIG: ==========/ietf-interfaces:interfaces (container)
/ietf-interfaces:interfaces/interface[name='ens32'] (list instance)
/ietf-interfaces:interfaces/interface[name='ens32']/name = ens32
/ietf-interfaces:interfaces/interface[name='ens32']/type = iana-if-type:ethernetCsmacd
/ietf-interfaces:interfaces/interface[name='ens32']/enabled = false
/ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4 (container)
/ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/enabled = false
/ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/forwarding = false
/ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/mtu = 1500
/ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6 (container)
/ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/enabled = true
/ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/forwarding = false
/ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/mtu = 1500
/ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/dup-addr-detect-transmits = 1
/ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/autoconf (container)
/ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv6/autoconf/create-global-addresses = true
/ietf-interfaces:interfaces/interface[name='lo'] (list instance)
/ietf-interfaces:interfaces/interface[name='lo']/name = lo
/ietf-interfaces:interfaces/interface[name='lo']/type = iana-if-type:softwareLoopback
/ietf-interfaces:interfaces/interface[name='lo']/enabled = true
/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4 (container)
/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/enabled = true
/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/forwarding = false
/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/address[ip='127.0.0.1'] (list instance)
/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/address[ip='127.0.0.1']/ip = 127.0.0.1
/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/address[ip='127.0.0.1']/prefix-length = 8
/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6 (container)
/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/enabled = true
/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/forwarding = false
/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/dup-addr-detect-transmits = 1
/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/autoconf (container)
/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/autoconf/create-global-addresses = true

可以看到,当前配置信息已经发生了改变,正确读取到系统端口配置信息。

此时,如果启动netopeer2-server和netopeer2-cli后,可以通过netopeer2-cli客户端看到相应端口信息。

插件形式

sysrepo插件就是一个共享库文件,必须提供两个接口:sr_plugin_init_cb() 和 sr_plugin_cleanup_cb()。设备的初始化数据必须在sr_plugin_init_cb()接口中实现,将编译好的.so文件放入sysrepo插件路径下,其安装路径在cmake的时候指定,如下所示:

[root@bogon build]# cmake ..
-- ietf-yang-library revision: 2019-01-04
-- Sysrepo repository: /home/renzg/netopeer2/libnetconf2/sysrepo-master/build/repository
-- Startup data path:  /home/renzg/netopeer2/libnetconf2/sysrepo-master/build/repository/data
-- Notification path:  /home/renzg/netopeer2/libnetconf2/sysrepo-master/build/repository/data/notif
-- YANG module path:   /home/renzg/netopeer2/libnetconf2/sysrepo-master/build/repository/yang
-- SRPD plugins path:  /usr/local/lib64/sysrepo/plugins
-- Missing tools (devscripts, debhelper package) for building DEB package.
-- To build local RPM package, use "build-rpm" target.
-- Configuring done
-- Generating done
-- Build files have been written to: /home/renzg/netopeer2/libnetconf2/sysrepo-master/build

/usr/local/lib64/sysrepo/plugins即为sysrepo插件路径。

插件形式实现读取设备初始数据的代码如下:

int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_data)
{int rc;(void)private_data;unsigned int dev_count;char** devices, *msg = NULL;int i;/* remember the session of our plugin */sess = session;devices = iface_get_ifcs(1, &dev_count, &msg);if (devices == NULL) {goto error;}for(i = 0; i < dev_count; i++){rc = parse_iface_config(session, devices[i], &msg);free(devices[i]);if(msg != NULL){free(msg);msg = NULL;}}free(devices);/* apply the change */rc = sr_apply_changes(session, 0, 0);if (rc != SR_ERR_OK) {goto error;}printf("sr_apply_changes end\n");/* sysrepo/plugins.h provides an interface for logging */SRP_LOG_DBGMSG("OVEN: Oven plugin initialized successfully.");return SR_ERR_OK;error:SRP_LOG_ERR("OVEN: Oven plugin initialization failed: %s.", sr_strerror(rc));sr_unsubscribe(subscription);return rc;
}void
sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *private_data)
{(void)session;(void)private_data;/* nothing to cleanup except freeing the subscriptions */sr_unsubscribe(subscription);SRP_LOG_DBGMSG("OVEN: Oven plugin cleanup finished.");
}

然后在sysrepo/examples/CMakeLists.txt文件中添加自己的.c文件

# ietf-interfaces plugin
add_library(ietf-interfaces MODULE plugin/iface_if.c plugin/interfaces.c)
set_target_properties(ietf-interfaces PROPERTIES PREFIX "")
target_link_libraries(ietf-interfaces sysrepo)

编译sysrepo源码,会在exampls文件夹下生成ietf-interfaces.so文件,将该文件复制到/usr/local/lib64/sysrepo/plugins目录下,执行sysrepo-plugind即可,如下所示:

[root@bogon build]# sysrepo-plugind -v3 -d
[INF]: Applying scheduled changes.
[INF]: No scheduled changes.
[INF]: Session 5 (user "root") created.
xpath0: /ietf-interfaces:interfaces/interface[name='ens32']
xpath: /ietf-interfaces:interfaces/interface[name='ens32']/type, ianaift: iana-if-type:ethernetCsmacd
xpath: /ietf-interfaces:interfaces/interface[name='ens32']/enabled
xpath_ip: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/address[ip='192.168.32.10']
xpath: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/address[ip='192.168.32.10']/prefix-length
xpath_ip: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/address[ip='192.168.32.10']
xpath: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/address[ip='192.168.32.10']/prefix-length
xpath_ip: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/address[ip='192.168.32.15']
xpath: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/address[ip='192.168.32.15']/prefix-length
xpath_ip: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/address[ip='192.168.32.15']
xpath: /ietf-interfaces:interfaces/interface[name='ens32']/ietf-ip:ipv4/address[ip='192.168.32.15']/prefix-length
xpath0: /ietf-interfaces:interfaces/interface[name='ens34']
xpath: /ietf-interfaces:interfaces/interface[name='ens34']/type, ianaift: iana-if-type:ethernetCsmacd
xpath: /ietf-interfaces:interfaces/interface[name='ens34']/enabled
xpath_ip: /ietf-interfaces:interfaces/interface[name='ens34']/ietf-ip:ipv4/address[ip='192.168.34.15']
xpath: /ietf-interfaces:interfaces/interface[name='ens34']/ietf-ip:ipv4/address[ip='192.168.34.15']/prefix-length
xpath_ip: /ietf-interfaces:interfaces/interface[name='ens34']/ietf-ip:ipv4/address[ip='192.168.34.15']
xpath: /ietf-interfaces:interfaces/interface[name='ens34']/ietf-ip:ipv4/address[ip='192.168.34.15']/prefix-length
xpath_ip: /ietf-interfaces:interfaces/interface[name='ens34']/ietf-ip:ipv4/address[ip='192.168.34.10']
xpath: /ietf-interfaces:interfaces/interface[name='ens34']/ietf-ip:ipv4/address[ip='192.168.34.10']/prefix-length
xpath0: /ietf-interfaces:interfaces/interface[name='lo']
xpath: /ietf-interfaces:interfaces/interface[name='lo']/type, ianaift: iana-if-type:softwareLoopback
xpath:/ietf-interfaces:interfaces/interface[name='lo']/enabled
xpath_ip: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/address[ip='127.0.0.1']
xpath: /ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv4/address[ip='127.0.0.1']/prefix-length
[INF]: No datastore changes to apply.
sr_apply_changes end

可以看到两种方式得到的结果是相同的。

完毕!

netopeer2开发(一)相关推荐

  1. java知识体系介绍

    国内最牛七星级团队马士兵.高淇等11位十年开发经验专家录制 目 录 百战程序员Java1573题 2百战程序员介绍 3JavaSE编程基础 9第一章 初识Java 9阶段项目课程1 11第二章 数据类 ...

  2. 【阶段小结】协同开发——这学期的Git使用小结

    [阶段小结]协同开发--这学期的Git使用小结 一.Git简介 1. Git简单介绍 2. Git工作流程以及各个区域 3. Git文件状态变化 二.Git安装&Git基本配置 三.个人踩坑 ...

  3. 基于Golang的简单web服务程序开发——CloudGo

    基于Golang的简单web服务程序开发--CloudGo[阅读时间:约10分钟] 一.概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 (1)基本要求 (2)扩展要求 三.具体 ...

  4. 【ReactiveX】基于Golang pmlpml/RxGo程序包的二次开发

    基于Golang pmlpml/RxGo程序包的二次开发[阅读时间:约20分钟] 一.ReactiveX & RxGo介绍 1.ReactiveX 2.RxGo 二.系统环境&项目介绍 ...

  5. 【golang程序包推荐分享】分享亿点点golang json操作及myJsonMarshal程序包开发的踩坑经历 :)

    目录[阅读时间:约5分钟] 一.概述 1.Json的作用 2.Go官方 encoding/json 包 3. golang json的主要操作 二.Json Marshal:将数据编码成json字符串 ...

  6. 基于Golang的对象序列化的程序包开发——myJsonMarshal

    基于Golang的对象序列化的程序包开发--myJsonMarshal[阅读时间:约10分钟] 一.对象序列化概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 三.具体程序设计及 ...

  7. 基于Golang的监听读取配置文件的程序包开发——simpleConfig_v1

    基于Golang的监听&读取配置文件的程序包开发--simpleConfig_v1 [阅读时间:约10分钟] 一.配置文件概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 ...

  8. 基于Golang的CLI 命令行程序开发

    基于Golang的CLI 命令行程序开发 [阅读时间:约15分钟] 一. CLI 命令行程序概述 二. 系统环境&项目介绍&开发准备 1.系统环境 2.项目介绍 3.开发准备 三.具体 ...

  9. 2022-2028年中国老年旅游市场深度调研及开发战略研究报告

    [报告类型]产业研究 [报告价格]¥4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中国老年旅游行业市场行业相关概述.中国老年 ...

最新文章

  1. 地图篇-01.获取用户位置
  2. php cros跨域处理,php接口设置cors实现ajax跨域
  3. 为什么牛逼的程序员都不用 “ ! = null 做判空?
  4. Hibernate映射关系之一对多
  5. mysql游标表间数据迁移_MySQL存储过程--通过游标遍历和异常处理迁移数据到历史表...
  6. 【Vue2.0】—props 配置(十三)
  7. 中国抗衰老护肤品市场趋势报告、技术动态创新及市场预测
  8. 怎么自动选中select中所有option
  9. apache的mpm工作模式
  10. c语言:【顺序表】静态顺序表的删除指定位置元素Erase、删除指定元素Remove
  11. jqprint 打印表格宽度_只要30秒!快速解决Excel表格打印问题
  12. 资金盘FairWin漏洞系统详解:项目方可以撇开“作恶”嫌疑了?
  13. 人工智能和计算机程序有什么区别,AI与计算机程序的区别?
  14. uos系统安装教程_统一操作系统UOS下载&安装图文教程:尝鲜记(一)
  15. 那些编程中遇到的常见英文缩写
  16. Go语言%d,%p,%v等占位符
  17. 华为往事(十一)---华为的“中南海”
  18. lic库的学习与使用流程(一般的库的使用流程)编译运行含有外包库程序的操作export和-L -I
  19. 用 C# picturebox 控件画图
  20. 浅析嵌入式系统的发展趋势

热门文章

  1. 物流英语与计算机操作,物流【英语】与计算机模拟题及正确答案.doc
  2. 如何向日历中添加日程
  3. 驱动开发:内核特征码扫描PE代码段
  4. python爬虫淘宝和天猫的区别_python爬虫获取淘宝天猫商品详细参数
  5. ffplay flv mp4 转_ffmpeg转换mp4到flv的使用笔记
  6. linux列表中添加多个元素,这12种方法轻松合并Python中的列表
  7. 机器人的弊议论文_《人工智能利与弊》高中作文800字5篇
  8. Python画一朵玫瑰
  9. 嘀嗒陪诊小程序v1.0.8+小程序前端
  10. C语言程序设计之考卷成绩分析软件程序设计