zebra在设计命令格式时,将命令节点NODE和命令COMMAND分开,整个命令结构是一个树状,如图
NODEn表示命令节点,CMDn表示具体命令,在zebra的整个命令行设计当中,zebra用向量的概念将命令和节点连接起来,一个全局向量CMDVEC,指向整个命令结构,CMDVEC的每个索引值都是一个具体的命令节点,在每个命令节点的结构中又存在各自的命令向量cmdvector,该向量指向隶属于该节点的命令,cmd_vector终端额每个索引值都是一个具体的命令。程序索引顺序为CMDVEC->NODEn->CMD1。
命令的注册过程
zebra要成功注册一个命令,需要以下几个步骤:
(1)安装一个新节点(如无需安装可省略这步)
(2)写一条命令的实现
(3)将一条命令挂到节点下
/* struct for vector */
struct vector
{
unsigned int max; /* max number of used slot */
unsigned int alloced; /* number of allocated slot */
void **index; /* index to data */
};
在zebra.h中定义,表示一个向量结构,在该结构中,max表示目前使用的最大slot,alloced 表示被分配到的slot,max<=alloced,index通过索引方式。存储value.
命令节点
struct cmd_node
{
/*node inedx*/
enum node_type node;
char *prompt;
int vtysh; /*is this node's configuration goes to vtysh?*/
int (*func)(struct vty *);
vector cmd_vecotr;
};
该结构在command.h中定义,用来表示一个命令节点,节点的类型由node_type枚举指出,节点的标识字符由prompt表示,func表示该节点对应的操作方法。该节点下的命令由vector定义的cmd_voctor表示,例如,在全局配置模式下,命令节点的定义可以是:
struct cmd_node config_node=
{
CONFIG_NODE,
"%s(config)#",
1
};
此外,command.h中还定义了一个重要的结构,就是cmd_element结构,该结构定义了一条命令的全部信息,定义如下
struct cmd_element
{
char *string; //command specification by string
int (*func)(struct cmd_element*,struct vty *,int ,char **);
char *doc; //documentation of this command;
int daemon;
vector strvec; //pointing out each description vector
int cmdsize; //command index count;
char *config; //configuration string
vector subconfig;
}
string描述了命令的实现串,比如我们要显示摸个配置信息“show where you are from”;
func 是实现string的具体方法;doc是string的解释,zebra将string和doc解析存储,由strvec这个向量指向。下面我们逐步使用zebra。
安装一个命令节点
zebra中安装一个命令节点的接口:void install_node(struct cmd_node *node, int (*func)(struct vty*))
我们知道。整个zebra的框架是由一个向量指向一个节点,该节点又存在另一个向量,这个向量又有自己的存储结构。从而将整个zebra的命令连接起来,祈祷提纲挈领的作用。zebra中由vector定义了一个全局向量,名为cmdvec,也就是上文中说的CMDVEC。命令节点的实质是将一个cmd_node结构的地址。存储到cmdvec中一个未被使用的slot-index[i]里。
你可以将自己的命令安装在zebra原带的节点下,也可以添加自己新的节点,我以我的名字命名了一个新的节点。在command.c中定义:
struct cmd_node menger_node=
{
MENGER_NODE,
"%s(menger)# ",
1
};
将MENGER_NODE添加到node_type中,然后用install_node将这个节点安装到cmdvec中,install_node(&menger_node,NULL);
写一条命令的实现方法
zebtas实现命令的方法由command.h中的一个宏来实现
/*DEFUN for vty command interface*/
#define DEFUN(funcname,cmdname,cmdstr,helpstr)\
int funcname(struct cmd_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.c文件,照着样子写一条命令实现方法。
例如我实现的一个简单方法:
DEFUN(menger_hello, menger_hello_cmd, "menger say hello", "greet\n" "greet to someone\n") { vty_out(vty,"hello,you can do like this %s",VTY_NEWLINE); return CMD_SUCCESS; }
但是这样子还不够,要进入menger_node节点还得靠一个触发命令
DEGUN(menger_enable, menger_enable_cmd, "menger", "turn on privileged mode command\n") { vty->node=MENGER_NODE; return CMD_SUCESS; }
安装命令
命令安装的实质是将一个cmd_element结构存储到cmd_node结构中的成员cmd_vec向量的一个未被使用的slot里。
调用接口:void install_element(enum node_type, struct cmd_element *cmd);
将刚才写好的命令安装到定义的节点下,在command.c中添加;
/*为了进入自定义节点,需要安装触发节点*/
install_element(ENABLE_NODE,&menger_enable_cmd);
install_element(MENGER_NODE,&menger_hello_cmd);
【本博客 http://www.cnblogs.com/iTsihang 中原创之博文,版权属作者所有,欢迎转载。转载之时请保留本段内容,否则作者将保留追究版权之权利】