Pktgen CLI样例程序

来源:互联网 发布:linux epoll wait 编辑:程序博客网 时间:2024/06/05 03:46
Pktgen CLI样例程序
    之前介绍了pktgen的命令使用,已经pktgen命令的组织,即目录的组织结构,具体是怎么实现的,后期再看代码
    目前,我们怎么在这个目录结构中,添加自己的命令呢?
    这就是Pktgen的CLI command line interface命令行接口
    这节介绍pktgen的命令行接口,以及与CLI相关的概念,和CLI的一个样例程序
    
    
    
    CLI是command line interface的简写
    CLI样例程序是DPDK的一部分(其实不是),CLI很像DPDK的cmdline库,拥有相似的
    编程接口和编程模型
    
    CLI的主要目的是让开发者只用少量的代码和配置也能快速的创建命令
    使用开发者熟悉的类Unix系统结构
    允许开发者为应用和部署开发许多的命令
    
    CLI被设计成了目录结构,而不是单层的命令行接口
    CLI允许开发者使用目录风格的解决方案去控制DPDK应用程序
    目录风格的设计不是什么新鲜的,但是他有很多优点
    
    其中一个优点是目录路径对于命令来说可以成为命令的一部分
    另一个优点就是使用目录结构可以创建分层的命令
    而且开发者还可以动态的添加删除命令
    
    CLI还有一下几个优点:
        CLI没有全局变量,除了唯一一个线程变量this_cli, this_cli只能被创建CLI实例的线程访问
        CLI支持命令,文件,别名,目录
            变量的别名就是用一个简单的字符串替换别的命令,就像shell的alias
            文件可以是静态或则动态的信息,可以在线进行修改,保存。
            文件支持简单的回调函数让开发者更新其中的内容
        如果开发者需要,可以添加支持彩色和鼠标
        CLI就像DPDK的cmdline库,在程序用两者都是可以使用的
        为命令和文件使用一个简单的,伪造的,像目录一样的布局。命令可以分层,而且命令的路径
    可以用来作为具体的目标的标识,而不需要在命令行上声明它(意思就是,路径可以区分命令)
        命令能够自动补全,就像shell的命令行一样
        命令回调函数很简单,就像普通的 argc/argv函数一样
            CLI不会为开发者转换参数,需要开发者来对argv进行解码
            当前的命令行,很多的参数转换是很难用的,或则不符合开发的要求,仅仅只是摘取了字符串的
            类型,而且没有进行转换(好像是说,别动东西不好用,我这东西好用)
        可以动态的添加删除命令,目录,文件和别名,不需要静态的编译到应用程序(MD命令删除倒是可以,不知道怎么添加)
        没有变态的数据结构,可以将testpmd的代码行数从12K优化到4.5K,可以为testpmd支持
        CMDLINE和CLI,而且是使用相同的命令行选项(估计一个是DPDK自带的,一个是PKTGEN的)
        提供两种解析命令行参数的方法,第一种是标准的argc/argv函数
            第二种方法是使用一种字符串集合映射就像printf格式一样,检测出用户输入的命令行
            一个ID值将会被返回,用来指示那个映射的字符串被查找到了,然后让命令行能够
            使用switch语句
        使用env命令或则API可以支持环境变量
        可以提供关键的帮助
        这翻译,没谁了,理解大概意思就行,之后看代码,一看就明白的
        
概述
    CLI样例程序是一个简单的应用,示范了如何在DPDK中使用命令行接口,这个应用程序是按行读取的,
    以此来控制DPDK程序。
    
    CLI基于命令行的好处是动态的,意思是,节点或则条目可以在线添加删除
    允许添加一个新的目录,文件或命令,或则删除他们
    CLI没有全局可修改的变量,除了一个全局指针是一个基于线程的变量
    它允许开发者在一个线程中有多个CLI命令
    
    另一个优点是使用开发者熟悉的后台函数来处理命令,而且是基于argc/argv的,开发者
    能够获取整个命令行。
    
    还有一个优点是使用MAP结构,用来识别命令;
    允许开发定义新版本的命令,而且能通过简单的ID值识别这些新版本的命令
    
    最后一个优点是CLI添加目录,文件和命令非常简单。
    基本的概念就是使用标准的Unix设计(anything is file?)
    MD,一个发包程序,这么高端,不亏是开源项目啊。
    为了添加一个命令,开发者需要添加一个项到cli_tree_t的结构,而且需要创建一个
    函数,使用下面的原型
    int user_cmd(int argc, char **argv);
    
    argc/argv 就像标准unix系统那样使用。(比如咋们的a.out)
    可以使用getopt()函数进行解析,还有别的都可以
    命令行结构和文本转换是在编译的时候定义的。
    在CLI处理时,argc/argv需要进行传递,进行转换
    The cli variable being a thread Local Storage (TLS) all user routines
    a CLI routine only need to access the thread variable to
    eliminate needing a global variable to reference the specific
    CLI instance and passing the value in the API
    所有用户的处理线路的CLI变量是基于线程本地存储的,每个CLI线路只需要访问本
    线程的变量,以此来消除全局变量需要关联到特定的CLI实例,通过API进行
    传递(可恶:大概就是全局变量使用需要API麻烦,用本地变量)
    
    用户可以设置环境变量通过env命令,这些变量也在命令行中进行了解析,直接替换完成
    
    
    CLI系统也支持简单的文件通过像alias命令一样。如果用户有更多的参数,
    则将这些参数附加到别名字符串上,并像在命令行上输入一样进行处理。
    
    CLI样例程序支持一些CMDLINE库的特性,比如
    补全,剪切/粘贴,和一些其它的特殊功能,是配置和debug faster and easier
    
    CLI设计使用了一些非常简单的VT100控制字符串用来显示数据和接收输入
    一些控制字符串用来clear屏幕或则行,定位光标,在VT100支持的终端上
    CLI屏幕代码也支持基本的颜色和许多其他的VT100命令

    这个应用程序也展示了怎么扩展,来处理用户输出的命令
        
    这个样例程序有一个简单的命令提示,DPDK-cli:/> 就像unix shell命令
        
    CLI有一些默认的命令:
        ls: list the current or provided directory files/commands.
        cd: Change directory command.
        pwd: print out the current working directory.
        history: List the current command line history if enabled.
        more: A simple command to page contents of files.
        help: display a the help screen.
        quit: exit the CLI application, also Ctrl-x will exit as well.
        mkdir: add a directory to the current directory.
        delay: wait for a given number of microseconds.
        sleep: wait for a given number of seconds.
        rm: remove a directory, file or command. Removing a file will delete the data.
        cls: clear the screen and redisplay the prompt.
        version: Display the current DPDK version being used.
        path: display the current search path for executable commands.
        cmap: Display the current system core and socket information.
        hugepages: Display the current hugepage information.
        sizes: a collection system structure and buffer sizes for debugging.
        copyright: a file containing DPDK copyright information.
        env: a command show/set/modify the environment variables.

        Some example commands under /bin directory are:

        ll: an alias command to display long ls listing ls -l
        h: alias command for history
        hello: a simple Hello World! command.
        show: has a number of commands using the map feature.

        Under the /data directory is:

        pci: a simple example file for displaying the lspci command in CLI.

自动补全
    The CLI auto completion works similar to the standard Unix* system
    by expanding commands and directory paths
    
特殊命令
    ! 和shell 一样
    @  使用Linux系统命令


编译这个程序
    1. Go to example directory:
    export RTE_SDK=/path/to/rte_sdk
    cd ${RTE_SDK}/examples/cli

    1. Set the target (a default target is used if not specified). For example:
    export RTE_TARGET=x86_64-native-linuxapp-gcc
    
    1.Build the application:
    make
    
解释:
    后面的章节为这些代码提供了一些解释
    
EAL Initialization and cmdline Start

cli_start(): 一直运行,直到Ctrl+x 或 输入quit

cli_create(): 需要四个参数,如果没提供,每个参数都有默认值
int cli_create(cli_prompt_t prompt_func, cli_tree_t tree_func,
                    int nb_entries, uint32_t nb_hist);

cli_create_with_tree(): 会调用cli_create(),用了其中的三个默认参数
int cli_create_with_tree(cli_tree_t tree)
{
    return cli_create(NULL, tree, CLI_DEFAULT_NODES, CLI_DEFAULT_HIST_LINES);
}

int
main(int argc, char **argv)
{
    if (cli_create_with_tree(init_tree) ==0) {
        cli_start(NULL, 0); /* NULL is some init message done only once */
                            /* 0 means do not use color themes */
        cli_destroy();
    }
    ...
}
                    
The tree init routine is defined like:
static struct cli_tree my_tree[] = {
    c_dir("/data"),
    c_file("pci", pci_file, "display lspci information"),
    c_dir("/bin"),
    c_cmd("hello", hello_cmd, "Hello-World!!"),
    c_alias("h", "history", "display history commands"),
    c_alias("ll", "ls -l", "long directory listing alias"),
    c_end()
};

static int
init_tree(void)
{
    /*
     * Root is created already and using system default cmds and dirs, the
     * developer is not required to use the system default cmds/dirs.
     */
    if (cli_default_tree_init())
        return -1;

        /* Using NULL here to start at root directory */
    if (cli_add_tree(NULL, my_tree))
        return -1;

        cli_help_add("Show", show_map, show_help);

        return cli_add_bin_path("/bin");
}

上面的结构用来创建树结构体,cli_tree可以用来创建一个新的目录树

可以使用这些宏定义: c_dir, c_file, c_cmd, c_alias and c_end

用户可以创建自己需要的命令,通过cli_default_tree_init() 可以得到默认命令
如果开发者不想调用默认命令函数,那么必须调用cli_create_root()先,在添加
其他节点之前。其余的都是动态的了。
——————————————————————————————————————————————————————————————————————————————
上面的代码都是老版本的了,最后一个要求也是。但具有参考价值哈。。。。

新代码附上

不上了,source insight 不能复制粘贴?

我是3.3.3版本的
->main()
    -> pktgen_cli_create()
        -> cli_create(my_prompt, init_tree)
            ->my_prompt()
            ->cli_create_root()
            ->init_tree()
                ->cli_default_tree_init()
                ->cli_add_tree()
                ->cli_help_add()
                ->cli_add_bin_path()

到这里,基本就能添加自己的命令了。照猫画虎

添加修改命令很容易,关键是这个命令行架构怎么做的?
原创粉丝点击