FRR BGP 协议分析 5 -- 路由更新(2)

处理NLRI

获取NLRI的报文长度,填入nlris[NLRI_UPDATE],到现在为止nlris里面的4种类型(如果有的话),已经全部填写到nlris数组结构体里面

然后我们遍历这个数组,处理里面所有的NLRI的类型,本次先分析NLRI_UPDATE,MP后面再分析。

根据前面解析出来的SAFI选取不同的处理函数,afi/safi定义如下:

AFI_IP 的组合定义如下:

IP + UNICAST

普通的IP 单播路由处理

IP + MULTICAST

组播路由??

IP + MPLS_VPN

MPLS VPN 路由的处理

IP + ENCAP

??目前不太清楚

IP + EVPN

?? 还是L2VPN + EVPN ??

IP + LABELED_UNICAST

BGP的标签分发的路由处理

IP + FLOWSPEC

BGP FLOWSPEC的处理

 

 

可以从下面的函数查看组合:

IP + UNICAST/ MULTICAST走的是下面的函数,NLRI里面存放的是前缀,为了方便,把报文也放到下面:

这里又引出BGP的一个数据结构struct prefix

在每次的for循环里面,需要填充好prefix前缀里面的长度、family、前缀值,然后以便后续bgp_update函数继续处理。

bgp_update 引申出struct bgp_node的数据结构,是BGP 存放路由的关键数据结构,我们先认识下,使用关键字prefix组织成radix树

struct bgp_path_info 存放在bgp_node的void *info里面,这个数据结构的意义是什么??

bgp_afi_node_get在bgp对应的afi/safi table里面使用prefix前缀,获取struct bgp_node节点,并加入afi/safi table的二叉树里面。

如果需要记录adj_in,那么把当前的信息存入bgp_adj_in结构体,然后link到bgp_node的链表上面。

然后会进行AS_PATH的防环检查,

attr_new = bgp_attr_intern(&new_attr); 会根据前面解析的attr(局部变量传下来的),申请一个attr_new,以便后续保存。

info_make 会创建一个新的struct bgp_path_info数据结构,attr_new 便保存在里面的,后续会在给bgp_path_info赋值。

函数bgp_path_info_add 会把新的bgp_path_info,连接到bgp_node里面。

bgp_maximum_prefix_overflow 会检查BGP Max Prefix条目限制

bgp_process 会把rn入队work_queue,后续work_queue注册的回调函数bgp_process_wq,会出队继续处理rn,而work_queue是在初始化的时候,就已经初始化好了

这里的work_queue和linux内核的work queue是异曲同工之妙。

WORK_QUEUE 后续处理

work queue的回调函数bgp_process_wq出队queue继续处理,bgp_process_main_one 处理具体的queue node,即bgp route_node的信息,这里提个问题,单线程处理的bgpd,为何这里需要在异步下work_queue继续处理??

 

 

bgp_process_main_one 会根据BGP的选路原则选择一个最优的路由,选择原则如下:

https://i-blog.csdnimg.cn/blog_migrate/96cab4497ef4c00dd115d810cbf06d17.png

 然后group_announce_route发布路由,会遍历bgp->update_groups的HASH表,执行回调函数update_group_walkcb,最后会调到函数group_announce_route_walkcb

而这里涉及到的结构体struct update_group/ struct update_subgroup是在bgp_establish的时候调用update_group_adjust_peer_afs创建的

    /* assign update-group/subgroup */

    update_group_adjust_peer_afs(peer);

回到group_announce_route_walkcb函数,遍历group下的subgroup,然后得到struct bgp_path_info和bgp_node,调用函数subgroup_process_announce_selected,最后调用bgp_adj_out_set_subgroup 加入sync->update表,等待定时器更新发送,但此时传入定时器的时间为0,所以应该是一个实时的时间,此时相当于又异步了一次。

事件执行会调用bgp_generate_updgrp_packets,然后调用subgroup_update_packet,里面封装发送的UPDATE报文,bgp_packet_attribute封装属性,报文封装好后,调用bpacket_reformat_for_peer修正下报文的nexthop,然后调用bgp_packet_add把报文加入到peer的obuf里面,然后调用bgp_writes_on(peer),等fd可写的时候,IO线程会把UPDATE报文发送出去。

到此我们分析了接受到UPDATE消息,然后在BGP 路由表里面添加了路由,并且发送出去的全部过程,涉及的路径很长,细节很大,只有后面再慢慢体会。

而这个BGP 路由下发到ZEBRA和linux内核的过程同样很长,后面再继续分析。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值