ff_init函数详解

# ff_init函数详解

  • ff_init(int argc, char** argv)
    • 该函数完成f-stack的初始化工作
int ff_init(int argc, char * const argv[])
{
            int ret;
            /**
             * 1. 解析命令行参数
             * 2. 加载ini格式配置文件
             */
            ret = ff_load_config(argc, argv);
            if (ret < 0)
                exit(1);
            /**
             * 多进程框架下dpdk相关初始化
             */
            ret = ff_dpdk_init(dpdk_argc, (char **)&dpdk_argv);
            if (ret < 0)
                exit(1);
            /**
              * 初始化freebsd子系统,启动freebsd系统
              * 1. 设置kern.hz环境变量,更改freebsd系统的系统时钟
              * 2. 设置freebsd boot相关环境变量
              * 3. 设置freebsd系统物理内存大小,默认为256M
              * 4. 分配和初始化numa结构中per-cpu结构
              * 5. 初始化freebsd系统中0号进程
              * 6. 启动freebsd内存管理子系统
              * 7. freebsd同步机制初始化
              * 8. 启动freebsd系统
              * 9. 预留文件描述符
              * 10. 设置freebsd sysctl相关参数
              */
            ret = ff_freebsd_init();
            if (ret < 0)
                exit(1);
            /**
              *
              * 1.新建freebsd网络设备并加入freebsd内核中
              * 2.设置网络设备驱动相关函数指针
              * 3.将dpdk soft context与freebsd协议栈上下文关联
              */
            ret = ff_dpdk_if_up();
            if (ret < 0)
                exit(1);
            return 0;
}
  •  ff_load_config函数
 int ff_load_config(int argc, char *const argv[])
            {
                /**
                 * ff_global_cfg全局配置变量
                 * 初始化配置为默认值
                 */
                ff_default_config(&ff_global_cfg);
                /**
                 * 解析命令行参数相关配置
                 * 1. --conf|-c  指定配置文件
                 * 2. --proc-type|-t 指定当前进程类型,primary|secondary|auto
                 * 3. --proc-id|-p 指定当前进程使用lcore索引
                 */
                int ret = ff_parse_args(&ff_global_cfg, argc, argv);
                if (ret < 0) {
                    return ret;
                }
                /**
                 * 解析ini文件,初始化其余配置项
                 */
                ret = ini_parse(ff_global_cfg.filename, ini_parse_handler,
                    &ff_global_cfg);
                if (ret != 0) {
                    printf("parse %s failed on line %d\n", ff_global_cfg.filename, ret);
                    return -1;
                }
                /**
                 * 配置检查
                 * 1. kni选项检查,如果启用了kni选项,必须指定method参数
                 * 2. 检查port相关配置,必须包含addr、netmask、broadcast、gateway
                 * 3. 指定使用lcore有效性
                 * 4. 启用kni功能时,primary进程使用的lcore必须在启用port端口lcore_list中
                 */
                if (ff_check_config(&ff_global_cfg)) {
                    return -1;
                }
                /**
                 * 根据配置项设置dpdk eal层(Environment Abstraction Layer)初始化参数
                 */
                if (dpdk_args_setup(&ff_global_cfg) <= 0) {
                    return -1;
                }
                return 0;
            }
  •  ff_dpdk_init函数
    •  多进程框架下dpdk相关初始化
    1. 初始化eal
    2. 初始化lcore相应配置
    3. 初始化网卡收发包mbuf内存缓冲池
    4. 初始化网卡队列通信dispatch_ring数组
    5.  初始化与外部工具通信相关缓冲池(message_poll)和消息队列(msg_ring)
    6. kni模块初始化
int ff_dpdk_init(int argc, char **argv)
            {
                /**
                  *参数校验
                  */
                if (ff_global_cfg.dpdk.nb_procs < 1 ||
                    ff_global_cfg.dpdk.nb_procs > RTE_MAX_LCORE ||
                    ff_global_cfg.dpdk.proc_id >= ff_global_cfg.dpdk.nb_procs ||
                    ff_global_cfg.dpdk.proc_id < 0) {
                    printf("param num_procs[%d] or proc_id[%d] error!\n",
                        ff_global_cfg.dpdk.nb_procs,
                        ff_global_cfg.dpdk.proc_id);
                    exit(1);
                }
                /* dpdk eal初始化 */
                int ret = rte_eal_init(argc, argv);
                if (ret < 0) {
                    rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
                }
                numa_on = ff_global_cfg.dpdk.numa_on;
                idle_sleep = ff_global_cfg.dpdk.idle_sleep;
                /**
                  *初始化lcore相应配置
                  *1. 检查port有效性
                  *2. 检查enable lcore有效性
                  *3. numa启用时,设置lcore对应cpu所在socketid
                  *4. 设置当前lcore与需要处理网卡队列关系(port设置的lcore_list中每个lcore处理网卡的一个rx队列核一个tx队列)
                  */
                init_lcore_conf();
                /**
                  *初始化网卡收发包mbuf内存缓冲池
                  *1. 由primary进程分配
                  *2. 如果支持numa,则为numa中每个socket分配一个缓冲(局部性原理)
                  *3. 缓冲池名称为mbuf_pool_socketid
                  */
                init_mem_pool();
                /**
                  *初始化网卡队列通信dispatch_ring数组,,该数组主要用于当用户通过ff_regist_packet_dispatcher注册了自定义分发器后,在不同lcore之间分发接收到的数据包
                  *1. dispatch_ring为一二位数组,行数为启用port数目,列数为对应网卡启用队列数目
                  *2. 指针指向rte_ring结构
                  *3. ring名称为dispatch_ring_p#portid_q#queueid
                  *4. ring由primary进程分配
                  *5. ring为单消费者,多生产者
                  */
                init_dispatch_ring();
                /**
                  *初始化message_pool和msg_ring
                  *1. message_pool名称为ff_msg_pool
                  *2. 该ring主要用于ioctl等控制,供ifconfig等工具程序使用
                  *3. 由primary进程分配
                  *4. 每个lcore分配一对ring,一个用于IN,一个用于OUT
                  *5. ring名称为ff_msg_ring_in_#lcoreid、ff_msg_ring_out_#lcoreid
                  *6. ring为单生产者、单消费者
                  */
                init_msg_ring();
            #ifdef FF_KNI
                enable_kni = ff_global_cfg.kni.enable;
                if (enable_kni) {
                    init_kni();
                }
            #endif
            /**
              *配置网卡并启动网卡,该函数主要在primary进程中执行
              *1. 获取网卡配置
              *2. 设置网卡RX、TX队列配置
              *3. 设置RSS(receive side scaling)参数,如果开启多队列,则设置为对称RSS
              *4. 开启网卡混杂模式
              *5. 开启pcap模式
              *6. 检查所有启用网卡连接状态
              */
                ret = init_port_start();
                if (ret < 0) {
                    rte_exit(EXIT_FAILURE, "init_port_start failed\n");
                }
                /**
                  *初始化定时器相关
                  *1. 初始化dpdk定时器子系统
                  *2. 根据配置文件提供hz初始化定时器时钟频率
                  *3. 初始化freebsd协议栈使用定时器,设置回调函数
                  */
                init_clock();
                return 0;
            }
  • init_lcore_conf函数
    • lcore与对应处理的网卡队列关系图
  • init_kni函数
  1. 初始化kni模块

    

static int init_kni(void)
            {
                int nb_ports = rte_eth_dev_count();
                kni_accept = 0;
                if(strcasecmp(ff_global_cfg.kni.method, "accept") == 0)
                    kni_accept = 1;
                /**
                  *kni模块初始化
                  *1. primary完成用于存储kni子系统统计信息数组指针kni_stat,每个port对应一个kni_interface_stats结构
                  *2. primary完成kni子系统初始化
                  *3. 分配用于存储kni模块通信使用ring指针数组kni_rp,缓冲池名称为kni::ring_%d,每个port对应一个ring
                  *4. 根据配置文件初始化kni模块相关tcp/udp层端口位图,位图大小为8192*8
                  */
                ff_kni_init(nb_ports, ff_global_cfg.kni.tcp_port, ff_global_cfg.kni.udp_port);
                unsigned socket_id = lcore_conf.socket_id;
                /**
                  *关联kni模块使用mbuf缓冲池与当前进程proc lcore网卡收发包mbuf内存缓冲池在同一numa socket上
                  */
                struct rte_mempool *mbuf_pool = pktmbuf_pool[socket_id];
                nb_ports = ff_global_cfg.dpdk.nb_ports;
                int i, ret;
                for (i = 0; i < nb_ports; i++) {
                    uint16_t port_id = ff_global_cfg.dpdk.portid_list[i];
                    /**
                      *分配kni模块使用的数据结构,由primary进程分配,secondary进程获取即可
                      *1. 分配统计信息结构
                      *2. 为每个port分配对应的rte_kni结构
                      *3. 为kni模块通信使用ring分配空间
                      *4. ring为单消费者、多生产者
                      */
                    ff_kni_alloc(port_id, socket_id, mbuf_pool, KNI_QUEUE_SIZE);
                }
                return 0;
            }
  •  ff_dpdk_if_up函数

    

            int ff_dpdk_if_up(void)
            {
                int i;
                struct lcore_conf *qconf = &lcore_conf;
                /**
                 * 遍历所有的网卡port
                 */
                for (i = 0; i < qconf->nb_tx_port; i++) {
                    uint16_t port_id = qconf->tx_port_id[i];
                    /**
                     * 获取port对应配置
                     */
                    struct ff_port_cfg *pconf = &qconf->port_cfgs[port_id];
                    /**
                     * 1.新建freebsd网络设备并加入freebsd内核中
                     * 2.设置网络设备驱动相关函数指针
                     * 3.将dpdk soft context与freebsd协议栈上下文关联
                     */
                    veth_ctx[port_id] = ff_veth_attach(pconf);
                    if (veth_ctx[port_id] == NULL) {
                        rte_exit(EXIT_FAILURE, "ff_veth_attach failed");
                    }
                }
                return 0;
            }
  •  f-stackdpdk与freebsd协议栈关联图

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值