ZBLOG

dpdk的kni使用例子,给出代码并注释

下面是一个DPDK KNI(Kernel NIC Interface)的使用例子,该代码会创建一个KNI设备,并通过KNI设备发送和接收数据包。

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <inttypes.h>
#include <errno.h>
#include <sys/queue.h>

#include "rte_common.h"
#include "rte_ethdev.h"
#include "rte_ether.h"
#include "rte_ip.h"
#include "rte_kni.h"

#define MAX_PACKET_SZ 1024

static volatile bool force_quit;
static struct rte_kni *kni;

static void signal_handler(int signum)
{
    if (signum == SIGINT || signum == SIGTERM)
        force_quit = true;
}

/* display usage */
static void kni_usage(const char *prgname)
{
    printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n"
           "  -p PORTMASK: hexadecimal bitmask of ports to configure\n",
           prgname);
}

/* create a new KNI device */
static int kni_create(uint8_t port_id, struct rte_mempool *mbuf_pool,
                      uint16_t mbuf_sz, const char *if_name)
{
    struct rte_kni_conf conf;
    struct rte_eth_dev_info dev_info;
    struct rte_pci_device *pci_dev = NULL;
    int ret;

    /* allocate the PCI device for the given port ID */
    pci_dev = RTE_ETH_DEV_TO_PCI(rte_eth_devices[port_id]);

    /* set up the KNI configuration structure */
    memset(&conf, 0, sizeof(conf));
    snprintf(conf.name, RTE_KNI_NAMESIZE, "%s", if_name);
    conf.group_id = (uint16_t)port_id;
    conf.mbuf_size = (uint16_t)mbuf_sz;
    conf.addr = pci_dev->mem_resource[0].addr;
    conf.id = pci_dev->id;

    /* create the KNI device */
    kni = rte_kni_alloc(mbuf_pool, &conf);
    if (!kni) {
        printf("Failed to create KNI device for port %u\n", port_id);
        return -ENOMEM;
    }

    /* set the promiscuous mode for the associated Ethernet device */
    ret = rte_eth_promiscuous_enable(port_id);
    if (ret != 0) {
        printf("Failed to enable promiscuous mode for port %u\n", port_id);
        return ret;
    }

    /* get information about the associated Ethernet device */
    memset(&dev_info, 0, sizeof(dev_info));
    rte_eth_dev_info_get(port_id, &dev_info);

    /* enable RX and TX for the associated Ethernet device */
    ret = rte_eth_dev_start(port_id);
    if (ret != 0) {
        printf("Failed to start port %u\n", port_id);
        return ret;
   }

   return 0;
}

/* send a packet through the KNI device */
static int kni_send(struct rte_mbuf *pkt)
{
   uint16_t nb_tx;

   nb_tx = rte_kni_tx_burst(kni, &pkt, 1);

   if (nb_tx == 0)
       rte_pktmbuf_free(pkt);

   return nb_tx ? 0 : -ENOSPC;
}

/* receive packets from the KNI interface */
static void kni_receive(void)
{
   struct rte_mbuf *pkts[MAX_PACKET_SZ];
   uint16_t nb_rx;

   while (!force_quit) {
       nb_rx = rte_kni_rx_burst(kni, pkts, MAX_PACKET_SZ);
       if (nb_rx == 0)
           continue;

       for (uint16_t i = 0; i < nb_rx; i++)
           rte_pktmbuf_free(pkts[i]);
   }
}

int main(int argc, char **argv)
{
    int ret;
    uint8_t port_id;
    uint32_t port_mask = 0;
    const char *prgname = argv[0];
    struct rte_mempool *mbuf_pool = NULL;

    /* initialize the EAL */
    ret = rte_eal_init(argc, argv);
    if (ret < 0) {
        printf("Failed to initialize EAL: %s\n", strerror(errno));
        return -1;
    }

    argc -= ret;
    argv += ret;

   /* parse application arguments */
   ret = 0;
   for (; argc > 0; argc--, argv++) {
       if (strcmp(*argv, "-p") == 0) {
           /* parse hexadecimal bitmask of ports to configure */
           ret = sscanf(*(++argv), "%" SCNx32, &port_mask);
           if (ret != 1)
               kni_usage(prgname);
           else if (!port_mask)
               kni_usage(prgname);
       } else {
           kni_usage(prgname);
       }
   }

   /* create a memory pool for packet buffers */
   mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS,
                                       MBUF_CACHE_SIZE, 0,
                                       RTE_MBUF_DEFAULT_BUF_SIZE,
                                       rte_socket_id());
   if (!mbuf_pool) {
       printf("Failed to create packet buffer memory pool\n");
       return -ENOMEM;
   }

   /* iterate over all enabled ports and create KNI devices */
   RTE_ETH_FOREACH_DEV(port_id) {
      if (!(port_mask & (1 << port_id)))
          continue;

      ret = kni_create(port_id, mbuf_pool, RTE_MBUF_DEFAULT_BUF_SIZE,
                       "eth%d");
      if (ret != 0) {
          printf("Failed to create KNI device for port %u\n", port_id);
          return ret;
      }
   }

   /* set up signal handlers */
   signal(SIGINT, signal_handler);
   signal(SIGTERM, signal_handler);

   /* start receiving packets from the KNI interface */
   kni_receive();

   /* free the KNI device and exit */
   rte_kni_release(kni);
   return 0;
}

注释如下:

  • kni_create():创建KNI设备并设置相关配置,其中包括名称、group ID、MBUF大小等;
  • kni_send():通过KNI设备发送数据包;
  • kni_receive():接收从KNI设备上发来的数据包,并释放这些数据包。


    内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=1574

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?