zoukankan      html  css  js  c++  java
  • BCM 交换机开发

    转:http://blog.chinaunix.net/uid-23782786-id-3839602.html

    前言:
            最近搞这玩样,真是折腾,网上的资料都是片段,而且很少。折腾了4、5还没明白其整个的工作流程。眼看时间一天天地流失,内心哪个捉急啊!

            于是,豁出去了,从Makefile开始看。并且在源码中添加调用栈打印,终于搞明白了流程;
            现摘记出来供后来人参考。
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    前提: 
         芯片:bcm56142 
          
         编译:(kernel model) 
              1. cd system/linux/kernel/x86-generic-2_6/ 
              2. make 
               
              程序的连接使用的是 -static 选项,所以 nsl,m,c,pthread等库只能使用静态库(*.a),否则链接过程会提示找不到库 :
                       /usr/bin/ld: cannot find -lnsl 之类的错误。
               
          编译完成后,进行安装; 
              insmod   linux-kernel-bde.ko 
              insmod   linux-uk-proxy.ko 
              insmod   linux-bcm-diag-full.ko 
              mknod    /dev/linux-uk-proxy c 125 0 
               
    1. BCM配置命令操作? 
              我们在shell中执行  ./bcm.user.proxy,就启动了BCM的命令行用户界面。
                    这时候,用户就可以使用命令了,比如配置Vlan,端口使能等。 
               
    2. 当在开发新产品时,该怎么使用这个SDK呢? 
        当然了,如果不使用这个SDK也是可以的,直接操作设备文件,但是这个是有工作量,需要花时间的... 
         
        我们在执行了 ./bcm.user.proxy时,实际启动的是一个用户空间程序,
               对应文件 systems/linux/kernel/user/bcm-diag-proxy/bcm-diag-proxy.c里的main()函数。 

        main() 
        ( 
            1. 首先打开设备文件 /dev/linux-uk-proxy。 
            2. 启动一个读线程,用于从内核 _service_list(name "BCM DIAG SHELL")的sndqueue发送队列
               读取内核执行命令后的输出信息。 
            3. 当前进程则将用户输入定向到标准输入,如果用户输入了字符,则将其发送到
                内核_service_list(name "BCM DIAG SHELL")rcvqueue 接收队列
        ) 

        当我们在 BCM> 提示符下输入一条命令,比如 show pci 
                 命令"show pci"被传送到了内核_service_list(name "BCM DIAG SHELL")rcvqueue接收队列上。  

        那么show pci命令怎么被执行了呢? 
         
        回到前面的 insmod linux-bcm-diag-full.ko 
        当这个模块被插入内核时,其初始化函数会调用 _init() 
        /* systems/linux/kernel/modules/shared/gmodule.c */ 
        int __init init_module()   //内核模块加载函数,即insmod时会调用的函数,module_init()最终也是掉这个函数 
        {     
                _gmodule = gmodule_get(); 
            ...... 
            if(_gmodule->init) 
            { 
                  if((rc = _gmodule->init()) < 0) //调用 _init() 
                  { 
                  } 
            } 
        } 
         
        /* systems/linux/kernel/modules/bcm-diag-full/bcm-diag-full.c */ 
        _init() 
        { 
            最重要的活就是创建了一个处理shell命令的内核线程:_bcm_shell() 
        } 
         
        /* systems/linux/kernel/modules/bcm-diag-full/bcm-diag-full.c */ 
        _bcm_shell() 
        { 
            调用函数 diag_shell(),这个就是最重要的函数了。 
        } 
         
        /* src/appl/diag/system.c */ 
        diag_shell() 
        { 
            diag_init();    // 这个没啥好说的,自己看代码,初始化了一些链表,并打印BCM相关信息 
            sysconf_init();  
            sysconf_probe();//这里去探测系统中存在的BCM家族的芯片,主要是通过读PCI配置空间的ID 
            sysconf_attach(); //这里就是将探测到的设备对应的函数安装到对应的钩子上 
            while(1) 
            { 
                sh_process(-1, "BCM", TRUE);  //这个东东就一直轮询用户的输入,并执行用户的命令了。 
            } 
        } 
         
        /* src/appl/diag/shell.c */ 
        sh_process() 
        { 
            while(1) 
            { 
                sal_readline(); //关注一下这个函数,这个函数就是
                                      //             去从内核_service_list(name "BCM DIAG SHELL")rcvqueue接收队列上取用户的命令 
            } 
             
          ...... 
          if( cur_mode == BCMX_CMD_MODE ) 
              sh_process_command();     //看到没,这时候才是真正的去执行用户输入的命令了。 
        } 
         
       /* src/sal/appl/io.c */ 
       sal_readline() 
       { 
               sal_console_gets();     
       } 
        
       /* src/sal/appl/linux/console.c */ 
       sal_console_gets() 
       { 
               tty_gets(); 
       } 
        
       /* systems/linux/kernel/modules/bcm-diag-full/bcm-diag-full.c */ 
       tty_gets() 
       { 
               while(!(rc >= 0)) 
               { 
                     rc=linux_uk_proxy_recv();    //直接从内核_service_list(name "BCM DIAG SHELL")rcvqueue队列上
                                                                 // 取用户的命令 
               } 
       } 
        
        
       /* systems/linux/kernel/modules/uk-proxy/linux-uk-proxy.c */ 
       linux_uk_proxy_recv() 
       {     
           return _list_op(&s->recv_q.data, &s->recv_q.free, data, len, _LIST_OP_F_GET | _LIST_OP_F_KERN); 
       } 
        
       从以上分析可以看出,linux-bcm-diag-full.ko 是很重要的模块,用于接口用户的,执行bcm 命令。 
         
    写这篇文档,一是记录下,日后自己再做BCM的开发,可以省时省力些;二来给像我一样刚接触BCM开发的后来者以参考,少走弯路。 
    当然,要向了解所有的,最好还是看下他的makefile工程,虽然可能会花上一两天时间,但是对你看代码很有帮助的, 
    因为代码里好多一样的文件名和函数名,不看Makefile你不知道调哪个了. 
     
    对于开发BCM应用: 
    1. 你可以修改 bcm-diag-proxy.c的main线程,将其的输入重定向一个文件,然后你懂的... 
    2. 直接操作 /dev/linux-uk-proxy文件(open,ioctl,对应内核的模块linux-uk-proxy.c 中的_ioctl)
     
  • 相关阅读:
    洛谷P3886 [JLOI2009]神秘的生物(插头dp)
    Leetcode 842 将数组拆分成斐波那契序列
    Leetcode 08.07 无重复字符串的排列组合
    Leetcode131 分割回文串
    Leetcode 516 最长回文子序列
    Leetcode08.12 N皇后
    Leetcode 813 最大平均值和分组
    Leetcode 79 单词搜索 二维平面上的回溯
    题解 洛谷 P4694 【[PA2013]Raper】
    跳表的基本认识
  • 原文地址:https://www.cnblogs.com/newjiang/p/9169193.html
Copyright © 2011-2022 走看看