zebra代碼簡單分析 --- 001

原文鏈接:https://blog.csdn.net/dadoneo/article/details/8685894

1) zebra是很有名的linux下的開源路由軟件項目,代碼寫的非常漂亮,模塊化,很清晰的結構。 關於軟件的框架部分就不說了,zebra 官方網站上已經有詳細的解釋了,簡單的來說:zebra作爲一個守護進程來維護linux路由信息,其他模塊rip, bgp 和這個守護進程通過消息通信來更新和獲取路由信息。

2) 項目主要是用到了RIP協議功能

3) 每一個模塊實際上是一個單進程的工作方式,在進程中,輪流執行thread塊,看上去是併發在運行;每一個模塊都有一個master結構,這個master結構維護了幾個thread list,有 event, read ,write等;當有需要的時候,每個thread塊結構加入到相應的list中去,進而在主進程會不斷的poll來執行list中的每一個thread塊

4) command list, 本質上是函數指針,關鍵性的代碼

#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
int funcname (struct cmd_element *, struct vty *, int, char **); \
struct cmd_element cmdname = \
{ \
cmdstr, \
funcname, \
helpstr \
}; \
int funcname \
(struct cmd_element *self, struct vty *vty, int argc, char **argv)

當讀取輸入的命令時,這個命令字符串可能來自於用戶輸入,也可能來自於配置文件,根據命令的字符串信息來匹配到相應的command list中的command node,每一個command node都會知道一個函數指針,調用這個函數就會執行相應的命令了

5)工作過程,首先zebra模塊啓動,其次啓動相應的路由協議模塊,我們啓動了RIP模塊;在啓動RIP模塊的時候指定了配置文件,配置文件的產生是根據當前設備的wan連接狀態產生了,例如

interface br0
router rip
redistribute kernel
redistribute connected
redistribute static
network br0
interface br0
ip rip send version 2
ip rip receive version 2
interface ipoa0
router rip
redistribute kernel
redistribute connected
redistribute static
network ipoa0
interface ipoa0
ip rip send version 2
ip rip receive version 2

顯然我們設備有一個br0的橋接的interface,還有一個ipoa0的wan連接,rip模塊在解析配置文件的時候會依次執行每一行,每一行實際上就是一條命令;

例如, “router rip”

對應到command list中的“router_rip”函數,代碼中它是如下定義的

DEFUN (router_rip,
       router_rip_cmd,
       "router rip",
       "Enable a routing process\n"
       "Routing Information Protocol (RIP)\n")

這個DEFUN的定義在以上已經提到了。那個函數做了什麼呢,其實很簡單實際上就是創建了socket,根據RIP協議的RFC文檔,它監聽了520端口;並且創建了兩個thread塊;

   rip_event ( RIP_READ, rip->sock );
   rip_event ( RIP_UPDATE_EVENT, 1 );

這兩個線程並沒有真正的創建,只是master的tread list中,這樣RIP進程會依次執行

  /* Execute each thread. */
  while (thread_fetch (master, &thread)) 
    thread_call (&thread);

6)和zebra模塊通信,當RIP執行redistribute kernel命令的時候實際上是給zebra發了一個消息,因爲最終的路由信息是zebra這個守護進程維護的,消息的格式是有定義的,

 int ret;
  struct stream *s;

  s = stream_new (ZEBRA_MAX_PACKET_SIZ);

  /* Total length of the messages. */
  stream_putw (s, 4);
  
  stream_putc (s, command);
  stream_putc (s, type);

  ret = writen (sock, s->data, 4);

  stream_free (s);

struct stream 就是消息的定義了。

實際上模塊間的通信方式可以是tcp/udp通信也是unix socket通信,這個是可以由宏定義了,搞清楚這些之後,剩下的就是對協議的理解,以及對linux網絡編程的掌握了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章