IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> BFD协议解析及C/C++代码实现 -> 正文阅读

[C++知识库]BFD协议解析及C/C++代码实现

为了最大限度地减少设备/链路故障对业务的影响,提高网络可用性,网络设备必须能够快速检测到与相邻设备的通信故障。然后可以采取措施及时纠正故障,以确保服务的连续性。

而 BFD (双向转发检测)是一种故障检测协议,可以快速确定两个转发引擎之间的通信故障。

BFD Control 数据包格式

BFD 控制数据包有一个强制部分和一个可选认证部分。 认证部分的格式,如果目前,取决于使用的身份验证类型。

BFD Control 数据包强制部分

BFD 控制数据包的强制部分具有以下内容格式:

在这里插入图片描述
在这里插入图片描述

Version (Vers): 协议的版本号。 协议版本为 1。
Diagnostic (Diag):指定本地系统原因的诊断代码会话状态的最后一次更改。 值为:

 0 -- No Diagnostic
 1 -- Control Detection Time Expired
 2 -- Echo Function Failed
 3 -- Neighbor Signaled Session Down
 4 -- Forwarding Plane Reset
 5 -- Path Down
 6 -- Concatenated Path Down
 7 -- Administratively Down
 8 -- Reverse Concatenated Path Down
 9-31 -- Reserved for future use

该字段允许远程系统确定原因,例如,上一个会话失败。

State (Sta):发送系统看到的当前 BFD 会话状态。值为:

 0 -- AdminDown
 1 -- Down
 2 -- Init
 3 -- Up

在这里插入图片描述

Poll ( P):如果设置,发送系统正在请求验证连接性或参数更改,并且正在等待数据包, 最后(F)位作为回复。 如果清楚,发射系统不要求验证。

Final (F):如果设置,发送系统正在响应接收到的 BFD设置了轮询 § 位的控制数据包。 如果清楚,则传输系统没有响应轮询。

Control Plane Independent ?:如果设置,传输系统的 BFD 实现不会与其控制平面共享命运(换句话说,BFD 是在转发平面中实现并且可以继续运行通过控制平面的中断)。 如果清楚,则传输系统的 BFD 实现与其共享命运控制平面。

Authentication Present (A):如果设置,则存在身份验证部分并且会话是待认证

Demand (D):如果设置,需求模式在发射系统中处于活动状态(系统希望在需求模式下运行,知道会话是双向向上,并指示远程系统停止BFD 控制数据包的周期性传输)。 如果清楚,需求模式在发射系统中未激活。

Multipoint (M):该位保留用于将来的点对多点扩展BFD。 它在发送和接收时都必须为零。

Detect Mult :检测时间乘数。 协商的传输间隔,乘以这个值,提供检测时间 异步模式下的接收系统。 例如:

bfd_detect_time_multiplier * (bfd_desired_min_tx_interval/1000)

Length:BFD控制报文的长度,以字节为单位。

My Discriminator: 由传输系统,用于解复用多个 BFD 会话在同一对系统之间。

Your Discriminator:从相应的远程系统接收到的鉴别器。该字段反映了 My Discriminator 的接收值,如果该值未知,则为零。

Desired Min TX Interval:这是本地的最小间隔(以微秒为单位)系统希望在传输 BFD 控制数据包时使用,减去应用的任何抖动。 零值是预订的。

Required Min RX Interval:这是接收到的最小间隔(以微秒为单位)该系统能够支持的 BFD 控制数据包,减去发送方应用的任何抖动。 如果该值为零,发射系统不希望远程系统发送任何周期性的 BFD 控制数据包。

Required Min Echo RX Interval:这是接收到的最小间隔(以微秒为单位)本系统能够支持的 BFD Echo 报文,少发送方应用的任何抖动。 如果这值为零,发射系统不支持接收 BFD Echo 数据包。

BFD Control 数据包可选部分

可能存在可选的身份验证部分:

在这里插入图片描述

Auth Type :正在使用的身份验证类型,如果身份验证存在 (A)位已设置。

 0 - Reserved
 1 - Simple Password
 2 - Keyed MD5
 3 - Meticulous Keyed MD5
 4 - Keyed SHA1
 5 - Meticulous Keyed SHA1
 6-255 - Reserved for future use

Auth Len:身份验证部分的长度(以字节为单位),包括Auth Type 和 Auth Len 字段。

Simple Password 验证部分格式

如果在报头中设置了 Authentication Present (A) 位,并且Authentication Type 字段包含 1(Simple Password),身份验证部分具有以下格式:

在这里插入图片描述

在这里插入图片描述
Auth Type :身份验证类型,在本例中为 1(简单密码)。
Auth Len:认证部分的长度,以字节为单位。 对于简单密码认证,长度等于密码长度加三。
Auth Key ID:此数据包使用的身份验证密钥 ID。 这允许多个键同时激活。
Password :此会话中使用的简单密码。 密码是一个 二进制字符串,长度必须为 1 到 16 个字节。 这密码必须根据部分进行编码和配置。

Simple Password Authentication

最直接(也是最弱)的身份验证形式是简单的密码验证。 在这种身份验证方法中,一个或多个密码(具有相应的密钥 ID)在每个系统和其中一个密码/ID 对包含在每个 BFD 中控制数据包。 接收系统接受数据包,如果密码和密钥 ID 与配置的密码/ID 对之一匹配在那个系统中。

使用简单密码验证传输 :

  • 当前为会话选择的密码和密钥 ID 必须是存储在每个传出 BFD 控制的身份验证部分包。 Auth Type 字段必须设置为
    1(简单密码)。Auth Len 字段必须设置为适当的长度(4 到 19字节)。

使用简单密码验证接收 :

  • 如果接收到的 BFD 控制报文不包含Authentication 部分,或者 Auth Type
    不是1(简单密码),则必须丢弃接收到的数据包。
  • 如果 Auth Key ID 字段与配置的 ID 不匹配密码,接收到的数据包必须被丢弃。
  • 如果 Auth Len 字段不等于密码的长度由密钥 ID 选择,加上三,必须丢弃数据包。
  • 如果密码字段与管理员选择的密码不匹配密钥ID,数据包必须被丢弃。否则,数据包必须被接受。

Keyed MD5 认证部分格式

强烈建议不要使用基于 MD5 的身份验证。但是,这里记录了它与现有的兼容性实施。

如果在报头中设置了 Authentication Present (A) 位,并且Authentication Type 字段包含 2(Keyed MD5)或 3(Meticulous Keyed MD5),认证部分的格式如下:

在这里插入图片描述在这里插入图片描述

Auth Type:身份验证类型,在本例中为 2 (Keyed MD5) 或 3(Meticulous Keyed MD5)。

Auth Len:认证部分的长度,以字节为单位。 对于Keyed MD5 和 Meticulous Keyed MD5 认证,长度为 24。

Auth Key ID:此数据包使用的身份验证密钥 ID。 这允许多个键同时激活。

Reserved:该字节必须在发送时设置为零,并在接收时忽略。

Sequence Number:此数据包的序列号。 对于Keyed MD5 5身份验证,此值偶尔会增加。 为了
Meticulous Keyed MD5 身份验证,此值递增为会话传输的每个连续数据包。 这提供了防止重放攻击。

Keyed MD5 and Meticulous Keyed MD5 Authentication

Keyed MD5 和 Meticulous Keyed MD5 认证机制是与其他协议中使用的非常相似。 在这些方法中身份验证,一个或多个密钥(具有相应的密钥 ID)在每个系统中配置。

其中一个密钥包含在 MD5 中在传出 BFD 控制数据包上计算的摘要,但数据包中不携带密钥本身。 帮助避免重播攻击,每个数据包中还携带一个序列号。 对于Keyed MD5,序列号偶尔递增。 一丝不苟Keyed MD5,序列号在每个数据包上递增。

如果密钥 ID 匹配以下之一,则接收系统接受数据包配置的密钥,包括所选密钥匹配的 MD5 摘要数据包中携带的,并且序列号大于或等于收到的最后一个序列号(对于 Keyed MD5),或严格大于收到的最后一个序列号(对于细致的Keyed MD5)。

使用 Keyed MD5 和 Meticulous Keyed MD5 认证的传输 :

  • Auth Type 字段必须设置为 2(Keyed MD5)或 3(Meticulous Keyed MD5)。 Auth Len
    字段必须设置为 24。 Auth KeyID 字段必须设置为当前身份验证密钥的 ID。序列号字段必须设置为
    bfd.XmitAuthSeq。
  • 身份验证密钥值是最多 16 个字节的二进制字符串,并且必须放在 Auth Key/Digest 字段中,并用必要时尾随零字节。
    为了互操作性,配置密钥的管理接口必须接受 ASCII 字符串,并且应该还允许配置任何十六进制形式的任意二进制字符串。
    其他配置可能支持方法。
  • 必须在整个 BFD 控制中计算 MD5 摘要包。 结果摘要必须存储在 Auth 中传输前的密钥/摘要字段(替换密钥,不能在数据包中携带)。

使用 Keyed MD5 和 Meticulous Keyed MD5 身份验证接收:

  • 如果接收到的 BFD 控制报文不包含身份验证部分,或身份验证类型不正确(2 为 Keyed MD5 or 3 for Meticulous Keyed MD5),然后是接收到的数据包必须丢弃。
  • 如果 Auth Key ID 字段与配置的 ID 不匹配验证密钥,接收到的数据包必须被丢弃。
  • 如果 Auth Len 字段不等于 24,则数据包必须是丢弃。
  • 如果 bfd.AuthSeqKnown 为 1,请检查序列号字段。 为了 Keyed MD5,如果序列号超出范围bfd.RcvAuthSeq 到 bfd.RcvAuthSeq+(3Detect Mult) 包含(当被视为一个无符号的 32 位循环数空间),收到必须丢弃数据包。 对于 Meticulous Keyed MD5,如果序列号在 bfd.RcvAuthSeq+1 到bfd.RcvAuthSeq+(3Detect Mult) 包含(当被视为无符号 32 位循环数空间)接收的数据包必须是丢弃。
  • 否则(bfd.AuthSeqKnown 为 0),bfd.AuthSeqKnown 必须设置为 1,并且 bfd.RcvAuthSeq 必须设置为接收到的值序列号字段。
  • 将 Auth Key/Digest 字段的内容替换为由接收到的 Auth Key ID 字段选择的身份验证密钥。 如果整个 BFD 控制数据包的 MD5 摘要等于Auth Key/Digest 字段的接收值,接收到的数据包必须接受。 否则(摘要与 Auth 不匹配Key/Digest 字段),接收到的数据包必须被丢弃。

Keyed SHA1 认证部分格式

如果在报头中设置了 Authentication Present (A) 位,并且Authentication Type 字段包含 4(Keyed SHA1)或 5(Meticulous Keyed SHA1),认证部分的格式如下:

在这里插入图片描述
在这里插入图片描述

Auth Type:身份验证类型,在本例中为 4 (Keyed SHA1) 或 5(Meticulous Keyed SHA1)。

Auth Len:认证部分的长度,以字节为单位。 对于Keyed SHA1和 Meticulous Keyed SHA1 认证,长度为 28。

Auth Key ID:此数据包使用的身份验证密钥 ID。 这允许多个键同时激活。

Reserved:该字节必须在发送时设置为零,在接收时忽略 。

Sequence Number:此数据包的序列号。 对于Keyed SHA1身份验证,此值偶尔会增加。 为了Meticulous Keyed SHA1 Authentication,此值递增对于为会话传输的每个连续数据包。 这提供针对重放攻击的保护。

Auth Key/Hash:该字段携带数据包的 20 字节 SHA1 哈希值。

Keyed SHA1 and Meticulous Keyed SHA1 Authentication

Keyed SHA1 和 Meticulous Keyed SHA1 认证机制与其他协议中使用的非常相似。 在这些方法中身份验证,一个或多个密钥(具有相应的密钥ID)在每个系统中配置。

其中一个键包含在SHA1散列在传出 BFD 控制数据包上计算,但密钥本身不包含在数据包中。 帮助避免重播攻击,每个数据包中还携带一个序列号。 对于键控SHA1,序列号偶尔会增加。 为了Meticulous Keyed SHA1,序列号每递增一次包。

如果密钥 ID 匹配以下之一,则接收系统接受数据包配置的密钥,包含所选密钥匹配的 SHA1 哈希数据包中携带的,如果序列号更大大于或等于收到的最后一个序列号(对于 Keyed SHA1),或严格大于收到的最后一个序列号(对于细致的键控 SHA1)。

使用 Keyed SHA1 和 Meticulous Keyed SHA1 进行传输验证 :

  • Auth Type 字段必须设置为 4 (Keyed SHA1) 或 5 (Meticulous键控 SHA1)。 Auth Len
    字段必须设置为 28。 Auth KeyID 字段必须设置为当前身份验证密钥的 ID。序列号字段必须设置为bfd.XmitAuthSeq。
  • 身份验证密钥值是最多 20 个字节的二进制字符串,并且必须放在 Auth Key/Hash 字段中,用必要时尾随零字节。
    为了互操作性,配置密钥的管理接口必须接受ASCII 字符串,并且应该还允许配置任何十六进制形式的任意二进制字符串。 其他配置可能支持方法。
  • 必须在整个 BFD 控制数据包上计算 SHA1 哈希。生成的哈希必须先存储在 Auth Key/Hash
    字段中传输(替换密钥,这不能是包中携带)。

使用 Keyed SHA1 和 Meticulous Keyed SHA1 身份验证接收:

  • 如果接收到的 BFD 控制报文不包含身份验证部分,或身份验证类型不正确(4 为 Keyed SHA1 或 5 为 Meticulous Keyed SHA1),然后收到必须丢弃数据包。
  • 如果 Auth Key ID 字段与配置的 ID 不匹配验证密钥,接收到的数据包必须被丢弃。
  • 如果 Auth Len 字段不等于 28,则数据包必须是丢弃。
  • 如果 bfd.AuthSeqKnown 为 1,请检查序列号字段。 为了Keyed SHA1,如果序列号超出范围 bfd.RcvAuthSeq 到 bfd.RcvAuthSeq+(3Detect Mult) 包含(当被视为一个无符号的 32 位循环数空间),收到必须丢弃数据包。 对于 Meticulous Keyed SHA1,如果序列号在 bfd.RcvAuthSeq+1 到bfd.RcvAuthSeq+(3Detect Mult) 包含(当被视为无符号 32 位循环数空间,接收到的数据包必须是丢弃。 否则(bfd.AuthSeqKnown 为 0),bfd.AuthSeqKnown 必须设置为1、bfd.RcvAuthSeq 必须设置为接收到的值序列号字段,并且接收到的数据包必须被接受。
  • 将 Auth Key/Hash 字段的内容替换为由接收到的 Auth Key ID 字段选择的身份验证密钥。 如果整个 BFD 控制数据包的 SHA1 哈希等于Auth Key/Hash 字段的接收值,接收到的数据包必须接受。 否则(哈希与 Auth 不匹配Key/Hash 字段),接收到的数据包必须被丢弃。

BFD协议解析及C/C++代码实现

static void dissect_bfd_control(u_char *bfd_data, int payload_len)
{

	
	bfd_version = (bfd_data[0] & 0xe0) >> 5;
    bfd_diag    = (bfd_data[0] & 0x1f);
    flags       = bfd_data[1];
    switch (bfd_version) {
        case 0:
            bfd_flags      = flags;
            break;
        case 1:
        default:
            bfd_sta        = flags & 0xc0;
            bfd_flags      = flags & 0x3e;
            bfd_flags_a    = flags & 0x04;
            break;
    }

	bfd_detect_time_multiplier     = bfd_data[2];

    bfd_length                     = bfd_data[3];
    bfd_my_discriminator           = pntoh32(bfd_data + 4);
    bfd_your_discriminator         = pntoh32(bfd_data + 8);
    bfd_desired_min_tx_interval    = pntoh32(bfd_data + 12);
    bfd_required_min_rx_interval   = pntoh32(bfd_data + 16);
    bfd_required_min_echo_interval = pntoh32(bfd_data + 20);

    switch (bfd_version) {
        case 0:
            printf("Diag: %s, Flags: 0x%02x",
                         val_to_str_const(bfd_diag, bfd_control_v0_diag_values, "Unknown"),
                         bfd_flags);
            break;
        case 1:
        default:
            printf("Diag: %s, State: %s, Flags: 0x%02x",
                         val_to_str_const(bfd_diag, bfd_control_v1_diag_values, "Unknown"),
                         val_to_str_const(bfd_sta >> 6 , bfd_control_sta_values, "Unknown"),
                         bfd_flags);
            break;
    }
    ...

解析结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

BFD 是一种协议,可识别两个转发引擎(例如接口、数据链路或实际转发引擎)之间的双向路径中的故障。BFD 检测到故障后,通知路由协议切换到对等体的备用路径。

欢迎关注微信公众号【程序猿编码】,需要BFD协议完整源码的添加本人微信号(c17865354792)

参考:rfc5880

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-16 12:52:35  更:2022-02-16 12:52:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:06:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码