Switch-Router

VPP: FIB

Published at 2022-04-11 | Last Update 2022-04-11

本系列文章仅为学习使用 VPP 过程中的一些自用笔记

FIB 介绍

维基百科是这样描述 FIB 的:

A forwarding information base (FIB), also known as a forwarding table or MAC table, is most commonly used in network bridging, routing, and similar functions to find the proper output network interface to which the input interface should forward a packet.

一句话概括,FIB 的功能是为报文寻找合适的出接口

在不少人心目中,为报文寻找出接口是路由的功能。但对于网络设备而言,路由是更高层次的概念,它指的是 BGP、OSPF 这样的路由协议,而偏底层的 FIB 才是决定报文怎么走的信息提供者。或者我们可以这样说说,路由协议下发到 FIB,FIB 决定报文去向

FIB 并不是 VPP 特有的概念,其他内核如 Linux 也有自己的 FIB 实现,但本文主要聚焦分析 VPP 中的 FIB。

Control Plane 和 Data Plane

VPP 的 FIB 逻辑上分为 Control Plane (控制平面) 和 Data Plane (数据平面)。Control Plane 指的是由上层下发的规则,可以理解为是一种 Desired (期待的) 状态。Control Plane 规则会 contribute (生成) 整个 Data Plane。

                           +----------------+
     ip route add ... ---> |  Control Plane |
                           +----------------+
                                   |
                                   |contribute to
                                   |dataplane
                                   +
                           +----------------+
    packet#2  packet#1---->|   Data Plane   | ------>packet#0
                           +----------------+

Control Plane

以下一些术语在 FIB 中经常被提及

FIB table (FIB 表)

FIB 由一张一张的 table 组成,每张 table 相互隔离,具体的 FI (转发规则) 都是存放在 table 中。我们可以使用以下命令为 interface 设置自己使用的 FIB table。

set interface ip table <interface> <table-id>

这样一来,从该 interface 收到的报文就只会查询该 FIB table,如果查询成功,则会上送本地或者从同样设置了该 FIB table 的其他 interface 转发出去。

VPP 通过多个 FIB table 可以实现支持多个 VRF 的效果。

FIB entry (FIB 表项)

存储在 FIB table 中的规则称为 FIB entry。报文查找 FIB 实际上就是去指定的 table 中查找匹配的 FIB entry,并执行对应的动作。

Prefix (前缀)

FIB entry 的匹配方式是 Longest-Prefix 匹配,这里的 Prefix 指的是 IP address 和 mask 的组合。举例来说

  • 1.1.1.1 只是一个 IP address 而不是一个 prefix
  • 1.1.1.0/24 是一个 prefix
  • 1.1.1.1/32 也是一个 prefix,并且还是一个 host prefix 因为它的 mask 长度等于 IP address 的长度

Path 和 Path-list

Path 指的是通向特定 Prefix 的一条路径, Path-list 是一组 Path 的集合,在不涉及 ECMP (等价路由) 场景中,一个 Path-list 只包含一条 Path。

 ip route add 64.10.128.0/20 10.0.0.2 GigabitEthernet2/0/1
   |
   | 控制平面下发路由
   |     
 +-----+ G2/0/1           10.0.0.2 +--------+                         
 | VPP +---------------------------+ Router +-------- Network ------- Net: 64.10.128.0/20
 +-----+                           +--------+                         

 
 FIB entry 64.10.128.0/20:
   Path-list:nexthop:10.0.0.2

但若包含等价路由,则一个 Path-list 可能包含多条 Path

 ip route add 64.10.128.0/20 
    10.0.0.2 GigabitEthernet2/0/1
    10.1.1.2 GigabitEthernet2/0/2
   |
   | 控制平面下发路由    
   |                         10.0.0.2 +--------+
 +-----+ G2/0/1            +----------+ Router +-----------+                      
 |     +-------------------+          +--------+           |
 | VPP |                                                 Netwrok --- Net:64.10.128.0/20  
 |     +-------------------+          +--------+           |
 +-----+ G2/0/2            +----------+ Router +-----------+                         
                             10.1.1.2 +--------+
          
 
 FIB entry 64.10.128.0/20:
   Path-list:via G2/0/1 nexthop:10.0.0.2
              via G2/0/2 nexthop:10.1.1.2

Adjacency (邻接表项)

An adjacency is a representation of a peer on a particular link.

Adjacency 描述的是链路上的 peer 端信息,这个 peer 也就是报文 Next hop (下一跳)。

根据包含的信息不同,Adjacency 可分为多种类型,最常见的是 rewrite 类型和 glean 类型。

  • rewrite 类型表示 Adjacency 知道 peer 端的 MAC 地址,向 peer 发送报文时直接填入这个 MAC 地址就行。
  • glean 类型的 Adjacency 表示不知道 peer 端的 MAC 地址,如果要向 peer 端发送报文,还需要先进行 ARP 操作

一个例子

下面是一个综合了上面几个概念的例子,例子中下发了 3 条路由,因此生成了 3 条 fib entry,其中 2 条包含 ECMP,但因为它们的 Path 列表完全相同,因此它们共享一个 Path-list,另 1 条 fib entry 独享一个 Path-list。在 Adjacency 层面,由于 2 条 Path 完全相同,因此它们共享一条 Adjacency。

image

Data Plane

mtrie && data-path object

为了高效地进行 Longest-Prefix 查找,VPP 采用 mtrie 对 FIB entry 进行组织。

同时,对 32-bit 的 IPv4 地址来说,常用的分层方式有两种,即 8-8-8-8 和 16-8-8 , 分别如下图所示。

image

考虑到网络报文的实际特点(高 16-bit 通常变化不大),VPP 采用的是 16-8-8 的分层方式。这意味着,找到匹配的 leaf (叶子) 几点,最多只需要进行 3 层搜索。

VPP mtrie 的 leaf 节点保存的是一个叫 load-balancer 的东西,而 load-balancer 包含了一个或多个 dpo (data-path object),dpo 指示了下一步会怎样处理报文。dpo 也有分为多种类型,常见有

  • 对应 rewrite 邻接表项 的 DPO_ADJACENCY 类型
  • 对应 glean 邻接表项的 DPO_ADJACENCY_GLEAN 类型
  • 对应 本地接收的 DPO_RECEIVE 类型。

之所以 load-balancer 可能包含多个 dpo,也是为了兼容 ECMP 场景时,一个 prefix 下面有多条 path,也就对应多条 Adjacency

下图展示了从 Control-Plane 到 Data-Plane 的映射过程:

image