【翻译自/doc/developer/zebra.rst】
一、Zebra 协议概述
协议守护程序使用Zebra协议(或``ZAPI``) 来与 **zebra**守护程序进行通信。
每个协议守护程序都可以向**zebra**守护程序请求信息,并向其发送信息,例如接口状态、路由状态、下一跳验证等。协议守护程序还可以使用**zebra**安装路由。**zebra**守护进程负责管理将哪一种路由安装进操作系统内核。一些守护进程会使用多个ZAPI连接。每个ZAPI会话都有一个元组标识:``{protocol,instance,session_id}` `用于被识别。LDPD就是一个例子:它使用二级同步ZAPI会话来管理标签块。``session_id``的默认值为零,但使用多个ZAPI会话的守护进程必须为会话的id分配唯一的值。
Zebra协议是一个流协议,具有一个通用的标头。版本0缺少版本字段,并且是隐式版本。版本1和所有后续版本都有一个版本字段。通过检查标头的第3个字节,可以将版本0与所有其他版本区分开来,该字节包含除版本0之外的所有版本的255(在Quagga中)或254(在FRR中)标记值。标记字节对应于版本0中的命令字段,标记值是版本0中保留的命令。
1.1 历史版本
[此部分说明了zebra通信协议在各个版本中的变化]
- 版本 0
由所有版本的GNU Zebra和所有版本的Quagga使用,包括Quagga 0.98。此版本没有“version”字段,因此被隐式地版本化为版本0。
- 版本 1
增加了“maker”和“version”字段,将“command”字段增加到16bit。Quagga版本0.99.3至0.99.20使用。
- 版本 2
Quagga版本0.99.21至0.99.23使用。
- 版本 3
添加了“vrf_id”字段。由Quagga版本0.99.23使用,直到FRR分叉。
- 版本 4
将标记值更改为254,以防止人们混合和匹配Quagga和FRR守护程序二进制文件。由FRR版本2.0至3.0.3使用。
- 版本 5
将VRF标识符字段从16bit增加到32bit。由FRR版本4.0至5.0.1使用。
- 版本 6
删除了以下命令:
* ZEBRA_IPV4_ROUTE_ADD
* ZEBRA_IPV4_ROUTE_DELETE
* ZEBRA_IPV6_ROUTE_ADD
* ZEBRA_IPV6_ROUTE_DELETE
自FRR 6.0版起使用。
2. Zebra协议定义
2.1 Zebra协议头字段定义
- Length(总长度)
包含此标头的数据包总长度。
- Marker(静态标记)
静态标记。标记值(如果存在)在所有版本的Quagga中都是255。在FRR的所有版本中都是254。这是为了允许将版本0的标头(不明确包含版本)与版本化的标头区分开来。
- Version(版本号)
Zebra协议版本号。对于无法识别的版本,客户端不应继续处理超过版本字段的消息。
- Command(协议命令)
Zebra协议命令。
2.1.1当前版本
- 版本 5, 6
2.1.2过去的版本
- 版本 0
- 版本 1, 2
- 版本 3, 4
2.2 Zebra协议命令
+------------------------------------+-------+
| Command | Value |
+====================================+=======+
| ZEBRA_INTERFACE_ADD | 0 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_DELETE | 1 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_ADDRESS_ADD | 2 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_ADDRESS_DELETE | 3 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_UP | 4 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_DOWN | 5 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_SET_MASTER | 6 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_SET_PROTODOWN | 7 |
+------------------------------------+-------+
| ZEBRA_ROUTE_ADD | 8 |
+------------------------------------+-------+
| ZEBRA_ROUTE_DELETE | 9 |
+------------------------------------+-------+
| ZEBRA_ROUTE_NOTIFY_OWNER | 10 |
+------------------------------------+-------+
| ZEBRA_REDISTRIBUTE_ADD | 11 |
+------------------------------------+-------+
| ZEBRA_REDISTRIBUTE_DELETE | 12 |
+------------------------------------+-------+
| ZEBRA_REDISTRIBUTE_DEFAULT_ADD | 13 |
+------------------------------------+-------+
| ZEBRA_REDISTRIBUTE_DEFAULT_DELETE | 14 |
+------------------------------------+-------+
| ZEBRA_ROUTER_ID_ADD | 15 |
+------------------------------------+-------+
| ZEBRA_ROUTER_ID_DELETE | 16 |
+------------------------------------+-------+
| ZEBRA_ROUTER_ID_UPDATE | 17 |
+------------------------------------+-------+
| ZEBRA_HELLO | 18 |
+------------------------------------+-------+
| ZEBRA_CAPABILITIES | 19 |
+------------------------------------+-------+
| ZEBRA_NEXTHOP_REGISTER | 20 |
+------------------------------------+-------+
| ZEBRA_NEXTHOP_UNREGISTER | 21 |
+------------------------------------+-------+
| ZEBRA_NEXTHOP_UPDATE | 22 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_NBR_ADDRESS_ADD | 23 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_NBR_ADDRESS_DELETE | 24 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_BFD_DEST_UPDATE | 25 |
+------------------------------------+-------+
| ZEBRA_IMPORT_ROUTE_REGISTER | 26 |
+------------------------------------+-------+
| ZEBRA_IMPORT_ROUTE_UNREGISTER | 27 |
+------------------------------------+-------+
| ZEBRA_IMPORT_CHECK_UPDATE | 28 |
+------------------------------------+-------+
| ZEBRA_BFD_DEST_REGISTER | 29 |
+------------------------------------+-------+
| ZEBRA_BFD_DEST_DEREGISTER | 30 |
+------------------------------------+-------+
| ZEBRA_BFD_DEST_UPDATE | 31 |
+------------------------------------+-------+
| ZEBRA_BFD_DEST_REPLAY | 32 |
+------------------------------------+-------+
| ZEBRA_REDISTRIBUTE_ROUTE_ADD | 33 |
+------------------------------------+-------+
| ZEBRA_REDISTRIBUTE_ROUTE_DEL | 34 |
+------------------------------------+-------+
| ZEBRA_VRF_UNREGISTER | 35 |
+------------------------------------+-------+
| ZEBRA_VRF_ADD | 36 |
+------------------------------------+-------+
| ZEBRA_VRF_DELETE | 37 |
+------------------------------------+-------+
| ZEBRA_VRF_LABEL | 38 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_VRF_UPDATE | 39 |
+------------------------------------+-------+
| ZEBRA_BFD_CLIENT_REGISTER | 40 |
+------------------------------------+-------+
| ZEBRA_BFD_CLIENT_DEREGISTER | 41 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_ENABLE_RADV | 42 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_DISABLE_RADV | 43 |
+------------------------------------+-------+
| ZEBRA_NEXTHOP_LOOKUP_MRIB | 44 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_LINK_PARAMS | 45 |
+------------------------------------+-------+
| ZEBRA_MPLS_LABELS_ADD | 46 |
+------------------------------------+-------+
| ZEBRA_MPLS_LABELS_DELETE | 47 |
+------------------------------------+-------+
| ZEBRA_MPLS_LABELS_REPLACE | 48 |
+------------------------------------+-------+
| ZEBRA_IPMR_ROUTE_STATS | 49 |
+------------------------------------+-------+
| ZEBRA_LABEL_MANAGER_CONNECT | 50 |
+------------------------------------+-------+
| ZEBRA_LABEL_MANAGER_CONNECT_ASYNC | 51 |
+------------------------------------+-------+
| ZEBRA_GET_LABEL_CHUNK | 52 |
+------------------------------------+-------+
| ZEBRA_RELEASE_LABEL_CHUNK | 53 |
+------------------------------------+-------+
| ZEBRA_FEC_REGISTER | 54 |
+------------------------------------+-------+
| ZEBRA_FEC_UNREGISTER | 55 |
+------------------------------------+-------+
| ZEBRA_FEC_UPDATE | 56 |
+------------------------------------+-------+
| ZEBRA_ADVERTISE_DEFAULT_GW | 57 |
+------------------------------------+-------+
| ZEBRA_ADVERTISE_SVI_MACIP | 58 |
+------------------------------------+-------+
| ZEBRA_ADVERTISE_SUBNET | 59 |
+------------------------------------+-------+
| ZEBRA_ADVERTISE_ALL_VNI | 60 |
+------------------------------------+-------+
| ZEBRA_LOCAL_ES_ADD | 61 |
+------------------------------------+-------+
| ZEBRA_LOCAL_ES_DEL | 62 |
+------------------------------------+-------+
| ZEBRA_VNI_ADD | 63 |
+------------------------------------+-------+
| ZEBRA_VNI_DEL | 64 |
+------------------------------------+-------+
| ZEBRA_L3VNI_ADD | 65 |
+------------------------------------+-------+
| ZEBRA_L3VNI_DEL | 66 |
+------------------------------------+-------+
| ZEBRA_REMOTE_VTEP_ADD | 67 |
+------------------------------------+-------+
| ZEBRA_REMOTE_VTEP_DEL | 68 |
+------------------------------------+-------+
| ZEBRA_MACIP_ADD | 69 |
+------------------------------------+-------+
| ZEBRA_MACIP_DEL | 70 |
+------------------------------------+-------+
| ZEBRA_IP_PREFIX_ROUTE_ADD | 71 |
+------------------------------------+-------+
| ZEBRA_IP_PREFIX_ROUTE_DEL | 72 |
+------------------------------------+-------+
| ZEBRA_REMOTE_MACIP_ADD | 73 |
+------------------------------------+-------+
| ZEBRA_REMOTE_MACIP_DEL | 74 |
+------------------------------------+-------+
| ZEBRA_DUPLICATE_ADDR_DETECTION | 75 |
+------------------------------------+-------+
| ZEBRA_PW_ADD | 76 |
+------------------------------------+-------+
| ZEBRA_PW_DELETE | 77 |
+------------------------------------+-------+
| ZEBRA_PW_SET | 78 |
+------------------------------------+-------+
| ZEBRA_PW_UNSET | 79 |
+------------------------------------+-------+
| ZEBRA_PW_STATUS_UPDATE | 80 |
+------------------------------------+-------+
| ZEBRA_RULE_ADD | 81 |
+------------------------------------+-------+
| ZEBRA_RULE_DELETE | 82 |
+------------------------------------+-------+
| ZEBRA_RULE_NOTIFY_OWNER | 83 |
+------------------------------------+-------+
| ZEBRA_TABLE_MANAGER_CONNECT | 84 |
+------------------------------------+-------+
| ZEBRA_GET_TABLE_CHUNK | 85 |
+------------------------------------+-------+
| ZEBRA_RELEASE_TABLE_CHUNK | 86 |
+------------------------------------+-------+
| ZEBRA_IPSET_CREATE | 87 |
+------------------------------------+-------+
| ZEBRA_IPSET_DESTROY | 88 |
+------------------------------------+-------+
| ZEBRA_IPSET_ENTRY_ADD | 89 |
+------------------------------------+-------+
| ZEBRA_IPSET_ENTRY_DELETE | 90 |
+------------------------------------+-------+
| ZEBRA_IPSET_NOTIFY_OWNER | 91 |
+------------------------------------+-------+
| ZEBRA_IPSET_ENTRY_NOTIFY_OWNER | 92 |
+------------------------------------+-------+
| ZEBRA_IPTABLE_ADD | 93 |
+------------------------------------+-------+
| ZEBRA_IPTABLE_DELETE | 94 |
+------------------------------------+-------+
| ZEBRA_IPTABLE_NOTIFY_OWNER | 95 |
+------------------------------------+-------+
| ZEBRA_VXLAN_FLOOD_CONTROL | 96 |
+------------------------------------+-------+
| ZEBRA_VXLAN_SG_ADD | 97 |
+------------------------------------+-------+
| ZEBRA_VXLAN_SG_DEL | 98 |
+------------------------------------+-------+
| ZEBRA_VXLAN_SG_REPLAY | 99 |
+------------------------------------+-------+
| ZEBRA_MLAG_PROCESS_UP | 100 |
+------------------------------------+-------+
| ZEBRA_MLAG_PROCESS_DOWN | 101 |
+------------------------------------+-------+
| ZEBRA_MLAG_CLIENT_REGISTER | 102 |
+------------------------------------+-------+
| ZEBRA_MLAG_CLIENT_UNREGISTER | 103 |
+------------------------------------+-------+
| ZEBRA_MLAG_FORWARD_MSG | 104 |
+------------------------------------+-------+
| ZEBRA_ERROR | 105 |
+------------------------------------+-------+
| ZEBRA_CLIENT_CAPABILITIES | 106 |
+------------------------------------+-------+
| ZEBRA_OPAQUE_MESSAGE | 107 |
+------------------------------------+-------+
| ZEBRA_OPAQUE_REGISTER | 108 |
+------------------------------------+-------+
| ZEBRA_OPAQUE_UNREGISTER | 109 |
+------------------------------------+-------+
| ZEBRA_NEIGH_DISCOVER | 110 |
+------------------------------------+-------+
3.数据平面批处理
数据平面批处理是一种优化功能,它减少了我们想要发送的每一条消息在用户空间到内核空间转换中所涉及的处理时间。
3.1设计
通过对数据平面抽象,我们为要发送到内核的消息创建了一个“数据平面上下文对象队列”。在单独的pthread中,我们循环这个队列,并将上下文对象发送到合适的数据平面。这种批处理增强方法紧密结合数据平面上下文对象,因此它们能够被按批发送到支持它的数据平面。
数据平面代码有一个主要变化。它不逐个调用依赖于内核的函数,而是将一系列工作下放给内核级别进行处理。
3.1.1网络连接
目前,这是唯一允许向其批量发送消息的数据平面。
当消息必须发送到内核时,它们会连续添加到由“struct-nl_batch”表示的批中。上下文对象首先被编码为二进制表示。所有编码函数都使用相同的接口:将上下文对象、缓冲区和缓冲区大小作为参数。重要的是,它们应该处理消息无法放入缓冲区的情况并返回适当的错误提示。为了实现零拷贝(仅在用户空间中),消息被编码到相同的缓冲区,该缓冲区将被传递到内核。因此,理论上我们可以达到缓冲区的边界。
如果出现以下情况之一,存储在batch中的消息会被发送:
- - 当编码函数返回缓冲区溢出错误时。导致此错误的上下文对象将重新添加到新的空batch中。
- - 当批次的大小达到一定的限制时。
- - 当前正在处理的上下文对象的命名空间与以前的所有命名空间不同时。它们必须通过不同的套接字发送,因此消息不能共享同一缓冲区。
- - 在处理完列表中的最后一条消息之后。
如前所述,有一个特殊的阈值,它小于底层缓冲区的大小。它可以防止溢出错误,从而消除消息被编码两次的情况。
批处理中使用的缓冲区是全局的,因为每次分配那么多内存并不是最有效的。但是,可以使用隐藏的vtysh命令动态更改其大小:
zebra kernel netlink batch-tx-buf(1-1048576)(1-1048576)
此功能仅在测试中使用,不应在任何其他地方使用。
对于批处理中的每个失败消息,内核都会以错误消息进行响应。错误消息按照发送时的顺序保存,因此解析响应非常简单。我们使用双指针技术来匹配请求和响应,然后设置数据平面上下文对象的适当状态。还有一个全局接收缓冲区,被认为是内核发送的任何内容都适合这个缓冲区。网络连接错误消息的内容由错误码和请求原始网络连接的消息组成,因此批处理响应不会比增加了一些标头空间的批处理请求更大。