博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
kni
阅读量:4216 次
发布时间:2019-05-26

本文共 5053 字,大约阅读时间需要 16 分钟。

当dpdk不想在用户态实现协议栈的还,可以采用KNI 调用内核实现的协议栈kni分为用户态和内核态其内核态的入口为lib/librte_eal/linuxapp/kni/kni_misc.c中#可以看这是个标准的ko的实现,其入口函数是kni_initmodule_init(kni_init);static int __initkni_init(void){	int rc;	#检查kthread_mode 这个参数是否等于single 或者 multiple	if (kni_parse_kthread_mode() < 0) {		pr_err("Invalid parameter for kthread_mode\n");		return -EINVAL;	}	if (multiple_kthread_on == 0)		pr_debug("Single kernel thread for all KNI devices\n");	else		pr_debug("Multiple kernel thread mode enabled\n");	#注册一个网络子系统#ifdef HAVE_SIMPLIFIED_PERNET_OPERATIONS	rc = register_pernet_subsys(&kni_net_ops);#else	rc = register_pernet_gen_subsys(&kni_net_id, &kni_net_ops);#endif	if (rc)		return -EPERM;	#注册一个misc设备,这个misc 设备包含ioctl操作	rc = misc_register(&kni_misc);	if (rc != 0) {		pr_err("Misc registration failed\n");		goto out;	}	#根据输入参数配置lo mode	kni_net_config_lo_mode(lo_mode);	return 0;}这个模块可以接受的参数如下:MODULE_PARM_DESC(lo_mode,"KNI loopback mode (default=lo_mode_none):\n""    lo_mode_none        Kernel loopback disabled\n""    lo_mode_fifo        Enable kernel loopback with fifo\n""    lo_mode_fifo_skb    Enable kernel loopback with fifo and skb buffer\n""\n");module_param(kthread_mode, charp, S_IRUGO);MODULE_PARM_DESC(kthread_mode,"Kernel thread mode (default=single):\n""    single    Single kernel thread mode enabled.\n""    multiple  Multiple kernel thread mode enabled.\n""\n");可见可以配置lo mode和kthread_mode用户态可以参考example/kni/main.c中的写法intmain(int argc, char** argv){	int ret;	uint16_t nb_sys_ports, port;	unsigned i;	/* Associate signal_hanlder function with USR signals */	#注册下面四个信号量的处理函数为signal_handler	signal(SIGUSR1, signal_handler);	signal(SIGUSR2, signal_handler);	signal(SIGRTMIN, signal_handler);	signal(SIGINT, signal_handler);	/* Initialise EAL */	#初始化eal环境。	ret = rte_eal_init(argc, argv);	if (ret < 0)		rte_exit(EXIT_FAILURE, "Could not initialise EAL (%d)\n", ret);	argc -= ret;	argv += ret;	/* Parse application arguments (after the EAL ones) */	ret = parse_args(argc, argv);	if (ret < 0)		rte_exit(EXIT_FAILURE, "Could not parse input parameters\n");	/* Create the mbuf pool */	#创建pktmbuf_pool 	pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF,		MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, rte_socket_id());	if (pktmbuf_pool == NULL) {		rte_exit(EXIT_FAILURE, "Could not initialise mbuf pool\n");		return -1;	}	/* Get number of ports found in scan */	#得到网卡的port的个数	nb_sys_ports = rte_eth_dev_count();	if (nb_sys_ports == 0)		rte_exit(EXIT_FAILURE, "No supported Ethernet device found\n");	/* Check if the configured port ID is valid */	#检查这些网口id 是否有效	for (i = 0; i < RTE_MAX_ETHPORTS; i++)		if (kni_port_params_array[i] && i >= nb_sys_ports)			rte_exit(EXIT_FAILURE, "Configured invalid "						"port ID %u\n", i);	/* Initialize KNI subsystem */	#初始化KNI 子系统	init_kni();	#让每个核都运行main_loop	/* Launch per-lcore function on every lcore */	rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER);	RTE_LCORE_FOREACH_SLAVE(i) {		if (rte_eal_wait_lcore(i) < 0)			return -1;	}}具体的mail_loop实现如下:static intmain_loop(__rte_unused void *arg){	uint8_t i, nb_ports = rte_eth_dev_count();	int32_t f_stop;	const unsigned lcore_id = rte_lcore_id();	enum lcore_rxtx {		LCORE_NONE,		LCORE_RX,		LCORE_TX,		LCORE_MAX	};	enum lcore_rxtx flag = LCORE_NONE;	#具体是发送还是接受	for (i = 0; i < nb_ports; i++) {		if (!kni_port_params_array[i])			continue;		if (kni_port_params_array[i]->lcore_rx == (uint8_t)lcore_id) {			flag = LCORE_RX;			break;		} else if (kni_port_params_array[i]->lcore_tx ==						(uint8_t)lcore_id) {			flag = LCORE_TX;			break;		}	}	#给你讲flag决定是发送数据还是接受手机	if (flag == LCORE_RX) {		RTE_LOG(INFO, APP, "Lcore %u is reading from port %d\n",					kni_port_params_array[i]->lcore_rx,					kni_port_params_array[i]->port_id);		while (1) {			f_stop = rte_atomic32_read(&kni_stop);			if (f_stop)				break;			#循环接受数据			kni_ingress(kni_port_params_array[i]);		}	} else if (flag == LCORE_TX) {		RTE_LOG(INFO, APP, "Lcore %u is writing to port %d\n",					kni_port_params_array[i]->lcore_tx,					kni_port_params_array[i]->port_id);		while (1) {			f_stop = rte_atomic32_read(&kni_stop);			if (f_stop)				break;			#循环发送数据			kni_egress(kni_port_params_array[i]);		}	} else		RTE_LOG(INFO, APP, "Lcore %u has nothing to do\n", lcore_id);	return 0;}我们看看接受数据的情况static voidkni_ingress(struct kni_port_params *p){	uint8_t i;	uint16_t port_id;	unsigned nb_rx, num;	uint32_t nb_kni;	struct rte_mbuf *pkts_burst[PKT_BURST_SZ];	if (p == NULL)		return;	nb_kni = p->nb_kni;	port_id = p->port_id;	for (i = 0; i < nb_kni; i++) {		/* Burst rx from eth */		#首先从网口读数据到pkts_burst		nb_rx = rte_eth_rx_burst(port_id, 0, pkts_burst, PKT_BURST_SZ);		if (unlikely(nb_rx > PKT_BURST_SZ)) {			RTE_LOG(ERR, APP, "Error receiving from eth\n");			return;		}		/* Burst tx to kni */		#将pkts_burst中的数据督导kni中		num = rte_kni_tx_burst(p->kni[i], pkts_burst, nb_rx);		kni_stats[port_id].rx_packets += num;		rte_kni_handle_request(p->kni[i]);		if (unlikely(num < nb_rx)) {			/* Free mbufs not tx to kni interface */			kni_burst_free_mbufs(&pkts_burst[num], nb_rx - num);			kni_stats[port_id].rx_dropped += nb_rx - num;		}	}}

转载地址:http://hnnmi.baihongyu.com/

你可能感兴趣的文章
HBase - ROOT 和 META 表结构 (region定位原理)
查看>>
HBase API 和 基本操作
查看>>
Hbase的存储模型
查看>>
InfluxDB influxdbc.conf配置文件详解
查看>>
通过BulkLoad的方式快速导入海量数据
查看>>
Mysql根据内容查找在哪个表(Go版本)
查看>>
玩转Anaconda
查看>>
kali linux中文版安装
查看>>
安卓逆向之环境搭建
查看>>
修改包名实现app分身
查看>>
NDK静态注册之调用C层并返回字符串
查看>>
AndroidStudio踩坑记
查看>>
go-colly官方文档翻译(持续翻译中)
查看>>
adb禁用手机更新
查看>>
partition 函数使用练习
查看>>
set容器的并、交、差
查看>>
关于insert_iterator和inserter
查看>>
test
查看>>
关于拷贝构造函数
查看>>
深拷贝与浅拷贝
查看>>