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 }
這是進入配置模式的命令。
嗯,這個就看到這里吧!