#include "main.h"
/* Constants of the system */
#define MEMPOOL_NAME "replay_dpdk" // Name of the NICs' mem_pool, useless comment....
#define MEMPOOL_ELEM_SZ 2048 // Power of two greater than 1500
#define MEMPOOL_CACHE_SZ 512 // Max is 512
#define RX_QUEUE_SZ 256 // The size of rx queue. Max is 4096 and is the one you'll have best performances with. Use lower if you want to use Burst Bulk Alloc.
#define TX_QUEUE_SZ 4096 // Unused, you don't tx packets
int do_shutdown=0; // 1 stop to replay
uint32_t loop_times=1; // loop times;
double rate=0; // rate control
uint32_t nb_sys_ports=0; // port number
pcap_info_t *pcap_info=NULL; // pcap info
static struct rte_mempool *rx_pktmbuf_mempool[RTE_MAX_ETHPORTS];
static struct rte_mempool tx_pktmbuf_mempool;
static struct ether_addr port_eth_addr[RTE_MAX_ETHPORTS];
port_statistic_t port_statics[RTE_MAX_ETHPORTS];
eth_stats_t port_stats[RTE_MAX_ETHPORTS];
uint64_t num_pkt_good_sent=0;
uint64_t num_bytes_good_sent=0;
uint64_t old_num_pkt_good_sent=0;
uint64_t old_num_bytes_good_sent=0;
uint64_t num_bytes_for_rate=0;
uint64_t num_bytes_for_rate_ps=0;
uint64_t mempool_count = 1048576; // 2^20
struct timeval start_time, last_time;
struct rte_eth_link link;
uint64_t tx_cycles=0;
/*
size_t get_file_length(char *file_name)
{
int file_len;
FILE *fd;
if((fd=fopen(file_name,"r"))==NULL)
return 0;
fseek(fd,0,SEEK_END);
file_len=ftell(fd);
fseek(fd,0, SEEK_SET);
fclose(fd);
return file_len;
}
*/
double delta_time (struct timeval * now, struct timeval * before)
{
time_t delta_seconds;
time_t delta_microseconds;
/*
* compute delta in second, 1/10's and 1/1000's second units
*/
delta_seconds = now -> tv_sec - before -> tv_sec;
delta_microseconds = now -> tv_usec - before -> tv_usec;
if(delta_microseconds < 0) {
/* manually carry a one from the seconds field */
delta_microseconds += 1000000; /* 1e6 */
-- delta_seconds;
}
return((double)(delta_seconds * 1000) + (double)delta_microseconds/1000);
}
/*
* set packet rate according the rate parameter
*/
void replay_packet_rate(pcap_info_t *pcap_info, uint32_t pid)
{
uint32_t size=0;
double pps=0;
double link_speed=0;
uint64_t hz=0;
hz=rte_get_timer_hz();
size=pcap_info->pkt_size + PKT_PREAMBLE_SIZE/*Preamble*/ +INTER_FRAME_GAP /*IFG*/ + FCS_SIZE /*CRC*/;
if(rate > 0)
{
pps= ((rate * MILLION)/8.0)/size;
printf("Port %d rate set to %.2f Mbit/s, %d-byte packets, %.2f Mpps\n",
pid, rate, size, pps/MILLION);
tx_cycles= hz/pps;
}
else
{
link_speed =(double)link.link_speed/MILLION;
pps = (link_speed*MILLION/8.0)/size;
printf("Port %d rate set to %.2f Mbit/s, %d-byte packets, %.2f Mpps\n",
pid, link_speed, size, pps/MILLION);
tx_cycles=hz/pps;
}
}
/* Loop function, batch timing implemented */
static int main_loop(__attribute__((unused)) void *arg)
{
uint64_t curr_tsc=0, prev_tsc=0;
uint64_t tx_next_cycle, diff_hz; /* Next cycle to send a burst of traffic */
int i=0, ret=0, coount=0, j=0;
// unsigned lcore_id;
struct rte_mbuf *mbuf, *mbuf_copy;
struct timeval now_time;
double deltaMillisec, real_rate, diff_rate, diff_pps;
for (i=0;i<nb_sys_ports; i++)
rte_eth_stats_reset( i ); // reset the general I/O statics of an Ethernet device
gettimeofday(&start_time, NULL);
memcpy(&last_time, &start_time, sizeof(start_time));
if(rate > 0)
{
diff_hz=(double)rte_get_tsc_hz();
}
tx_next_cycle = rte_get_tsc_cycles() + tx_cycles;
while(!do_shutdown)
{
curr_tsc = rte_get_tsc_cycles();
if(curr_tsc>=tx_next_cycle)
{
tx_next_cycle=curr_tsc +tx_cycles;
for(i=0; i<nb_sys_ports; i++)
{
/* get one object from mempool, 0:success, -ENOENT:Not enough entries */
if(unlikely(rte_mempool_get_bulk(&tx_pktmbuf_mempool, &mbuf, 1))!=0)
{
rte_pktmbuf_free(mbuf);
break;
}
for(j=0; j<times; j++)
{
if(unlikely(i)==0)
while(rte_eth_tx_burst(i, 0, &mbuf,1)!=1);
else
{
mbuf_copy=rte_pktmbuf_clone(mbuf, &tx_pktmbuf_mempool);
while(rte_eth_tx_burst(i,0,&mbuf_copy, 1)!=1);
}
}
}
}
prev_tsc=curr_tsc;
/* adjust the rate */
if(count++ %100 ==0)
{
gettimeofday(&now_time,NULL);
deltaMillisec= delta_time(now_time, last_time);
real_rate= (num_bytes_good_sent*1000)/deltaMillisec*8/MILLION; // Mbps
printf("real rate is %8.3Mbps\n", real_rate);
if(real_rate> rate)
{
diff_rate=real_rate-rate;
diff_pps= (diff_rate/8) / (num_bytes_good_sent/num_pkt_good_sent);
tx_cycles += diff_hz/diff_pps;
}
else
{
diff_rate=rate-real_rate;
diff_pps= (diff_rate/8) / (num_bytes_good_sent/num_pkt_good_sent);
tx_cycles -= diff_hz/diff_pps;
}
}
num_pkt_good_sent += times;
num_bytes_good_sent += (mbuf->data_len + 24) * times; /* 8 Preamble + 4 CRC + 12 IFG*/
}
sig_handler(SIGINT);
return 0;
}
void print_stats (void){
int ret;
struct timeval now_time;
double delta_ms;
double tot_ms;
double Mbps_inst, Mbps_tot, mpps_inst, mpps_tot;
/* Get actual time */
ret = gettimeofday(&now_time, NULL);
if (ret != 0)
FATAL_ERROR("Error: gettimeofday failed. Quitting...\n");
/* Compute stats */
delta_ms=delta_time(&now_time, &last_time);
tot_ms= delta_time(&now_time, &start_time);
Mbps_inst = (double)(num_bytes_good_sent - old_num_bytes_good_sent)/delta_ms/1000*8;
Mbps_tot = (double)(num_bytes_good_sent)/tot_ms/1000000*8;
mpps_inst = (double)(num_pkt_good_sent - old_num_pkt_good_sent)/delta_ms/1000;
mpps_tot = (double)(num_pkt_good_sent)/tot_ms/1000;
printf("Rate: %8.3fMbps %8.3fMpps [Average rate: %8.3fMbps %8.3fMpps]\n",
Mbps_inst, mpps_inst, Mbps_tot, mpps_tot);
/* Update counters */
old_num_bytes_good_sent = num_bytes_good_sent;
old_num_pkt_good_sent = num_pkt_good_sent;
last_time = now_time;
}
void alarm_routine (__attribute__((unused)) int unused){
/* If the program is quitting don't print anymore */
if(do_shutdown)
return;
/* Print per port stats */
print_stats();
/* Schedule an other print */
alarm(1);
signal(SIGALRM, alarm_routine);
}
/* Signal handling function */
static void sig_handler(int signo)
{
uint64_t diff;
int ret;
struct timeval t_end;
/* Catch just SIGINT */
if (signo == SIGINT){
do_shutdown=1;
/* Print the per stats */
printf("\n-----------quit to replya---------\n");
ret = gettimeofday(&t_end, NULL);
if (ret != 0)
FATAL_ERROR("Error: gettimeofday failed. Quitting...\n");
diff = t_end.tv_sec - start_time.tv_sec;
printf("The replay lasted %ld seconds. Sent %ld packets on every interface\n", diff, num_pkt_good_sent);
print_stats();
/* Close the pcap file */
if(pcap_info->fd)
fclose(pcap_info->fd);
pcap_info->fd=NULL;
}
}
/*
* callback function bt rte_mempool_create() to construct pcap packets
*/
static void replay_pcap_mbuf_ctor(struct rte_memool *mp, void *opaque_arg, void *_m, unsigned i)
{
struct rte_mbuf *m = _m;
#if RTE_VERSION >= RTE_VERSION_NUM(16, 7, 0, 0)
uint32_t buf_len, mbuf_size, priv_size;
#else
uint32_t buf_len = mp->elt_size - sizeof(struct rte_mbuf);
#endif
pcaprec_hdr_t hdr;
ssize_t len = -1;
char buffer[8912];
pcap_info_t *pcap = (pcap_info_t *)opaque_arg;
#if RTE_VERSION >= RTE_VERSION_NUM(16, 7, 0, 0)
priv_size = rte_pktmbuf_priv_size(mp);
mbuf_size = sizeof(struct rte_mbuf) + priv_size;
buf_len = rte_pktmbuf_data_room_size(mp);
#endif
memset(m, 0, mbuf_size);
#if RTE_VERSION >= RTE_VERSION_NUM(17, 11, 0, 0)
/* start of buffer is just after mbuf structure */
m->priv_size = priv_size;
m->buf_addr = (char *)m + mbuf_size;
m->buf_iova = rte_mempool_virt2iova(m) + mbuf_size;
m->buf_len = (uint16_t)buf_len;
#elif RTE_VERSION >= RTE_VERSION_NUM(16, 7, 0, 0)
/* start of buffer is after mbuf structure and priv data */
m->priv_size = priv_size;
m->buf
评论0