quagga源碼分析--通用庫command


quagga作為一個路由器軟件,自然要提供人機接口。

quagga提供snmp管理接口,而且,自然就會有對應的命令行管理格式,當然一般路由軟件不會提供界面形式的,也許有webui,然而quagga並沒有。

我們要看的就是這個命令行處理的代碼 command。

 

接觸過類似命令行的朋友肯定有一點點好奇吧,那么數量龐大的命令和參數輸入,還可以提供提示和自動補齊,這肯定不是一件很簡單的事情。

下面是一個配置示例:

1 !
2 interface bge0
3 ip ospf authentication message-digest
4 ip ospf message-digest-key 1 md5 ABCDEFGHIJK
5 !
6 router ospf
7 network 192.168.0.0/16 area 0.0.0.1
8 area 0.0.0.1 authentication message-digest

哦哦,看到這樣的命令,實在是頭疼。

 

嗯,不廢話了,我們還是看代碼吧,看command是怎么處理這令人頭疼的命令行吧:

 1 void cmd_init(int terminal) {
 2    ......
 3 
 4     cmdvec = vector_init(VECTOR_MIN_SIZE);
 5   
 6     /* Install top nodes. */
 7     install_node(&view_node, NULL);
 8     install_node(&enable_node, NULL);
 9 
10     /* Each node's basic commands. */
11     install_element(VIEW_NODE, &show_version_cmd);
12 
13     .....
14 }

 

這個就是命令行初始化的簡化版本。

quagg使用了非常常見的樹形列表來描述所有的命令, cmdvec包含所有的頂層命令節點,節點下面是當前節點的所包含的命令元素.

 1 struct cmd_node 
 2 {
 3   /* Node index. */
 4   enum node_type node;        
 5 
 6   /* Prompt character at vty interface. */
 7   const char *prompt;            
 8 
 9   /* Is this node's configuration goes to vtysh ? */
10   int vtysh;
11   
12   /* Node's configuration write function */
13   int (*func) (struct vty *);
14 
15   /* Vector of this node's command list. */
16   vector cmd_vector;    
17 };

 

上面已經舉過命令行的具體例子,解釋和執行命令行的函數如下:

1 extern vector cmd_make_strvec (const char *);
2 extern int cmd_execute_command (vector, struct vty *, struct cmd_element **, int);

通過查找匹配,找到對應的函數執行:

1 /* Execute matched command. */
2     return (*matched_element->func)(matched_element, vty, argc, argv);

執行的函數由如下的宏聲明:

 1 /* helper defines for end-user DEFUN* macros */
 2 #define DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \
 3   struct cmd_element cmdname = \
 4   { \
 5     .string = cmdstr, \
 6     .func = funcname, \
 7     .doc = helpstr, \
 8     .attr = attrs, \
 9     .daemon = dnum, \
10   };
11 
12 #define DEFUN_CMD_FUNC_DECL(funcname) \
13   static int funcname (struct cmd_element *, struct vty *, int, const char *[]);
14 
15 #define DEFUN_CMD_FUNC_TEXT(funcname) \
16   static int funcname \
17     (struct cmd_element *self __attribute__ ((unused)), \
18      struct vty *vty __attribute__ ((unused)), \
19      int argc __attribute__ ((unused)), \
20      const char *argv[] __attribute__ ((unused)) )
21 
22 #define DEFUN(funcname, cmdname, cmdstr, helpstr) \
23   DEFUN_CMD_FUNC_DECL(funcname) \
24   DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
25   DEFUN_CMD_FUNC_TEXT(funcname)

然后看一個具體命令行聲明:

 1 /* Configration from terminal */
 2 DEFUN(config_terminal,
 3       config_terminal_cmd,
 4       "configure terminal",
 5       "Configuration from vty interface\n"
 6       "Configuration terminal\n") {
 7     if (vty_config_lock(vty)) vty->node = CONFIG_NODE;
 8     else {
 9         vty_out(vty, "VTY configuration is locked by other VTY%s", VTY_NEWLINE);
10         return CMD_WARNING;
11     }
12     return CMD_SUCCESS;
13 }

這是進入配置模式的命令。

嗯,這個就看到這里吧!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM