BGP协议建立起来后,后续的核心就是UPDATE路由,其关键的部分还是在路由的更新与撤销上面,这之间包含了繁杂的属性的处理过程。

我们知道,BGP发布路由时采用如下策略:

  1. 存在多条有效路由时,BGP Speaker只将最优路由发布给对等体。
  2. BGP Speaker从EBGP获得的路由会向它所有BGP对等体发布(包括EBGP对等体和IBGP对等体)。
  3. BGP Speaker从IBGP获得的路由不向它的IBGP对等体发布。
  4. BGP Speaker从IBGP获得的路由发布给它的EBGP对等体。
  5. 连接一旦建立,BGP Speaker将把自己所有BGP最优路由发布给新对等体。

我们先认识下BGP的 UPDATE消息,在展开代码的分析。

Update消息

Update消息的格式如下图所示,其作用是向对等体宣告一条可行的路由或者撤销多条不可行的路由或者两者。

bgp 路由update更新 bgp更新路由的方式_抓包

bgp 路由update更新 bgp更新路由的方式_主线程_02

bgp 路由update更新 bgp更新路由的方式_数据结构_03

 

路径属性包含以下几种:可能不是最新的。

 

bgp 路由update更新 bgp更新路由的方式_bgp 路由update更新_04

有了上面的知识,让我们看一个真实的抓包:

普通的

bgp 路由update更新 bgp更新路由的方式_bgp 路由update更新_05

MP_REACH_NLRI的抓包:

bgp 路由update更新 bgp更新路由的方式_抓包_06

Update消息处理

根据前面FSM的分析我们知道IO线程FD可读以后,会执行bgp_process_reads处理可读的事件,bgp_read 读取FD的报文消息,TCP是stream如何保证读取的是完整的报文,没有可能读取一半??然后添加事件到主线程继续处理,主线程调用bgp_process_packet处理接收到的报文,其中处理update的消息的函数是bgp_update_receive。

bgp 路由update更新 bgp更新路由的方式_数据结构_07

这个函数很大,我们分阶段来分析:

bgp 路由update更新 bgp更新路由的方式_数据结构_08

BGP 把 NLRI 分为4种,nlri是(network layer reachable infomation)的缩写:

        NLRI_UPDATE       NLRI_WITHDRAW

        NLRI_MP_UPDATE    NLRI_MP_WITHDRAW

MP是Multiprotocol BGP 多协议BGP的简写,上面的代码引申出BGP新的两个数据结构:

bgp_nlri用于解析过程中的临时存储,解析完成后,用于后续的函数继续处理

bgp 路由update更新 bgp更新路由的方式_bgp 路由update更新_09

struct attr 是BGP 所有属性attribute的统一的结构体,包含了前面描述的BGP的所有属性信息。

bgp 路由update更新 bgp更新路由的方式_数据结构_10

=======================================================================

bgp 路由update更新 bgp更新路由的方式_bgp 路由update更新_11

首先解析报文里面是否携带了撤销路由,如果有则保存到nlris[NLRI_WITHDRAW]里面,并增加解析报文的长度+withdraw_len,然后继续解析路径属性

解析路径属性

bgp 路由update更新 bgp更新路由的方式_数据结构_12

bgp_attr_parse 处理解析各种属性值,像下面的报文Path Attributes有很多,所以while循环里面处理所有的属性信息。

bgp 路由update更新 bgp更新路由的方式_数据结构_13

bgp 路由update更新 bgp更新路由的方式_抓包_14

先获取flag和type,然后根据flag里面是否有BGP_ATTR_FLAG_EXTLEN用于MP的扩展字段,如果有那么长度是2个字节,否则是一个字节

bgp 路由update更新 bgp更新路由的方式_数据结构_15

然后填充下面的结构体,以便后面继续处理,参数太多,写成一个结构体往下传递

bgp 路由update更新 bgp更新路由的方式_bgp 路由update更新_16

bgp 路由update更新 bgp更新路由的方式_数据结构_17

然后根据属性的TYPE值,处理不同的属性,我们拿简单的BGP_ATTR_ORIGIN看下,其解析报文里面的origin值(1个字节),并赋值到attr里面,置位Flag |= BGP_ATTR_ORIGIN,attr是函数bgp_update_receive传下来的一个临时变量,后续会分析attr的处理。

bgp 路由update更新 bgp更新路由的方式_抓包_18

bgp 路由update更新 bgp更新路由的方式_抓包_19

我们在来看看AS_PATH的解析过程

bgp 路由update更新 bgp更新路由的方式_主线程_20

存放的数据结构struct aspath

bgp 路由update更新 bgp更新路由的方式_抓包_21

真正的AS号存放在assegment的as里面,type/length对应的是AS_PATH报文的内容,str是翻译为人可以读的内容比如100,400

bgp 路由update更新 bgp更新路由的方式_bgp 路由update更新_22

bgp 路由update更新 bgp更新路由的方式_数据结构_23

assegments_parse根据报文解析并创建segments,然后aspath_hash_alloc创建新的aspath并hash加入全局的ashash的全局HASH表里面。

我们继续在看看next_hop的处理

 

其余的路径解析这里不再分析,等后面业务遇到的时候在继续分析。

当所有的路径属性解析完成后,需要做一次检查,检查所有的公知比尊的属性是否全部包含,否则是有问题的,返回错误

bgp 路由update更新 bgp更新路由的方式_抓包_24

至此UPDATE报文里面的属性全部解析完成,存放在下图的attr的局部变量里面。

bgp 路由update更新 bgp更新路由的方式_抓包_25