zoukankan      html  css  js  c++  java
  • DPDK KNI 接口2

    参考文献:

      DPDK官网

    ........................................................................................................................................

    一. DPDK KNI 作用

    DPDK Kernel NIC Interface(KNI)允许用户空间应用程序访问Linux *控制面。

    使用DPDK KNI的好处是:

    • 比现有的Linux TUN / TAP接口更快(通过消除系统调用和copy_to_user()/copy_from_user()操作)。
    • 允许使用标准Linux网络工具(如ethtool,ifconfig和tcpdump)管理DPDK端口。
    • 允许与内核网络堆栈的接口。

    使用DPDK内核NIC接口的应用程序的组件如图所示。

    Figure 21-1 Components of a DPDK KNI Application

     

    KNI内核可加载模块支持两种类型的设备:

    • 其他设备:
      • 创建网络设备(通过ioctl调用)。
      • 维护所有KNI实例共享的内核线程上下文(模拟网络驱动程序的RX端)。
      • 对于单内核线程模式,维护所有KNI实例共享的内核线程上下文(模拟网络驱动程序的RX端)。
      • 对于多个内核线程模式,为每个KNI实例(模拟新驱动程序的RX侧)维护一个内核线程上下文。

    网络设备:

    • 通过实现由struct net_device定义的诸如netdev_ops,header_ops,ethtool_ops之类的几个操作提供的Net功能,包括支持DPDK mbufs和FIFO。
    • 接口名称由用户空间提供。
    • MAC地址可以是真正的NIC MAC地址或随机

     

    DPDK缓冲区流  

    为了最小化在内核空间中运行的DPDK代码的数量,mbuf mempool仅在用户空间中进行管理。内核模块可以感知mbufs,但是所有mbuf分配和释放操作将仅由DPDK应用程序处理。

     

      • Figure 21-2 Packet Flow via mbufs in the DPDK KNI

    kni 源码讲解

     1     /* Initialise EAL */
     2     ret = rte_eal_init(argc, argv);
     3     if (ret < 0)
     4         rte_exit(EXIT_FAILURE, "Could not initialise EAL (%d)
    ", ret);
     5     argc -= ret;
     6     argv += ret;
     7 
     8     /* Parse application arguments (after the EAL ones) */
     9     ret = parse_args(argc, argv);
    10     if (ret < 0)
    11         rte_exit(EXIT_FAILURE, "Could not parse input parameters
    ");
    12 
    13     /* Create the mbuf pool */
    14     pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF,
    15         MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, rte_socket_id());
    16     if (pktmbuf_pool == NULL) {
    17         rte_exit(EXIT_FAILURE, "Could not initialise mbuf pool
    ");
    18         return -1;
    19     }
    20 
    21     /* Get number of ports found in scan */
    22     nb_sys_ports = rte_eth_dev_count_avail();
    23     if (nb_sys_ports == 0)
    24         rte_exit(EXIT_FAILURE, "No supported Ethernet device found
    ");
    25 
    26     /* Check if the configured port ID is valid */
    27     for (i = 0; i < RTE_MAX_ETHPORTS; i++)
    28         if (kni_port_params_array[i] && !rte_eth_dev_is_valid_port(i))
    29             rte_exit(EXIT_FAILURE, "Configured invalid "
    30                         "port ID %u
    ", i);
    31 
    32     /* Initialize KNI subsystem */
    33     init_kni();
    34 
    35     /* Initialise each port */
    36     RTE_ETH_FOREACH_DEV(port) {
    37         /* Skip ports that are not enabled */
    38         if (!(ports_mask & (1 << port)))
    39             continue;
    40         init_port(port);
    41 
    42         if (port >= RTE_MAX_ETHPORTS)
    43             rte_exit(EXIT_FAILURE, "Can not use more than "
    44                 "%d ports for kni
    ", RTE_MAX_ETHPORTS);
    45 
    46         kni_alloc(port);
    47     }
    48     check_all_ports_link_status(ports_mask);
    49 
    50     pid = getpid();
    51     RTE_LOG(INFO, APP, "========================
    ");
    52     RTE_LOG(INFO, APP, "KNI Running
    ");
    53     RTE_LOG(INFO, APP, "kill -SIGUSR1 %d
    ", pid);
    54     RTE_LOG(INFO, APP, "    Show KNI Statistics.
    ");
    55     RTE_LOG(INFO, APP, "kill -SIGUSR2 %d
    ", pid);
    56     RTE_LOG(INFO, APP, "    Zero KNI Statistics.
    ");
    57     RTE_LOG(INFO, APP, "========================
    ");
    58     fflush(stdout);
    59 
    60     ret = rte_ctrl_thread_create(&kni_link_tid,
    61                      "KNI link status check", NULL,
    62                      monitor_all_ports_link_status, NULL);
    63     if (ret < 0)
    64         rte_exit(EXIT_FAILURE,
    65             "Could not create link status thread!
    ");
    66 
    67     /* Launch per-lcore function on every lcore */
    68     rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER);
    69     RTE_LCORE_FOREACH_SLAVE(i) {
    70         if (rte_eal_wait_lcore(i) < 0)
    71             return -1;
    72     }
    73     monitor_links = 0;
    74     pthread_join(kni_link_tid, &retval);
    75 
    76     /* Release resources */
    77     RTE_ETH_FOREACH_DEV(port) {
    78         if (!(ports_mask & (1 << port)))
    79             continue;
    80         kni_free_kni(port);
    81     }
    82     for (i = 0; i < RTE_MAX_ETHPORTS; i++)
    83         if (kni_port_params_array[i]) {
    84             rte_free(kni_port_params_array[i]);
    85             kni_port_params_array[i] = NULL;
    86         }
    87 
    88     return 0;

    main 主要完成步骤:

      1.进行EAL层的初始化

      2.解析DPDK和应用层的参数

      3.分配报文的mempool,为接收报文做准备

      4.初始化以及启动接口

      5.启动各个核上的线程

  • 相关阅读:
    批量新增百万条数据 十百万条数据
    sqlserver 组内排序
    EF ++属性会更新实体
    Entity Framework Core: A second operation started on this context before a previous operation completed
    abp Cannot access a disposed object. A common cause of this error is disposing
    abp xunit Can not register IHostingEnvironment. It should be a non-abstract class. If not, it should be registered before.”
    hangfire enqueued but not processing(hangfire 定时任务入队列但不执行)
    EF 更新实体 The instance of entity type 'BabyEvent' cannot be tracked because another instance
    datatable to entiy list 不支持可空类型和枚举类型
    webapi 设置不显示接口到swaggerUI
  • 原文地址:https://www.cnblogs.com/mysky007/p/11219609.html
Copyright © 2011-2022 走看看