BGP的核心就是交換路由,所以關鍵的部分還是在路由的更新與撤銷上面,這之間包含了繁雜的屬性,community等等可以稱之為業務邏輯的處理過程,不做詳述。
bgp_read函數是路由更新的事件處理函數,在收到BGP_MSG_UPDATE消息的時候開始調用bgp_update_receive函數處理。
1 switch (i) { 2 case NLRI_UPDATE: 3 case NLRI_MP_UPDATE: 4 nlri_ret = bgp_nlri_parse(peer, NLRI_ATTR_ARG, &nlris[i]); 5 break; 6 case NLRI_WITHDRAW: 7 case NLRI_MP_WITHDRAW: 8 nlri_ret = bgp_nlri_parse(peer, NULL, &nlris[i]); 9 }
上面是更新路由與撤銷路由。比如在cli輸入clear ip bgp 命令的時候會撤銷路由。
nlri是(network layer reachable infomation)的縮寫。
在bgp_nlri_parse里對bgp UPDATE消息內容進行處理,遍歷消息內容里的全部路由前綴,開始bgp_update調用。
1 /* Normal process. */ 2 if (attr) 3 ret = bgp_update(peer, &p, attr, packet->afi, packet->safi, 4 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0); 5 else 6 ret = bgp_withdraw(peer, &p, attr, packet->afi, packet->safi, 7 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL);
在bgp_update中對本節點以及所有的鄰居的路由信息都進行更新,主要的更新是在bgp_process函數里。
1 switch (bgp_node_table(rn)->type) { 2 case BGP_TABLE_MAIN: 3 work_queue_add(bm->process_main_queue, pqnode); 4 break; 5 case BGP_TABLE_RSCLIENT: 6 work_queue_add(bm->process_rsclient_queue, pqnode); 7 break; 8 }
可以看到,最后都是在工作隊列里進行更新。對應初始化的時候設置的工作函數:
1 bm->process_main_queue->spec.workfunc = &bgp_process_main; 2 bm->process_main_queue->spec.del_item_data = &bgp_processq_del; 3 bm->process_main_queue->spec.max_retries = 0; 4 bm->process_main_queue->spec.hold = 50; 5 6 bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient; 7 bm->process_rsclient_queue->spec.del_item_data = &bgp_processq_del; 8 bm->process_rsclient_queue->spec.max_retries = 0; 9 bm->process_rsclient_queue->spec.hold = 50;
對本節點(即服務端),在bgp_process_main里最終發送給了zserv。
1 zapi_ipv4_route(ZEBRA_IPV4_ROUTE_ADD, zclient, (struct prefix_ipv4 *)p, &api);
對於鄰居(即通過neighbor命令配置的),在bgp_process_rsclient中分別如下處理
如果是添加或者更新,則添加到fifo隊列中:
1 /* Add new advertisement to advertisement attribute list. */ 2 bgp_advertise_add(adv->baa, adv); 3 4 FIFO_ADD(&peer->sync[afi][safi]->update, &adv->fifo);
如果是撤銷路由,則:
1 /* Add to synchronization entry for withdraw announcement. */ 2 FIFO_ADD(&peer->sync[afi][safi]->withdraw, &adv->fifo); 3 4 /* Schedule packet write. */ 5 BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd);
都是在thread任務調度的bgp_write的事件中處理。