目录

1、加载kni驱动

2、kni初始化

3、运行


参考:dpdk之kni实现_dpdk kni

DPDK-KNI_加载

1、加载kni驱动

cd /root/dpdk-stable-19.08.2

./usertools/dpdk-setup.sh 然后执行45

插入kni驱动后可以看到如下文件

DPDK-KNI_协议栈_02

2、kni初始化

进程启动时执行:

rte_kni_init(参数)//该参数任意,用不到,可以填port id,然后执行:

static struct rte_kni *ng_alloc_kni(struct rte_mempool *mbuf_pool) {
	struct rte_kni *kni_handle = NULL;

	struct rte_kni_conf conf = {0};
	snprintf(conf.name, RTE_KNI_NAMESIZE, "vEth%d", gDpdkPortId);
	conf.group_id = gDpdkPortId;
	conf.mbuf_size = MAX_PACKET_SIZE;
	rte_memcpy(conf.mac_addr, gSrcMac, RTE_ETHER_ADDR_LEN);
	rte_eth_dev_get_mtu(gDpdkPortId, &conf.mtu);
	
	struct rte_kni_ops ops = {0};
	ops.port_id = gDpdkPortId;
	ops.config_network_if = ng_config_network_if;

	kni_handle = rte_kni_alloc(mbuf_pool, &conf, &ops);

	if (kni_handle == NULL) {
		rte_exit(EXIT_FAILURE, "Failed to create kni for port:%d\n", gDpdkPortId);
	}

	return kni_handle;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.

初始化完成后,运行程序可以看到,新增网卡,网卡名称在上述ng_alloc_kni中设置

如果网卡 处于down状态,需要ifconfig up,然后添加ip,ip和dpdk绑定的网卡ip相同

DPDK-KNI_协议栈_03

3、运行

1、kni回发报文给dpdk的三种方法(kni默认不回包给dpdk)

1.1)sudo echo 1 > /sys/devices/virtual/net/vEth0/carrier,这样内核收到dpdk的报文后才会回包。

1.2)起一个线程定时调用rte_kni_update_link函数,该函数也是设置上述内核参数

1.3)

DPDK-KNI_协议栈_04

2、对于dpdk不需要处理的报文送入内核协议栈:rte_kni_tx_burst(global_kni, &mbufs[i], 1);

注:rte_kni_tx_burst函数会对传入的mbufs[i]进行内存释放

3、rte_kni_handle_request

应用层操作的接口:rte_kni_handle_request; 该函数用于处理请求队列中的请求,因此这个函数需要周期性的执行,以免请求得不到处理,超时导致配置失败。可以放在定时任务或者主循环中调用。

注:每个kni设备本身,都有一个独占的发送队列、接收队列、分配队列、释放队列、请求队列、响应队列

rte_kni_tx_burst将mbuf存到接收队列kni->rx_q

4、dpdk读取内核协议栈回包,然后将报文送入网卡:

struct rte_mbuf *pkts_burst[BURST_SIZE];
		unsigned num_rx_recvd = rte_kni_rx_burst(global_kni, pkts_burst, BURST_SIZE);
		if (unlikely(num_rx_recvd > BURST_SIZE)) {
			printf("Error receiving from KNI\n");
			continue;
		}

		unsigned nb_tx = rte_eth_tx_burst(gDpdkPortId, 0, pkts_burst, (uint16_t)num_rx_recvd);
		//if (unlikely(nb_tx < num_rx_recvd)) {
		burst_free_mbufs(pkts_burst, num_rx_recvd);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

注:rte_kni_tx_burst和rte_kni_rx_burst没有将mbuf在内核态和用户态之间进行数据拷贝,它们共用同一个mbuf