代码部分
整个L3fwd有三千多行代码,但总体思想就是在L2fwd的基础上,增加网络层的根据 IP 地址进行路由查找的内容。
main.c 文件
int
main(int argc, char **argv)
{
/*......*/
/* init EAL */
ret = rte_eal_init(argc, argv);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n");
/*......*/
/* parse application arguments (after the EAL ones) */
// 解析命令行参数
ret = parse_args(argc, argv);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n");
// 检查 lcore 配置数组的正确性
if (check_lcore_params() < 0)
rte_exit(EXIT_FAILURE, "check_lcore_params failed\n");
// 检查 rx 队列数是否过多,把 param 的东西放到 conf 里
ret = init_lcore_rx_queues();
if (ret < 0)
rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n");
nb_ports = rte_eth_dev_count(); // 获取以太网端口数量
if (check_port_config() < 0) // 验证 port 掩码、 port id 的正确性
rte_exit(EXIT_FAILURE, "check_port_config failed\n");
nb_lcores = rte_lcore_count(); // 获取 lcore 数量
/* Setup function pointers for lookup method. */
setup_l3fwd_lookup_tables();// 设定是 Exact 还是 LPM
/* initialize all ports */
// 初始化端口
RTE_ETH_FOREACH_DEV(portid) {
/*......*/
ret = rte_eth_dev_configure(portid, nb_rx_queue,
(uint16_t)n_tx_queue, &local_port_conf);
// 配置以太网设备,rx 队列数量根据 param 数组来,tx 数量则是和 lcore 数量相同
/* init memory */
// 分配内存,设置 LPM 或 Hash 表
ret = init_mem(NB_MBUF);
if (ret < 0)
rte_exit(EXIT_FAILURE, "init_mem failed\n");
/* init one TX queue per couple (lcore,port) */
// 设置 Tx queue,每个端口只设置一条
queueid = 0;
for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
/*......*/
ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,
socketid, txconf);
/*......*/
}
printf("\n");
}
for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
/*......*/
// 配置 Rx 队列,每个端口上设置多条。
for(queue = 0; queue < qconf->n_rx_queue; ++queue) {
/*......*/
rte_eth_dev_info_get(portid, &dev_info);
/*......*/
ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd,
socketid,
&rxq_conf,
pktmbuf_pool[socketid]);
/*......*/
}
}
printf("\n");
/* start ports */
// 启用设备
RTE_ETH_FOREACH_DEV(portid) {
/*......*/
/* Start device */
ret = rte_eth_dev_start(portid);
/*......*/
if (promiscuous_on) // 设置混杂模式
rte_eth_promiscuous_enable(portid);
}
/*......*/
}
}
// 检查链路状态
check_all_ports_link_status(enabled_port_mask);
ret = 0;
/* launch per-lcore init on every lcore */
// 在每个lcore上执行函数,包括master lcore,根据选定的 LPM 还是 exact 执行对应的 main_loop 函数
rte_eal_mp_remote_launch(l3fwd_lkp.main_loop, NULL, CALL_MASTER);
RTE_LCORE_FOREACH_SLAVE(lcore_id) {
if (rte_eal_wait_lcore(lcore_id) < 0) {
ret = -1;
break;
}
}
/* stop ports */
RTE_ETH_FOREACH_DEV(portid) {
if ((enabled_port_mask & (1 << portid)) == 0)
continue;
printf("Closing port %d...", portid);
rte_eth_dev_stop(portid);
rte_eth_dev_clo