4. YANG 数据建模语言:基础语法、模块结构与数据类型

YANG(Yet Another Next Generation)是 IETF 标准化的数据建模语言(RFC 7950),用于定义网络设备配置数据、状态数据、远程过程调用(RPC)和通知的结构与约束。在控制平面接口调用与基线核验自动化中,YANG 是 NETCONF/RESTCONF 操作的核心契约,理解其语法与结构是编写自动化脚本、解析设备能力与生成基线模板的前提。

4.1 YANG 模块结构

一个 YANG 模块由头部声明、导入/包含语句、正文定义三部分组成。模块是 YANG 数据模型的基本容器,通常对应一个功能领域(如接口、路由、ACL)。

组成部分 关键字/语法 说明
模块头部 module <name> { 声明模块名称,必须唯一
命名空间 namespace "<uri>"; 定义 XML 命名空间,避免节点冲突
前缀 prefix <short>; 模块内引用本模块时的缩写
导入 import <module> { prefix <pre>; } 引用外部模块的类型或分组
包含 include <submodule>; 引入同一模块的子模块
正文定义 container / leaf / list / leaf-list / rpc / notification 核心数据与操作定义
模块结构示例(简化):
module example-interface {
    namespace "http://example.com/ns/interface";
    prefix if;

    import ietf-yang-types { prefix yang; }

    container interfaces {
        list interface {
            key "name";
            leaf name { type string; }
            leaf type { type enumeration { enum ethernet; enum loopback; } }
            leaf enabled { type boolean; default true; }
        }
    }
}
YANG 模块结构层次图 module example-interface namespace / prefix import / include revision / organization container list + key leaf / leaf-list rpc / notification 说明: • 模块头部定义元数据(命名空间、前缀、版本);import 引入外部模块的类型。 • 正文定义是数据模型的核心:container 作为容器,list 表示有序条目,leaf 为叶子节点。 • 每个模块必须包含至少一个 namespace 声明,且命名空间 URI 应全局唯一。

4.2 YANG 基础语法

YANG 语法采用类似 C 风格的花括号块结构,语句以分号结尾。核心语法规则包括:

  • 关键字与标识符:关键字小写(如 container、leaf、list);自定义标识符可包含字母、数字、连字符、下划线,不能以数字开头。
  • 语句结构:keyword [argument] { substatements; },其中 argument 可以是字符串、数字或引用。
  • 注释:支持单行 // 和多行 /* ... */ 注释。
  • 引用与路径:使用 prefix:node-name 格式引用外部模块节点;../ 表示父级路径。
  • 必须声明:mandatory true; 强制节点在配置中必须存在。
  • 默认值:default <value>; 为 leaf 指定默认值。
语法避坑:YANG 对缩进不敏感,但建议使用 4 空格缩进增强可读性。分号遗漏是初学者最常见的语法错误,尤其在嵌套块结束时容易忘记。

4.3 数据类型系统

YANG 提供丰富的内置数据类型,并支持通过 typedef 自定义派生类型。数据类型决定了节点可接受的值范围与格式。

类别 内置类型 说明 示例
基础类型 int8 / int16 / int32 / int64 有符号整数,范围固定 type int32;
基础类型 uint8 / uint16 / uint32 / uint64 无符号整数 type uint16 { range 0..4095; }
字符串 string UTF-8 文本,可加长度限制 type string { length 1..255; }
布尔 boolean true / false type boolean; default false;
枚举 enumeration 预定义命名值列表 enum up; enum down;
二进制 binary Base64 编码的二进制数据 type binary;
特殊类型 empty 无值标记,仅表示存在 type empty;
派生类型 typedef 基于内置类型自定义 typedef vlan-id { type uint16 { range 1..4094; } }
自定义类型示例:
typedef ipv4-address {
    type string {
        pattern '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}';
    }
    description "IPv4 地址格式";
}

typedef admin-status {
    type enumeration {
        enum up;
        enum down;
        enum testing;
    }
    default up;
}

4.4 容器(Container)与列表(List)

容器和列表是 YANG 中组织数据层次的核心结构。容器用于将相关叶子节点分组,列表用于表示可重复的条目集合。

结构 关键字 是否可重复 唯一标识 典型用途
容器 container 否(单实例) 无 分组配置参数,如系统信息、全局设置
列表 list 是(多实例) key 语句定义 接口列表、路由条目、VLAN 集合
叶子列表 leaf-list 是(多值) 无(有序集合) DNS 服务器列表、允许的 VLAN 列表
关键约束:列表必须通过 key 语句指定至少一个叶子节点作为唯一键。键值在列表实例中不可重复。如果列表不需要键(如状态数据),可使用 key 语句但留空,但实践中极少使用。
容器与列表数据层次对比 container system (单实例) leaf hostname leaf domain leaf contact leaf location list interface (多实例) key "name" (唯一标识) leaf name leaf type leaf enabled leaf mtu 对比要点: • 容器(左)为单实例,所有叶子节点全局唯一;适合存放系统级配置。 • 列表(右)为多实例,每个实例由 key 唯一标识;适合存放接口、路由等可重复对象。 • 列表内可嵌套容器或子列表,形成深层层次结构;容器内也可包含列表。

4.5 基线核验中的 YANG 应用

在自动化基线核验场景中,YANG 模型用于:

  • 定义期望基线:将设备配置的期望值建模为 YANG 容器/列表结构,存储为 JSON/XML 模板。
  • 解析设备状态:通过 NETCONF <get> 或 RESTCONF GET 获取设备实际运行数据,YANG 模型提供解析路径。
  • 差异对比:将实际数据与基线模板按 YANG 结构逐节点对比,自动标记偏离项。
  • 约束校验:利用 YANG 的 must、when、range 等约束语句,在数据写入前验证合规性。
自动化建议:在基线核验脚本中,优先使用 pyang 或 yangson 库加载 YANG 模型,将设备返回的 XML/JSON 数据绑定到模型实例,再通过 Python 字典对比实现基线校验。避免手动解析原始 XML 字符串。