zebra在设计命令格式的时候,将命令节点Node和命令Command分开,整个命令结构是一个树状的,如图:

NODEn表示命令节点,CMDn表示具体的命令。在zebra的整个命令行设计当中,zebra用向量的概念将命令和节点连接起来,建立起隶属关系。一个全局向量CMDVEC,指向整个命令结构,CMDVEC的每一个索引值都是一个具体的命令节点(如果有的话);在每个命令节点的结构中又存在各自的向量cmd_vector,该向量将指向隶属于该节点的命令,cmd_vector中的每个索引值都是一个具体的命令(如果注册的话)。于是,从最初的CMDVEC向量开始,程序就能“顺藤摸瓜“找到任何一个已经注册的命令。比如,程序调用某个方法,该方法对应的命令是CMD1,而该命令的调用是在NODEn这个节点下,那么自然而然,程序就能锁定CMDVEC—>NODEn—>CMD1,实现一条匹配。

命令的注册过程

zebra要成功注册一个命令,需要以下几个步骤:1> 安装一个节点。如果不需要新的命令节点,而使用zebra中自带的节点,可省去这个步骤;2> 写一条命令的实现;3> 将一条实现了的命令安装到命令节点下。

介绍之前,有必要说明一下和命令相关的数据结构。

向量

1 /* struct for vector */
2 struct _vector
3 {
4   unsigned int max;                         /* max number of used slot */
5   unsigned int alloced;                     /* number of allocated slot */
6   void **index;                             /* index to data */
7 };

在zebra.h中定义,表示一个向量结构。该结构中,max表示目前使用的最大slot,alloced表示已经分配给该向量的最大slot数,max <= alloced。Index通过索引方式,存储value。

命令节点

 1 /* Node which has some commands and prompt string and configuration function pointer . */2 3 struct cmd_node 5 {7   /* Node index. */9   enum node_type node;
11   /* Prompt character at vty interface. */
13   char *prompt;
17   /* Is this node's configuration goes to vtysh ? */
19   int vtysh;
23   /* Node's configuration write function */
25   int (*func) (struct vty *);
29   /* Vector of this node's command list. */
31   vector cmd_vector;
33 };

该结构在command.h中定义,用来表示一个命令节点,节点的类型由node_type枚举指出,节点的标识字符由prompt表示,func表示该节点对应的操作方法,该节点下的命令由vector定义的cmd_vector表示。例如,在全局配置模式下,命令节点的定义可以是:

 1 struct cmd_node config_node =3 {5   CONFIG_NODE,7   "%s(config)# ",9   1
11 };

命令

此外,command.h中还有一个重要的结构,就是cmd_element结构,该结构定义了一条命令的全部信息,定义如下:

 1 /* Structure of command element. */3 struct cmd_element 5 {7   char *string;                                          /* Command specification by string. */9   int (*func) (struct cmd_element *, struct vty *, int, char **);
11   char *doc;                                              /* Documentation of this command. */
13   int daemon;                                   /* Daemon to which this command belong. */
15   vector strvec;                                          /* Pointing out each description vector. */
17   int cmdsize;                                             /* Command index count. */
19   char *config;                                            /* Configuration string */
21   vector subconfig;                                    /* Sub configuration string */
23 };

string 描述了命令的实现串,比如我要显示某个配置信息:“show where are you 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的73行定义:

 1 struct cmd_node tsihang_node =3 {5   TSIHANG_NODE,7   "%s(tsihang)# ",9   1
11 };

将TSIHANG_NODE添加到node_type的CONFIG_NODE之后。然后在command.c的3115行,使用install_node将这个节点安装到cmdvec中:install_node (&tsihang_node, NULL);

写一条命令的实现方法

zebra实现命令的方法由command.h中的一个宏来实现

 1 /* DEFUN for vty command interafce. */3 #define DEFUN(funcname, cmdname, cmdstr, helpstr) \5   int funcname (struct cmd_element *, struct vty *, int, char **); \7   struct cmd_element cmdname = \9   { \
11     cmdstr, \
13     funcname, \
15     helpstr \
17   }; \
19   int funcname \
21   (struct cmd_element *self, struct vty *vty, int argc, char **argv)

这个宏很有意思,它表明了一个命令的结构,命令描述,命令的解释,和命令的具体实现方法。编辑command.c文件,照着样子写一条命令实现方法。

例如,我实现的一个简单方法:

 1 DEFUN (tsihang_hello, 3        tsihang_hello_cmd, 5        "tsihang say hello",7        "Greet\n"9        "Greet to someone\n")
11 {
13    vty_out (vty, "Hello,you can do like this %s", VTY_NEWLINE);
15    return CMD_SUCCESS;
17 }

但是这样还是不够的,要进入tsihang_node节点还得靠一个触发命令

 1 //add by Tsihang for test cmmand3 /* Tsihang command */ 5 DEFUN (tsihang_enable, 7        tsihang_enable_cmd,9        "tsihang",
11        "Turn on privileged mode command\n")
13 {
15     vty->node = TSIHANG_NODE;
17   return CMD_SUCCESS;
19 }

安装命令

命令的安装实质是将一个cmd_element结构,存储到cmd_node结构中的成员cmd_vec向量的一个未被使用的slot里。

调用接口

/* Install a command into a node. */void install_element (enum node_type ntype, struct cmd_element *cmd) ,

将刚才写好的命令安装到定义的节点下

在command.c中3192行添加

/* 为了进入自定义节点,需要安装触发命令 */

install_element(ENABLE_NODE, &tsihang_enable_cmd);install_element(TSIHANG_NODE, &tsihang_hello_cmd); 

编译,运行

编译在我的博客:http://www.cnblogs.com/iTsihang/archive/2012/11/22/2783249.html  中有介绍。

编译完成后,进入zebra目录,执行./zebra&,然后远程登录 telnet 127.0.0.1 2061 端口,zebra的密码都在zebra.conf文件中,登录后可使用。

进到tsihang节点下,运行命令:

1 Router(tsihang)#tsihang say hello
3 Hello, you can do like this
5 Router(tsihang)#

本测试例子下载:http://files.cnblogs.com/iTsihang/zebra-0.95a-t.tar.zip

zebra的命令存储原理及使用方法相关推荐

  1. 开源路由软件zebra的命令存储原理及使用方法

    ZZ FROM: http://www.cnblogs.com/iTsihang/archive/2012/12/05/2783252.html =========================== ...

  2. ARP***原理及解决方法与CMD命令分类(1)

    ARP***原理及解决方法与CMD命令分类 ARP***原理及解决方法与CMD命令 [故障原因] 局域网内有人使用ARP欺骗的***程序(比如:传奇盗号的软件,某些传奇外挂中也被恶意加载了此程序). ...

  3. Redis源码-String:Redis String命令、Redis String存储原理、Redis String三种编码类型、Redis字符串SDS源码解析、Redis String应用场景

    Redis源码-String:Redis String命令.Redis String存储原理.Redis String三种编码类型.Redis字符串SDS源码解析.Redis String应用场景 R ...

  4. Redis源码-ZSet:Redis ZSet存储原理、Redis ZSet命令、 Redis ZSet两种存储底层编码ziplist/dict+skiplist、Redis ZSet应用场景

    Redis源码-ZSet:Redis ZSet存储原理.Redis ZSet命令. Redis ZSet两种存储底层编码ziplist/dict+skiplist.Redis ZSet应用场景 Red ...

  5. 基于闪存存储原理的U盘数据安全测试和U盘数据保护软件

    第一章 摘要 Flash Memory是一种长寿命的非易失性存储介质,其存储原理存在诸多漏洞.其中最为严重的则为写入次数上限.而以闪存作为存储介质的U盘是否会因闪存的存储缺陷而成为不安全的存储设备,这 ...

  6. minio对象存储原理_使用MinIO在本地运行S3对象存储

    minio对象存储原理 Object storage is amazingly versatile. We normally associate it with AWS S3, but Object ...

  7. 并发编程之二:线程创建方法、运行原理、常见方法(sleep,join,interrupt,park,守护线程等)

    线程创建方法.运行原理.常见方法 线程的创建方法 继承Thread 实现Runnable FutureTask 线程的运行原理 栈与栈帧 线程运行情况 线程的上下文切换(Thread Context ...

  8. Clickhouse的数据存储原理、二进制文件内容分析与索引详解

    Clickhouse的数据存储原理.二进制文件内容分析与索引详解 Clickhouse以其强大的性能著称,已经被越来越多的使用在OLAP分析查询等场景中.Clickhouse是一个列式存储的数据库,而 ...

  9. FastDFS合并存储原理分析

    FastDFS合并存储原理分析 基于FastDFS 5.03/5.04 2014-12-03 一.合并存储简介 在处理海量小文件问题上,文件系统处理性能会受到显著的影响,在读写次数与吞吐量这两个指标上 ...

  10. MongoDB GridFS 存储原理

    https://blog.csdn.net/jiangtianjiao/article/details/89349154 http://rdc.hundsun.com/portal/article/7 ...

最新文章

  1. 醉没醉,带上智能手机走两步就知道
  2. tuple(元组)备注
  3. 用扫描的方式实现Rosenfeld and Pfaltz提出的距离变换!
  4. Android wear
  5. [k8s]elk架构设计-k8s集群里搭建
  6. 用计算机写文章教学课件,计算机教学课件
  7. 2019牛客暑期多校训练营(第五场)
  8. Vue 页面如何监听用户预览时间
  9. html5 怎么实现展开文字,html5实现滚动文字
  10. ip的增删改查以及网络设定
  11. python装饰器-简易版
  12. python机器学习库keras——线性回归、逻辑回归、一般逻辑回归
  13. 计算机考研408考试科目及备考指南
  14. 量子力学原理-波恩的概率论
  15. 用python写邮件和附件自动生成发送系统
  16. 我的2019全年目标
  17. u盘如何安装2003服务器系统,怎么用u盘安装2003系统安装教程
  18. 张晓龙2018微信公开课
  19. PDF编辑技巧之PDF页面旋转
  20. 小程序源码:喝酒娱乐小游戏助力神器-多玩法安装简单

热门文章

  1. 逆向project第003篇:跨越CM4验证机制的鸿沟(上)
  2. 第五章 多个消费者监听同一个队列
  3. 【转】请求处理机制其二:Django中间件的解析
  4. 中文的习题解答中国人看懂, 英文的习题解答外国人能看懂
  5. asp.net 母版页使用详解--转
  6. 业务层应该返回DataSet/DataTable,还是对象/对象集合?
  7. WCF 第五章 行为
  8. 01.自定义View(ArcView弧形进度条)
  9. inux系统磁盘管理基础知识及总结
  10. 【Win 10应用开发】分阶段进行数据绑定