

































./l2fwd [EAL options]---p PORTMASK [-q NQ]--[no-]mac-updating-c 3-n 2-c 表示的是整个程序会使用哪些核例如:-c f 表示 20+21+22+23 ---p 3-q 1 ./l2fwd -c3 -n2 ---p 3-q 1intmain(int argc,char**argv){struct lcore_queue_conf *qconf;struct rte_eth_dev_info dev_info;int ret;uint8_t nb_ports;uint8_t nb_ports_available;uint8_t portid, last_port;unsigned lcore_id, rx_lcore_id;unsigned nb_ports_in_mask =0;/* init EAL */ ret = rte_eal_init(argc, argv); //EAL的初使化。if(ret <0) rte_exit(EXIT_FAILURE,"Invalid EAL arguments\n"); argc -= ret; argv += ret; force_quit =false; signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler);/* parse application arguments (after the EAL ones) */ ret = l2fwd_parse_args(argc, argv);//这里是解析后面的---p 3-q 1 参数,用于获得这些参数的值。if(ret <0) rte_exit(EXIT_FAILURE,"Invalid L2FWD arguments\n");/* convert to number of cycles */ timer_period *= rte_get_timer_hz();/* create the mbuf pool */ l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, MEMPOOL_CACHE_SIZE,0, RTE_MBUF_DEFAULT_BUF_SIZE, //创建内存池, rte_socket_id());if(l2fwd_pktmbuf_pool == NULL) rte_exit(EXIT_FAILURE,"Cannot init mbuf pool\n"); nb_ports = rte_eth_dev_count(); //获得当初可用的最大网口数,是从PCI中获得的。if(nb_ports ==0) rte_exit(EXIT_FAILURE,"No Ethernet ports - bye\n");/* reset l2fwd_dst_ports */for(portid =0; portid < RTE_MAX_ETHPORTS; portid++) l2fwd_dst_ports[portid]=0; last_port =0;/* * Each logical core is assigned a dedicated TX queue on each port. */for(portid =0; portid < nb_ports; portid++){ //这里其实就是确定每个网口的发包对象。如网口0的报文传给网口1,。。。。这里就是初使化一个数组。/* skip ports that are not enabled */if((l2fwd_enabled_port_mask &(1<< portid))==0)continue;if(nb_ports_in_mask %2){ l2fwd_dst_ports[portid]= last_port; l2fwd_dst_ports[last_port]= portid;}else last_port = portid; nb_ports_in_mask++; rte_eth_dev_info_get(portid,&dev_info);}if(nb_ports_in_mask %2){ printf("Notice: odd number of ports in portmask.\n"); l2fwd_dst_ports[last_port]= last_port;} rx_lcore_id =0; qconf = NULL;/* Initialize the port/queue configuration of each logical core */for(portid =0; portid < nb_ports; portid++){//给每一个网口分配一个可用的,你配置过的逻辑核 /* skip ports that are not enabled */if((l2fwd_enabled_port_mask &(1<< portid))==0)continue;/* get the lcore_id for this port */while(rte_lcore_is_enabled(rx_lcore_id)==0|| lcore_queue_conf[rx_lcore_id].n_rx_port == l2fwd_rx_queue_per_lcore){ rx_lcore_id++;if(rx_lcore_id >= RTE_MAX_LCORE) rte_exit(EXIT_FAILURE,"Not enough cores\n");}if(qconf !=&lcore_queue_conf[rx_lcore_id])/* Assigned a new logical core in the loop above. */ qconf =&lcore_queue_conf[rx_lcore_id]; qconf->rx_port_list[qconf->n_rx_port]= portid; qconf->n_rx_port++; printf("Lcore %u: RX port %u\n", rx_lcore_id,(unsigned) portid);} nb_ports_available = nb_ports;/* Initialise each port */for(portid =0; portid < nb_ports; portid++){//就是初使化网口,给每个网口分配接收的缓存,分配接收和发送的队列。/* skip ports that are not enabled */if((l2fwd_enabled_port_mask &(1<< portid))==0){ printf("Skipping disabled port %u\n",(unsigned) portid); nb_ports_available--;continue;}/* init port */ printf("Initializing port %u... ",(unsigned) portid); fflush(stdout); ret = rte_eth_dev_configure(portid,1,1,&port_conf);//设置portid这个网口一个接收和一个发送的队列。if(ret <0) rte_exit(EXIT_FAILURE,"Cannot configure device: err=%d, port=%u\n", ret,(unsigned) portid); rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]);/* init one RX queue */ fflush(stdout); ret = rte_eth_rx_queue_setup(portid,0, nb_rxd, //给对应的网口分配接收队列。 rte_eth_dev_socket_id(portid), NULL, l2fwd_pktmbuf_pool);if(ret <0) rte_exit(EXIT_FAILURE,"rte_eth_rx_queue_setup:err=%d, port=%u\n", ret,(unsigned) portid);/* init one TX queue on each port */ fflush(stdout); ret = rte_eth_tx_queue_setup(portid,0, nb_txd,//给对应的网口分配发送队列。 rte_eth_dev_socket_id(portid), NULL);if(ret <0) rte_exit(EXIT_FAILURE,"rte_eth_tx_queue_setup:err=%d, port=%u\n", ret,(unsigned) portid);/* Initialize TX buffers */ tx_buffer[portid]= rte_zmalloc_socket("tx_buffer",//分配接收缓存空间,就是收包的缓存。 RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST),0, rte_eth_dev_socket_id(portid));if(tx_buffer[portid]== NULL) rte_exit(EXIT_FAILURE,"Cannot allocate buffer for tx on port %u\n",(unsigned) portid); rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST); ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid],//当报文发送失败后要调用的回调函数 rte_eth_tx_buffer_count_callback,&port_statistics[portid].dropped);if(ret <0) rte_exit(EXIT_FAILURE,"Cannot set error callback for ""tx buffer on port %u\n",(unsigned) portid);/* Start device */ ret = rte_eth_dev_start(portid);if(ret <0) rte_exit(EXIT_FAILURE,"rte_eth_dev_start:err=%d, port=%u\n", ret,(unsigned) portid); printf("done: \n"); rte_eth_promiscuous_enable(portid);//设置该网口为混杂模式,就是接收所有的报文。 printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",//初使化报文统计(unsigned) portid, l2fwd_ports_eth_addr[portid].addr_bytes[0], l2fwd_ports_eth_addr[portid].addr_bytes[1], l2fwd_ports_eth_addr[portid].addr_bytes[2], l2fwd_ports_eth_addr[portid].addr_bytes[3], l2fwd_ports_eth_addr[portid].addr_bytes[4], l2fwd_ports_eth_addr[portid].addr_bytes[5]);/* initialize port stats */ memset(&port_statistics,0,sizeof(port_statistics));}if(!nb_ports_available){ rte_exit(EXIT_FAILURE,"All available ports are disabled. Please set portmask.\n");} check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask);//检查这些网口是否可以用。 ret =0;/* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, NULL, CALL_MASTER);//在所有的逻辑核(包括管理核,一般DPDK会默认将第一个可用的逻辑核当管理核)上执行l2fwd_launch_one_lcore这个函数。 RTE_LCORE_FOREACH_SLAVE(lcore_id){if(rte_eal_wait_lcore(lcore_id)<0){//等待从逻辑核的结束。 ret =-1;break;}}for(portid =0; portid < nb_ports; portid++){ //down掉网口,结束。if((l2fwd_enabled_port_mask &(1<< portid))==0)continue; printf("Closing port %d...", portid); rte_eth_dev_stop(portid); rte_eth_dev_close(portid); printf(" Done\n");} printf("Bye...\n");return ret;}staticvoidl2fwd_main_loop(void){struct rte_mbuf *pkts_burst[MAX_PKT_BURST];struct rte_mbuf *m;int sent;unsigned lcore_id;uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;unsigned i, j, portid, nb_rx;struct lcore_queue_conf *qconf;constuint64_t drain_tsc =(rte_get_tsc_hz()+ US_PER_S -1)/ US_PER_S * BURST_TX_DRAIN_US;struct rte_eth_dev_tx_buffer *buffer; prev_tsc =0; timer_tsc =0; lcore_id = rte_lcore_id(); qconf =&lcore_queue_conf[lcore_id];//获得我们初使化的时候配置的逻辑核与网口的对应关系列表。if(qconf->n_rx_port ==0){ RTE_LOG(INFO, L2FWD,"lcore %u has nothing to do\n", lcore_id);return;} RTE_LOG(INFO, L2FWD,"entering main loop on lcore %u\n", lcore_id);for(i =0; i < qconf->n_rx_port; i++){ portid = qconf->rx_port_list[i]; RTE_LOG(INFO, L2FWD," -- lcoreid=%u portid=%u\n", lcore_id, portid);}while(!force_quit){ cur_tsc = rte_rdtsc();/* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc;if(unlikely(diff_tsc > drain_tsc)){//时间时隔到了就刷新发送所有网口上的待发送的报文。for(i =0; i < qconf->n_rx_port; i++){ portid = l2fwd_dst_ports[qconf->rx_port_list[i]]; buffer = tx_buffer[portid]; sent = rte_eth_tx_buffer_flush(portid,0, buffer);if(sent) port_statistics[portid].tx += sent;}/* if timer is enabled */if(timer_period >0){/* advance the timer */ timer_tsc += diff_tsc;/* if timer has reached its timeout */if(unlikely(timer_tsc >= timer_period)){/* do this only on master core */if(lcore_id == rte_get_master_lcore()){//如果是在逻辑核上,且符合条件,就打印统计信息。 print_stats();/* reset the timer */ timer_tsc =0;}}} prev_tsc = cur_tsc;}/* * Read packet from RX queues */for(i =0; i < qconf->n_rx_port; i++){//轮询每个网口,进行接收报文。 portid = qconf->rx_port_list[i]; nb_rx = rte_eth_rx_burst((uint8_t) portid,0, pkts_burst, MAX_PKT_BURST); port_statistics[portid].rx += nb_rx;for(j =0; j < nb_rx; j++){ m = pkts_burst[j]; rte_prefetch0(rte_pktmbuf_mtod(m,void*)); l2fwd_simple_forward(m, portid);}}}}staticvoidl2fwd_simple_forward(struct rte_mbuf *m,unsigned portid){struct ether_hdr *eth;void*tmp;unsigned dst_port;int sent;struct rte_eth_dev_tx_buffer *buffer; dst_port = l2fwd_dst_ports[portid];//获得发送的网口,相当于就是做转发。 eth = rte_pktmbuf_mtod(m,struct ether_hdr *);/* 02:00:00:00:00:xx */ tmp =ð->d_addr.addr_bytes[0];*((uint64_t*)tmp)=0x000000000002+((uint64_t)dst_port <<40);/* src addr */ ether_addr_copy(&l2fwd_ports_eth_addr[dst_port],ð->s_addr); buffer = tx_buffer[dst_port];//获得初使化的时候配置的发送缓存。 sent = rte_eth_tx_buffer(dst_port,0, buffer, m);//预发送,其实并没有真正的发送。if(sent) port_statistics[dst_port].tx += sent;}原文:http://www.cnblogs.com/yml435/p/6286162.html