如何使用libyang创建YANG带键列表节点并写入操作数据存储
问题描述
基于sysrepo示例YANG模型新增了WiFi扫描结构,其中scan容器下的bss列表以bssid为键,需要写入操作数据存储。使用libyang的lyd_new_path创建带键列表节点时,仅能生成bssid字段,其他字段无法添加;若不指定[bssid='...']谓词,会报错:
libyang[0]: 路径"/examples:scan/bss"中的列表"bss"缺少谓词。(路径: 模式位置"/examples:scan/bss"。)
YANG代码片段
container scan { config false; list bss { key "bssid"; leaf ssid { type string; } leaf bssid { type string; } leaf channel { type uint32; } leaf frequency { type uint32; } leaf chan_width { type int16; } leaf signal_strength { type int16; } } }
尝试的C代码
const char *s = "{\"bss\":[{\"bssid\":\"00:40:68:aa:bb:cc\",\"chan_width\":0,\"channel\":48,\"frequency\":5240,\"signal_strength\":0,\"ssid\":\"Hello World\"}]}"; err = lyd_new_path(NULL, ly_ctx, "/examples:scan/bss[bssid='00:40:68:aa:bb:cc']", s, 0, parent); printf("err=%d msg=%s parent=%p\n", err, ly_errmsg(ly_ctx), (void*)*parent); // 无数据测试是否成功(成功) err = lyd_new_path(*parent, ly_ctx, "/examples:scan/bss[bssid='00:40:68:11:22:33']", NULL, 0, NULL); printf("err=%d msg=%s parent=%p\n", err, ly_errmsg(ly_ctx), (void*)*parent); lyd_print_path("/tmp/test.json", *parent, LYD_JSON, 0);
解决方案
1. 匹配路径与数据层级
lyd_new_path的第四个参数(数据字符串)必须和路径指向的节点层级完全匹配。你当前路径指向的是单个bss列表项,但传入的JSON是包含bss数组的顶层结构,libyang无法识别这种不匹配的层级,因此只会解析出路径中指定的bssid字段。
2. 单个列表项的正确创建方式
针对单个bss列表项,传入的JSON应仅包含该列表项的字段键值对,无需外层的bss数组:
// 仅保留单个bss项的字段数据 const char *s = "{\"chan_width\":0,\"channel\":48,\"frequency\":5240,\"signal_strength\":0,\"ssid\":\"Hello World\"}"; // 路径指定具体bssid的列表项,传入对应字段数据 err = lyd_new_path(NULL, ly_ctx, "/examples:scan/bss[bssid='00:40:68:aa:bb:cc']", s, 0, parent);
3. 批量创建多个列表项
如果需要一次性添加多个bss项,可以直接传入包含完整scan容器结构的JSON,路径指向scan容器即可:
// 完整的scan容器JSON,包含多个bss项 const char *s = "{\"bss\":[{\"bssid\":\"00:40:68:aa:bb:cc\",\"chan_width\":0,\"channel\":48,\"frequency\":5240,\"signal_strength\":0,\"ssid\":\"Hello World\"}, {\"bssid\":\"00:40:68:11:22:33\",\"chan_width\":2,\"channel\":1,\"frequency\":2412,\"signal_strength\":-50,\"ssid\":\"Test AP\"}]}"; // 路径指向scan容器,直接导入完整结构 err = lyd_new_path(NULL, ly_ctx, "/examples:scan", s, 0, parent);
4. 谓词的必填性说明
bss是带键的列表,libyang要求必须通过谓词([bssid='xxx'])指定唯一的列表项,否则无法定位要操作的具体节点,因此不指定谓词必然报错,这是符合YANG模型规范的正常行为。
验证结果
修改后调用lyd_print_path生成的JSON会包含所有指定字段,示例输出:
{ "examples:scan": { "bss": [ { "bssid": "00:40:68:aa:bb:cc", "ssid": "Hello World", "channel": 48, "frequency": 5240, "chan_width": 0, "signal_strength": 0 }, { "bssid": "00:40:68:11:22:33", "chan_width": 2, "channel": 1, "frequency": 2412, "signal_strength": -50, "ssid": "Test AP" } ] } }
内容的提问来源于stack exchange,提问作者David Poole
相关产品推荐
相关产品推荐

