BGP协议建立起来后,后续的核心就是UPDATE路由,其关键的部分还是在路由的更新与撤销上面,这之间包含了繁杂的属性的处理过程。
我们知道,BGP发布路由时采用如下策略:
- 存在多条有效路由时,BGP Speaker只将最优路由发布给对等体。
- BGP Speaker从EBGP获得的路由会向它所有BGP对等体发布(包括EBGP对等体和IBGP对等体)。
- BGP Speaker从IBGP获得的路由不向它的IBGP对等体发布。
- BGP Speaker从IBGP获得的路由发布给它的EBGP对等体。
- 连接一旦建立,BGP Speaker将把自己所有BGP最优路由发布给新对等体。
我们先认识下BGP的 UPDATE消息,在展开代码的分析。
Update消息
Update消息的格式如下图所示,其作用是向对等体宣告一条可行的路由或者撤销多条不可行的路由或者两者。
路径属性包含以下几种:可能不是最新的。
有了上面的知识,让我们看一个真实的抓包:
普通的
MP_REACH_NLRI的抓包:
Update消息处理
根据前面FSM的分析我们知道IO线程FD可读以后,会执行bgp_process_reads处理可读的事件,bgp_read 读取FD的报文消息,TCP是stream如何保证读取的是完整的报文,没有可能读取一半??然后添加事件到主线程继续处理,主线程调用bgp_process_packet处理接收到的报文,其中处理update的消息的函数是bgp_update_receive。
这个函数很大,我们分阶段来分析:
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用于解析过程中的临时存储,解析完成后,用于后续的函数继续处理
struct attr 是BGP 所有属性attribute的统一的结构体,包含了前面描述的BGP的所有属性信息。
=======================================================================
首先解析报文里面是否携带了撤销路由,如果有则保存到nlris[NLRI_WITHDRAW]里面,并增加解析报文的长度+withdraw_len,然后继续解析路径属性
解析路径属性
bgp_attr_parse 处理解析各种属性值,像下面的报文Path Attributes有很多,所以while循环里面处理所有的属性信息。
先获取flag和type,然后根据flag里面是否有BGP_ATTR_FLAG_EXTLEN用于MP的扩展字段,如果有那么长度是2个字节,否则是一个字节
然后填充下面的结构体,以便后面继续处理,参数太多,写成一个结构体往下传递
然后根据属性的TYPE值,处理不同的属性,我们拿简单的BGP_ATTR_ORIGIN看下,其解析报文里面的origin值(1个字节),并赋值到attr里面,置位Flag |= BGP_ATTR_ORIGIN,attr是函数bgp_update_receive传下来的一个临时变量,后续会分析attr的处理。
我们在来看看AS_PATH的解析过程
存放的数据结构struct aspath
真正的AS号存放在assegment的as里面,type/length对应的是AS_PATH报文的内容,str是翻译为人可以读的内容比如100,400
assegments_parse根据报文解析并创建segments,然后aspath_hash_alloc创建新的aspath并hash加入全局的ashash的全局HASH表里面。
我们继续在看看next_hop的处理
其余的路径解析这里不再分析,等后面业务遇到的时候在继续分析。
当所有的路径属性解析完成后,需要做一次检查,检查所有的公知比尊的属性是否全部包含,否则是有问题的,返回错误
至此UPDATE报文里面的属性全部解析完成,存放在下图的attr的局部变量里面。