netopeer2开发(一)

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

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

完毕!

你可能感兴趣的:(netconf)