1*76404edcSAsim Jamshed #include <stdio.h> 2*76404edcSAsim Jamshed #include <stdlib.h> 3*76404edcSAsim Jamshed #include <string.h> 4*76404edcSAsim Jamshed #include <unistd.h> 5*76404edcSAsim Jamshed #include <stdint.h> 6*76404edcSAsim Jamshed #include <time.h> 7*76404edcSAsim Jamshed #include <sys/time.h> 8*76404edcSAsim Jamshed #include <sys/types.h> 9*76404edcSAsim Jamshed #include <sys/stat.h> 10*76404edcSAsim Jamshed #include <fcntl.h> 11*76404edcSAsim Jamshed #include <pthread.h> 12*76404edcSAsim Jamshed #include <signal.h> 13*76404edcSAsim Jamshed #include <sys/socket.h> 14*76404edcSAsim Jamshed #include <netinet/in.h> 15*76404edcSAsim Jamshed #include <arpa/inet.h> 16*76404edcSAsim Jamshed #include <sys/queue.h> 17*76404edcSAsim Jamshed #include <assert.h> 18*76404edcSAsim Jamshed 19*76404edcSAsim Jamshed #include <mos_api.h> 20*76404edcSAsim Jamshed #include "cpu.h" 21*76404edcSAsim Jamshed #include "rss.h" 22*76404edcSAsim Jamshed #include "http_parsing.h" 23*76404edcSAsim Jamshed #include "debug.h" 24*76404edcSAsim Jamshed #include "applib.h" 25*76404edcSAsim Jamshed 26*76404edcSAsim Jamshed #define CONFIG_FILE "config/epwget.conf" 27*76404edcSAsim Jamshed static struct conf_var g_conf[] = { 28*76404edcSAsim Jamshed { "url", {0} }, 29*76404edcSAsim Jamshed { "total_flows", {0} }, 30*76404edcSAsim Jamshed { "core_limit", {0} }, 31*76404edcSAsim Jamshed { "total_concurrency", {0} }, 32*76404edcSAsim Jamshed { "dest_port", {0} }, 33*76404edcSAsim Jamshed }; 34*76404edcSAsim Jamshed #define NUM_CONF_VAR (sizeof(g_conf) / sizeof(struct conf_var)) 35*76404edcSAsim Jamshed 36*76404edcSAsim Jamshed #define PORT_NUM 80 37*76404edcSAsim Jamshed //#define PORT_NUM 3333 38*76404edcSAsim Jamshed 39*76404edcSAsim Jamshed #define MAX_URL_LEN 128 40*76404edcSAsim Jamshed #define MAX_FILE_LEN 128 41*76404edcSAsim Jamshed #define HTTP_HEADER_LEN 1024 42*76404edcSAsim Jamshed 43*76404edcSAsim Jamshed #define IP_RANGE 1 44*76404edcSAsim Jamshed #define MAX_IP_STR_LEN 16 45*76404edcSAsim Jamshed 46*76404edcSAsim Jamshed #define BUF_SIZE (8*1024) 47*76404edcSAsim Jamshed 48*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 49*76404edcSAsim Jamshed struct mtcp_conf g_mcfg; 50*76404edcSAsim Jamshed static pthread_t mtcp_thread[MAX_CPUS]; 51*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 52*76404edcSAsim Jamshed static mctx_t g_mctx[MAX_CPUS]; 53*76404edcSAsim Jamshed static int done[MAX_CPUS]; 54*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 55*76404edcSAsim Jamshed static int num_cores; 56*76404edcSAsim Jamshed static int core_limit; 57*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 58*76404edcSAsim Jamshed static int fio = FALSE; 59*76404edcSAsim Jamshed static char outfile[MAX_FILE_LEN + 1]; 60*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 61*76404edcSAsim Jamshed static char host[MAX_IP_STR_LEN + 1]; 62*76404edcSAsim Jamshed static char path[MAX_URL_LEN + 1]; 63*76404edcSAsim Jamshed static in_addr_t daddr; 64*76404edcSAsim Jamshed static in_port_t dport; 65*76404edcSAsim Jamshed static in_addr_t saddr; 66*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 67*76404edcSAsim Jamshed static int total_flows; 68*76404edcSAsim Jamshed static int flows[MAX_CPUS]; 69*76404edcSAsim Jamshed static int flowcnt = 0; 70*76404edcSAsim Jamshed static int concurrency; 71*76404edcSAsim Jamshed static int max_fds; 72*76404edcSAsim Jamshed static uint16_t dest_port; 73*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 74*76404edcSAsim Jamshed struct wget_stat 75*76404edcSAsim Jamshed { 76*76404edcSAsim Jamshed uint64_t waits; 77*76404edcSAsim Jamshed uint64_t events; 78*76404edcSAsim Jamshed uint64_t connects; 79*76404edcSAsim Jamshed uint64_t reads; 80*76404edcSAsim Jamshed uint64_t writes; 81*76404edcSAsim Jamshed uint64_t completes; 82*76404edcSAsim Jamshed 83*76404edcSAsim Jamshed uint64_t errors; 84*76404edcSAsim Jamshed uint64_t timedout; 85*76404edcSAsim Jamshed 86*76404edcSAsim Jamshed uint64_t sum_resp_time; 87*76404edcSAsim Jamshed uint64_t max_resp_time; 88*76404edcSAsim Jamshed }; 89*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 90*76404edcSAsim Jamshed struct thread_context 91*76404edcSAsim Jamshed { 92*76404edcSAsim Jamshed int core; 93*76404edcSAsim Jamshed 94*76404edcSAsim Jamshed mctx_t mctx; 95*76404edcSAsim Jamshed int ep; 96*76404edcSAsim Jamshed struct wget_vars *wvars; 97*76404edcSAsim Jamshed 98*76404edcSAsim Jamshed int target; 99*76404edcSAsim Jamshed int started; 100*76404edcSAsim Jamshed int errors; 101*76404edcSAsim Jamshed int incompletes; 102*76404edcSAsim Jamshed int done; 103*76404edcSAsim Jamshed int pending; 104*76404edcSAsim Jamshed 105*76404edcSAsim Jamshed int maxevents; 106*76404edcSAsim Jamshed struct mtcp_epoll_event *events; 107*76404edcSAsim Jamshed 108*76404edcSAsim Jamshed struct wget_stat stat; 109*76404edcSAsim Jamshed }; 110*76404edcSAsim Jamshed typedef struct thread_context* thread_context_t; 111*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 112*76404edcSAsim Jamshed struct wget_vars 113*76404edcSAsim Jamshed { 114*76404edcSAsim Jamshed int request_sent; 115*76404edcSAsim Jamshed 116*76404edcSAsim Jamshed char response[HTTP_HEADER_LEN]; 117*76404edcSAsim Jamshed int resp_len; 118*76404edcSAsim Jamshed int headerset; 119*76404edcSAsim Jamshed uint32_t header_len; 120*76404edcSAsim Jamshed uint64_t file_len; 121*76404edcSAsim Jamshed uint64_t recv; 122*76404edcSAsim Jamshed uint64_t write; 123*76404edcSAsim Jamshed 124*76404edcSAsim Jamshed struct timeval t_start; 125*76404edcSAsim Jamshed struct timeval t_end; 126*76404edcSAsim Jamshed 127*76404edcSAsim Jamshed int fd; 128*76404edcSAsim Jamshed }; 129*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 130*76404edcSAsim Jamshed static struct thread_context *g_ctx[MAX_CPUS]; 131*76404edcSAsim Jamshed static struct wget_stat *g_stat[MAX_CPUS]; 132*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 133*76404edcSAsim Jamshed static thread_context_t 134*76404edcSAsim Jamshed CreateContext(mctx_t mctx) 135*76404edcSAsim Jamshed { 136*76404edcSAsim Jamshed thread_context_t ctx; 137*76404edcSAsim Jamshed 138*76404edcSAsim Jamshed ctx = (thread_context_t)calloc(1, sizeof(struct thread_context)); 139*76404edcSAsim Jamshed if (!ctx) { 140*76404edcSAsim Jamshed perror("malloc"); 141*76404edcSAsim Jamshed TRACE_ERROR("Failed to allocate memory for thread context.\n"); 142*76404edcSAsim Jamshed return NULL; 143*76404edcSAsim Jamshed } 144*76404edcSAsim Jamshed 145*76404edcSAsim Jamshed ctx->mctx = mctx; 146*76404edcSAsim Jamshed ctx->core = mctx->cpu; 147*76404edcSAsim Jamshed 148*76404edcSAsim Jamshed g_mctx[ctx->core] = mctx; 149*76404edcSAsim Jamshed 150*76404edcSAsim Jamshed return ctx; 151*76404edcSAsim Jamshed } 152*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 153*76404edcSAsim Jamshed static void 154*76404edcSAsim Jamshed DestroyContext(thread_context_t ctx) 155*76404edcSAsim Jamshed { 156*76404edcSAsim Jamshed free(ctx); 157*76404edcSAsim Jamshed } 158*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 159*76404edcSAsim Jamshed static inline int 160*76404edcSAsim Jamshed CreateConnection(thread_context_t ctx) 161*76404edcSAsim Jamshed { 162*76404edcSAsim Jamshed mctx_t mctx = ctx->mctx; 163*76404edcSAsim Jamshed struct mtcp_epoll_event ev; 164*76404edcSAsim Jamshed struct sockaddr_in addr; 165*76404edcSAsim Jamshed int sockid; 166*76404edcSAsim Jamshed int ret; 167*76404edcSAsim Jamshed 168*76404edcSAsim Jamshed assert(mctx); 169*76404edcSAsim Jamshed 170*76404edcSAsim Jamshed errno = 0; 171*76404edcSAsim Jamshed sockid = mtcp_socket(mctx, AF_INET, SOCK_STREAM, 0); 172*76404edcSAsim Jamshed if (sockid < 0) { 173*76404edcSAsim Jamshed TRACE_INFO("Failed to create socket! (%s)\n", 174*76404edcSAsim Jamshed strerror(errno)); 175*76404edcSAsim Jamshed return -1; 176*76404edcSAsim Jamshed } 177*76404edcSAsim Jamshed memset(&ctx->wvars[sockid], 0, sizeof(struct wget_vars)); 178*76404edcSAsim Jamshed ret = mtcp_setsock_nonblock(mctx, sockid); 179*76404edcSAsim Jamshed if (ret < 0) { 180*76404edcSAsim Jamshed TRACE_ERROR("Failed to set socket in nonblocking mode.\n"); 181*76404edcSAsim Jamshed exit(-1); 182*76404edcSAsim Jamshed } 183*76404edcSAsim Jamshed 184*76404edcSAsim Jamshed addr.sin_family = AF_INET; 185*76404edcSAsim Jamshed addr.sin_addr.s_addr = daddr; 186*76404edcSAsim Jamshed addr.sin_port = dport; 187*76404edcSAsim Jamshed 188*76404edcSAsim Jamshed ret = mtcp_connect(mctx, sockid, 189*76404edcSAsim Jamshed (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); 190*76404edcSAsim Jamshed if (ret < 0) { 191*76404edcSAsim Jamshed if (errno != EINPROGRESS) { 192*76404edcSAsim Jamshed perror("mtcp_connect"); 193*76404edcSAsim Jamshed mtcp_close(mctx, sockid); 194*76404edcSAsim Jamshed return -1; 195*76404edcSAsim Jamshed } 196*76404edcSAsim Jamshed } 197*76404edcSAsim Jamshed 198*76404edcSAsim Jamshed ctx->started++; 199*76404edcSAsim Jamshed ctx->pending++; 200*76404edcSAsim Jamshed ctx->stat.connects++; 201*76404edcSAsim Jamshed 202*76404edcSAsim Jamshed ev.events = MOS_EPOLLOUT; 203*76404edcSAsim Jamshed ev.data.sock = sockid; 204*76404edcSAsim Jamshed mtcp_epoll_ctl(mctx, ctx->ep, MOS_EPOLL_CTL_ADD, sockid, &ev); 205*76404edcSAsim Jamshed 206*76404edcSAsim Jamshed return sockid; 207*76404edcSAsim Jamshed } 208*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 209*76404edcSAsim Jamshed static inline void 210*76404edcSAsim Jamshed CloseConnection(thread_context_t ctx, int sockid) 211*76404edcSAsim Jamshed { 212*76404edcSAsim Jamshed mtcp_epoll_ctl(ctx->mctx, ctx->ep, MOS_EPOLL_CTL_DEL, sockid, NULL); 213*76404edcSAsim Jamshed mtcp_close(ctx->mctx, sockid); 214*76404edcSAsim Jamshed ctx->pending--; 215*76404edcSAsim Jamshed ctx->done++; 216*76404edcSAsim Jamshed assert(ctx->pending >= 0); 217*76404edcSAsim Jamshed while (/*ctx->pending*/ mtcp_get_connection_cnt(ctx->mctx) < concurrency && ctx->started < ctx->target) { 218*76404edcSAsim Jamshed if (CreateConnection(ctx) < 0) { 219*76404edcSAsim Jamshed done[ctx->core] = TRUE; 220*76404edcSAsim Jamshed break; 221*76404edcSAsim Jamshed } 222*76404edcSAsim Jamshed } 223*76404edcSAsim Jamshed } 224*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 225*76404edcSAsim Jamshed static inline int 226*76404edcSAsim Jamshed SendHTTPRequest(thread_context_t ctx, int sockid, struct wget_vars *wv) 227*76404edcSAsim Jamshed { 228*76404edcSAsim Jamshed char request[HTTP_HEADER_LEN]; 229*76404edcSAsim Jamshed struct mtcp_epoll_event ev; 230*76404edcSAsim Jamshed int wr; 231*76404edcSAsim Jamshed int len; 232*76404edcSAsim Jamshed 233*76404edcSAsim Jamshed wv->headerset = FALSE; 234*76404edcSAsim Jamshed wv->recv = 0; 235*76404edcSAsim Jamshed wv->header_len = wv->file_len = 0; 236*76404edcSAsim Jamshed 237*76404edcSAsim Jamshed snprintf(request, HTTP_HEADER_LEN, "GET %s HTTP/1.0\r\n" 238*76404edcSAsim Jamshed "User-Agent: Wget/1.12 (linux-gnu)\r\n" 239*76404edcSAsim Jamshed "Accept: */*\r\n" 240*76404edcSAsim Jamshed "Host: %s\r\n" 241*76404edcSAsim Jamshed // "Connection: Keep-Alive\r\n\r\n", 242*76404edcSAsim Jamshed "Connection: Close\r\n\r\n", 243*76404edcSAsim Jamshed path, host); 244*76404edcSAsim Jamshed len = strlen(request); 245*76404edcSAsim Jamshed 246*76404edcSAsim Jamshed wr = mtcp_write(ctx->mctx, sockid, request, len); 247*76404edcSAsim Jamshed if (wr < len) { 248*76404edcSAsim Jamshed TRACE_ERROR("Socket %d: Sending HTTP request failed. " 249*76404edcSAsim Jamshed "try: %d, sent: %d\n", sockid, len, wr); 250*76404edcSAsim Jamshed CloseConnection(ctx, sockid); 251*76404edcSAsim Jamshed } 252*76404edcSAsim Jamshed ctx->stat.writes += wr; 253*76404edcSAsim Jamshed TRACE_APP("Socket %d HTTP Request of %d bytes. sent.\n", sockid, wr); 254*76404edcSAsim Jamshed wv->request_sent = TRUE; 255*76404edcSAsim Jamshed 256*76404edcSAsim Jamshed ev.events = MOS_EPOLLIN; 257*76404edcSAsim Jamshed ev.data.sock = sockid; 258*76404edcSAsim Jamshed mtcp_epoll_ctl(ctx->mctx, ctx->ep, MOS_EPOLL_CTL_MOD, sockid, &ev); 259*76404edcSAsim Jamshed 260*76404edcSAsim Jamshed gettimeofday(&wv->t_start, NULL); 261*76404edcSAsim Jamshed 262*76404edcSAsim Jamshed char fname[MAX_FILE_LEN + 1]; 263*76404edcSAsim Jamshed if (fio) { 264*76404edcSAsim Jamshed snprintf(fname, MAX_FILE_LEN, "%s.%d", outfile, flowcnt++); 265*76404edcSAsim Jamshed wv->fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0644); 266*76404edcSAsim Jamshed if (wv->fd < 0) { 267*76404edcSAsim Jamshed TRACE_APP("Failed to open file descriptor for %s\n", fname); 268*76404edcSAsim Jamshed exit(1); 269*76404edcSAsim Jamshed } 270*76404edcSAsim Jamshed } 271*76404edcSAsim Jamshed 272*76404edcSAsim Jamshed return 0; 273*76404edcSAsim Jamshed } 274*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 275*76404edcSAsim Jamshed static inline int 276*76404edcSAsim Jamshed DownloadComplete(thread_context_t ctx, int sockid, struct wget_vars *wv) 277*76404edcSAsim Jamshed { 278*76404edcSAsim Jamshed #ifdef APP 279*76404edcSAsim Jamshed mctx_t mctx = ctx->mctx; 280*76404edcSAsim Jamshed #endif 281*76404edcSAsim Jamshed uint64_t tdiff; 282*76404edcSAsim Jamshed 283*76404edcSAsim Jamshed TRACE_APP("Socket %d File download complete!\n", sockid); 284*76404edcSAsim Jamshed gettimeofday(&wv->t_end, NULL); 285*76404edcSAsim Jamshed CloseConnection(ctx, sockid); 286*76404edcSAsim Jamshed ctx->stat.completes++; 287*76404edcSAsim Jamshed 288*76404edcSAsim Jamshed if (wv->recv - wv->header_len != wv->file_len) { 289*76404edcSAsim Jamshed fprintf(stderr, "Response size mismatch! " 290*76404edcSAsim Jamshed "actual recved: %ld, expected to recved: %ld\n", 291*76404edcSAsim Jamshed wv->recv-wv->header_len, wv->file_len); 292*76404edcSAsim Jamshed } 293*76404edcSAsim Jamshed 294*76404edcSAsim Jamshed tdiff = (wv->t_end.tv_sec - wv->t_start.tv_sec) * 1000000 + 295*76404edcSAsim Jamshed (wv->t_end.tv_usec - wv->t_start.tv_usec); 296*76404edcSAsim Jamshed TRACE_APP("Socket %d Total received bytes: %lu (%luMB)\n", 297*76404edcSAsim Jamshed sockid, wv->recv, wv->recv / 1000000); 298*76404edcSAsim Jamshed TRACE_APP("Socket %d Total spent time: %lu us\n", sockid, tdiff); 299*76404edcSAsim Jamshed if (tdiff > 0) { 300*76404edcSAsim Jamshed TRACE_APP("Socket %d Average bandwidth: %lf[MB/s]\n", 301*76404edcSAsim Jamshed sockid, (double)wv->recv / tdiff); 302*76404edcSAsim Jamshed } 303*76404edcSAsim Jamshed ctx->stat.sum_resp_time += tdiff; 304*76404edcSAsim Jamshed if (tdiff > ctx->stat.max_resp_time) 305*76404edcSAsim Jamshed ctx->stat.max_resp_time = tdiff; 306*76404edcSAsim Jamshed 307*76404edcSAsim Jamshed if (fio && wv->fd > 0) 308*76404edcSAsim Jamshed close(wv->fd); 309*76404edcSAsim Jamshed 310*76404edcSAsim Jamshed return 0; 311*76404edcSAsim Jamshed } 312*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 313*76404edcSAsim Jamshed static inline int 314*76404edcSAsim Jamshed HandleReadEvent(thread_context_t ctx, int sockid, struct wget_vars *wv) 315*76404edcSAsim Jamshed { 316*76404edcSAsim Jamshed mctx_t mctx = ctx->mctx; 317*76404edcSAsim Jamshed char buf[BUF_SIZE]; 318*76404edcSAsim Jamshed char *pbuf; 319*76404edcSAsim Jamshed int rd, copy_len; 320*76404edcSAsim Jamshed 321*76404edcSAsim Jamshed rd = 1; 322*76404edcSAsim Jamshed while (rd > 0) { 323*76404edcSAsim Jamshed rd = mtcp_read(mctx, sockid, buf, BUF_SIZE); 324*76404edcSAsim Jamshed if (rd <= 0) 325*76404edcSAsim Jamshed break; 326*76404edcSAsim Jamshed ctx->stat.reads += rd; 327*76404edcSAsim Jamshed 328*76404edcSAsim Jamshed TRACE_APP("Socket %d: mtcp_read ret: %d, total_recv: %lu, " 329*76404edcSAsim Jamshed "header_set: %d, header_len: %u, file_len: %lu\n", 330*76404edcSAsim Jamshed sockid, rd, wv->recv + rd, 331*76404edcSAsim Jamshed wv->headerset, wv->header_len, wv->file_len); 332*76404edcSAsim Jamshed 333*76404edcSAsim Jamshed pbuf = buf; 334*76404edcSAsim Jamshed if (!wv->headerset) { 335*76404edcSAsim Jamshed copy_len = MIN(rd, HTTP_HEADER_LEN - wv->resp_len); 336*76404edcSAsim Jamshed memcpy(wv->response + wv->resp_len, buf, copy_len); 337*76404edcSAsim Jamshed wv->resp_len += copy_len; 338*76404edcSAsim Jamshed wv->header_len = find_http_header(wv->response, wv->resp_len); 339*76404edcSAsim Jamshed if (wv->header_len > 0) { 340*76404edcSAsim Jamshed wv->response[wv->header_len] = '\0'; 341*76404edcSAsim Jamshed wv->file_len = http_header_long_val(wv->response, 342*76404edcSAsim Jamshed CONTENT_LENGTH_HDR, sizeof(CONTENT_LENGTH_HDR) - 1); 343*76404edcSAsim Jamshed TRACE_APP("Socket %d Parsed response header. " 344*76404edcSAsim Jamshed "Header length: %u, File length: %lu (%luMB)\n", 345*76404edcSAsim Jamshed sockid, wv->header_len, 346*76404edcSAsim Jamshed wv->file_len, wv->file_len / 1024 / 1024); 347*76404edcSAsim Jamshed wv->headerset = TRUE; 348*76404edcSAsim Jamshed wv->recv += (rd - (wv->resp_len - wv->header_len)); 349*76404edcSAsim Jamshed rd = (wv->resp_len - wv->header_len); 350*76404edcSAsim Jamshed 351*76404edcSAsim Jamshed pbuf += (rd - (wv->resp_len - wv->header_len)); 352*76404edcSAsim Jamshed 353*76404edcSAsim Jamshed } else { 354*76404edcSAsim Jamshed /* failed to parse response header */ 355*76404edcSAsim Jamshed wv->recv += rd; 356*76404edcSAsim Jamshed rd = 0; 357*76404edcSAsim Jamshed ctx->stat.errors++; 358*76404edcSAsim Jamshed ctx->errors++; 359*76404edcSAsim Jamshed CloseConnection(ctx, sockid); 360*76404edcSAsim Jamshed return 0; 361*76404edcSAsim Jamshed } 362*76404edcSAsim Jamshed } 363*76404edcSAsim Jamshed wv->recv += rd; 364*76404edcSAsim Jamshed 365*76404edcSAsim Jamshed if (fio && wv->fd > 0) { 366*76404edcSAsim Jamshed int wr = 0; 367*76404edcSAsim Jamshed while (wr < rd) { 368*76404edcSAsim Jamshed int _wr = write(wv->fd, pbuf + wr, rd - wr); 369*76404edcSAsim Jamshed assert (_wr == rd - wr); 370*76404edcSAsim Jamshed if (_wr < 0) { 371*76404edcSAsim Jamshed perror("write"); 372*76404edcSAsim Jamshed TRACE_ERROR("Failed to write.\n"); 373*76404edcSAsim Jamshed assert(0); 374*76404edcSAsim Jamshed break; 375*76404edcSAsim Jamshed } 376*76404edcSAsim Jamshed wr += _wr; 377*76404edcSAsim Jamshed wv->write += _wr; 378*76404edcSAsim Jamshed } 379*76404edcSAsim Jamshed } 380*76404edcSAsim Jamshed 381*76404edcSAsim Jamshed if (wv->header_len && (wv->recv >= wv->header_len + wv->file_len)) { 382*76404edcSAsim Jamshed break; 383*76404edcSAsim Jamshed } 384*76404edcSAsim Jamshed } 385*76404edcSAsim Jamshed 386*76404edcSAsim Jamshed if (rd > 0) { 387*76404edcSAsim Jamshed if (wv->header_len && (wv->recv >= wv->header_len + wv->file_len)) { 388*76404edcSAsim Jamshed TRACE_APP("Socket %d Done Write: " 389*76404edcSAsim Jamshed "header: %u file: %lu recv: %lu write: %lu\n", 390*76404edcSAsim Jamshed sockid, wv->header_len, wv->file_len, 391*76404edcSAsim Jamshed wv->recv - wv->header_len, wv->write); 392*76404edcSAsim Jamshed DownloadComplete(ctx, sockid, wv); 393*76404edcSAsim Jamshed 394*76404edcSAsim Jamshed return 0; 395*76404edcSAsim Jamshed } 396*76404edcSAsim Jamshed 397*76404edcSAsim Jamshed } else if (rd == 0) { 398*76404edcSAsim Jamshed /* connection closed by remote host */ 399*76404edcSAsim Jamshed TRACE_DBG("Socket %d connection closed with server.\n", sockid); 400*76404edcSAsim Jamshed 401*76404edcSAsim Jamshed if (wv->header_len && (wv->recv >= wv->header_len + wv->file_len)) { 402*76404edcSAsim Jamshed DownloadComplete(ctx, sockid, wv); 403*76404edcSAsim Jamshed } else { 404*76404edcSAsim Jamshed ctx->stat.errors++; 405*76404edcSAsim Jamshed ctx->incompletes++; 406*76404edcSAsim Jamshed CloseConnection(ctx, sockid); 407*76404edcSAsim Jamshed } 408*76404edcSAsim Jamshed 409*76404edcSAsim Jamshed } else if (rd < 0) { 410*76404edcSAsim Jamshed if (errno != EAGAIN) { 411*76404edcSAsim Jamshed TRACE_DBG("Socket %d: mtcp_read() error %s\n", 412*76404edcSAsim Jamshed sockid, strerror(errno)); 413*76404edcSAsim Jamshed ctx->stat.errors++; 414*76404edcSAsim Jamshed ctx->errors++; 415*76404edcSAsim Jamshed CloseConnection(ctx, sockid); 416*76404edcSAsim Jamshed } 417*76404edcSAsim Jamshed } 418*76404edcSAsim Jamshed 419*76404edcSAsim Jamshed return 0; 420*76404edcSAsim Jamshed } 421*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 422*76404edcSAsim Jamshed static void 423*76404edcSAsim Jamshed PrintStats() 424*76404edcSAsim Jamshed { 425*76404edcSAsim Jamshed struct wget_stat total = {0}; 426*76404edcSAsim Jamshed struct wget_stat *st; 427*76404edcSAsim Jamshed uint64_t avg_resp_time; 428*76404edcSAsim Jamshed uint64_t total_resp_time = 0; 429*76404edcSAsim Jamshed int i; 430*76404edcSAsim Jamshed 431*76404edcSAsim Jamshed for (i = 0; i < core_limit; i++) { 432*76404edcSAsim Jamshed st = g_stat[i]; 433*76404edcSAsim Jamshed if (!st) 434*76404edcSAsim Jamshed continue; 435*76404edcSAsim Jamshed avg_resp_time = st->completes? st->sum_resp_time / st->completes : 0; 436*76404edcSAsim Jamshed 437*76404edcSAsim Jamshed total.waits += st->waits; 438*76404edcSAsim Jamshed total.events += st->events; 439*76404edcSAsim Jamshed total.connects += st->connects; 440*76404edcSAsim Jamshed total.reads += st->reads; 441*76404edcSAsim Jamshed total.writes += st->writes; 442*76404edcSAsim Jamshed total.completes += st->completes; 443*76404edcSAsim Jamshed total_resp_time += avg_resp_time; 444*76404edcSAsim Jamshed if (st->max_resp_time > total.max_resp_time) 445*76404edcSAsim Jamshed total.max_resp_time = st->max_resp_time; 446*76404edcSAsim Jamshed total.errors += st->errors; 447*76404edcSAsim Jamshed total.timedout += st->timedout; 448*76404edcSAsim Jamshed 449*76404edcSAsim Jamshed memset(st, 0, sizeof(struct wget_stat)); 450*76404edcSAsim Jamshed } 451*76404edcSAsim Jamshed fprintf(stderr, "[ ALL ] connect: %7lu, read: %4lu MB, write: %4lu MB, " 452*76404edcSAsim Jamshed "completes: %7lu (resp_time avg: %4lu, max: %6lu us)\n", 453*76404edcSAsim Jamshed total.connects, 454*76404edcSAsim Jamshed total.reads / 1000 / 1000, total.writes / 1000 / 1000, 455*76404edcSAsim Jamshed total.completes, total_resp_time / core_limit, total.max_resp_time); 456*76404edcSAsim Jamshed } 457*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 458*76404edcSAsim Jamshed static void 459*76404edcSAsim Jamshed GlbInitWget() 460*76404edcSAsim Jamshed { 461*76404edcSAsim Jamshed struct mtcp_conf mcfg; 462*76404edcSAsim Jamshed char *url; 463*76404edcSAsim Jamshed int total_concurrency = 0; 464*76404edcSAsim Jamshed int flow_per_thread; 465*76404edcSAsim Jamshed int flow_remainder_cnt; 466*76404edcSAsim Jamshed int i; 467*76404edcSAsim Jamshed 468*76404edcSAsim Jamshed num_cores = GetNumCPUs(); 469*76404edcSAsim Jamshed core_limit = num_cores; 470*76404edcSAsim Jamshed concurrency = 100; 471*76404edcSAsim Jamshed total_flows = -1; 472*76404edcSAsim Jamshed 473*76404edcSAsim Jamshed LoadConfig(CONFIG_FILE, g_conf, NUM_CONF_VAR); 474*76404edcSAsim Jamshed 475*76404edcSAsim Jamshed url = g_conf[0].value; 476*76404edcSAsim Jamshed total_flows = atoi(g_conf[1].value); 477*76404edcSAsim Jamshed core_limit = atoi(g_conf[2].value); 478*76404edcSAsim Jamshed total_concurrency = atoi(g_conf[3].value); 479*76404edcSAsim Jamshed dest_port = atoi(g_conf[4].value); 480*76404edcSAsim Jamshed 481*76404edcSAsim Jamshed if ((strlen(url) == 0) 482*76404edcSAsim Jamshed || (strlen(url) > MAX_URL_LEN) 483*76404edcSAsim Jamshed || (total_flows <= 0)) { 484*76404edcSAsim Jamshed TRACE_INFO("Invalid configuration\n"); 485*76404edcSAsim Jamshed exit(0); 486*76404edcSAsim Jamshed } 487*76404edcSAsim Jamshed 488*76404edcSAsim Jamshed char* slash_p = strchr(url, '/'); 489*76404edcSAsim Jamshed if (slash_p) { 490*76404edcSAsim Jamshed strncpy(host, url, slash_p - url); 491*76404edcSAsim Jamshed strncpy(path, strchr(url, '/'), MAX_URL_LEN); 492*76404edcSAsim Jamshed } else { 493*76404edcSAsim Jamshed strncpy(host, url, MAX_IP_STR_LEN); 494*76404edcSAsim Jamshed strncpy(path, "/", 1); 495*76404edcSAsim Jamshed } 496*76404edcSAsim Jamshed 497*76404edcSAsim Jamshed daddr = inet_addr(host); 498*76404edcSAsim Jamshed dport = (dest_port == 0) ? htons(PORT_NUM) : htons(dest_port); 499*76404edcSAsim Jamshed saddr = INADDR_ANY; 500*76404edcSAsim Jamshed 501*76404edcSAsim Jamshed if (total_flows < core_limit) { 502*76404edcSAsim Jamshed core_limit = total_flows; 503*76404edcSAsim Jamshed } 504*76404edcSAsim Jamshed 505*76404edcSAsim Jamshed /* per-core concurrency = total_concurrency / # cores */ 506*76404edcSAsim Jamshed if (total_concurrency > 0) 507*76404edcSAsim Jamshed concurrency = total_concurrency / core_limit; 508*76404edcSAsim Jamshed 509*76404edcSAsim Jamshed /* set the max number of fds 3x larger than concurrency */ 510*76404edcSAsim Jamshed max_fds = concurrency * 3; 511*76404edcSAsim Jamshed 512*76404edcSAsim Jamshed TRACE_CONFIG("Application configuration:\n"); 513*76404edcSAsim Jamshed TRACE_CONFIG("URL: %s\n", path); 514*76404edcSAsim Jamshed TRACE_CONFIG("# of total_flows: %d\n", total_flows); 515*76404edcSAsim Jamshed TRACE_CONFIG("# of cores: %d\n", core_limit); 516*76404edcSAsim Jamshed TRACE_CONFIG("Concurrency: %d\n", total_concurrency); 517*76404edcSAsim Jamshed 518*76404edcSAsim Jamshed mtcp_getconf(&mcfg); 519*76404edcSAsim Jamshed mcfg.max_concurrency = max_fds; 520*76404edcSAsim Jamshed mcfg.max_num_buffers = max_fds; 521*76404edcSAsim Jamshed mtcp_setconf(&mcfg); 522*76404edcSAsim Jamshed 523*76404edcSAsim Jamshed flow_per_thread = total_flows / core_limit; 524*76404edcSAsim Jamshed flow_remainder_cnt = total_flows % core_limit; 525*76404edcSAsim Jamshed 526*76404edcSAsim Jamshed for (i = 0; i < MAX_CPUS; i++) { 527*76404edcSAsim Jamshed done[i] = FALSE; 528*76404edcSAsim Jamshed flows[i] = flow_per_thread; 529*76404edcSAsim Jamshed 530*76404edcSAsim Jamshed if (flow_remainder_cnt-- > 0) 531*76404edcSAsim Jamshed flows[i]++; 532*76404edcSAsim Jamshed } 533*76404edcSAsim Jamshed 534*76404edcSAsim Jamshed return; 535*76404edcSAsim Jamshed } 536*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 537*76404edcSAsim Jamshed static void 538*76404edcSAsim Jamshed InitWget(mctx_t mctx, void **app_ctx) 539*76404edcSAsim Jamshed { 540*76404edcSAsim Jamshed thread_context_t ctx; 541*76404edcSAsim Jamshed int ep; 542*76404edcSAsim Jamshed 543*76404edcSAsim Jamshed assert(mctx); 544*76404edcSAsim Jamshed 545*76404edcSAsim Jamshed int core = mctx->cpu; 546*76404edcSAsim Jamshed 547*76404edcSAsim Jamshed ctx = CreateContext(mctx); 548*76404edcSAsim Jamshed if (!ctx) 549*76404edcSAsim Jamshed exit(-1); 550*76404edcSAsim Jamshed g_ctx[core] = ctx; 551*76404edcSAsim Jamshed g_stat[core] = &ctx->stat; 552*76404edcSAsim Jamshed srand(time(NULL)); 553*76404edcSAsim Jamshed 554*76404edcSAsim Jamshed mtcp_init_rss(mctx, saddr, IP_RANGE, daddr, dport); 555*76404edcSAsim Jamshed 556*76404edcSAsim Jamshed if (flows[core] == 0) { 557*76404edcSAsim Jamshed TRACE_DBG("Application thread %d finished.\n", core); 558*76404edcSAsim Jamshed exit(-1); 559*76404edcSAsim Jamshed } 560*76404edcSAsim Jamshed ctx->target = flows[core]; 561*76404edcSAsim Jamshed 562*76404edcSAsim Jamshed /* Initialization */ 563*76404edcSAsim Jamshed ctx->maxevents = max_fds * 3; 564*76404edcSAsim Jamshed ep = mtcp_epoll_create(mctx, ctx->maxevents); 565*76404edcSAsim Jamshed if (ep < 0) { 566*76404edcSAsim Jamshed TRACE_ERROR("Failed to create epoll struct!n"); 567*76404edcSAsim Jamshed exit(EXIT_FAILURE); 568*76404edcSAsim Jamshed } 569*76404edcSAsim Jamshed ctx->events = (struct mtcp_epoll_event *) 570*76404edcSAsim Jamshed calloc(ctx->maxevents, sizeof(struct mtcp_epoll_event)); 571*76404edcSAsim Jamshed if (!ctx->events) { 572*76404edcSAsim Jamshed TRACE_ERROR("Failed to allocate events!\n"); 573*76404edcSAsim Jamshed exit(EXIT_FAILURE); 574*76404edcSAsim Jamshed } 575*76404edcSAsim Jamshed ctx->ep = ep; 576*76404edcSAsim Jamshed 577*76404edcSAsim Jamshed ctx->wvars = (struct wget_vars *)calloc(max_fds, sizeof(struct wget_vars)); 578*76404edcSAsim Jamshed if (!ctx->wvars) { 579*76404edcSAsim Jamshed TRACE_ERROR("Failed to create wget variables!\n"); 580*76404edcSAsim Jamshed exit(EXIT_FAILURE); 581*76404edcSAsim Jamshed } 582*76404edcSAsim Jamshed 583*76404edcSAsim Jamshed ctx->started = ctx->done = ctx->pending = 0; 584*76404edcSAsim Jamshed ctx->errors = ctx->incompletes = 0; 585*76404edcSAsim Jamshed 586*76404edcSAsim Jamshed *app_ctx = ctx; 587*76404edcSAsim Jamshed 588*76404edcSAsim Jamshed return; 589*76404edcSAsim Jamshed } 590*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 591*76404edcSAsim Jamshed static void 592*76404edcSAsim Jamshed RunWget(mctx_t mctx, void **app_ctx) 593*76404edcSAsim Jamshed { 594*76404edcSAsim Jamshed struct in_addr daddr_in; 595*76404edcSAsim Jamshed struct timeval cur_tv, prev_tv; 596*76404edcSAsim Jamshed int nevents; 597*76404edcSAsim Jamshed int i; 598*76404edcSAsim Jamshed 599*76404edcSAsim Jamshed assert(mctx); 600*76404edcSAsim Jamshed assert(*app_ctx); 601*76404edcSAsim Jamshed 602*76404edcSAsim Jamshed thread_context_t ctx = *app_ctx; 603*76404edcSAsim Jamshed int core = ctx->core; 604*76404edcSAsim Jamshed 605*76404edcSAsim Jamshed daddr_in.s_addr = daddr; 606*76404edcSAsim Jamshed fprintf(stderr, "Thread %d handles %d flows. connecting to %s:%u\n", 607*76404edcSAsim Jamshed core, flows[core], inet_ntoa(daddr_in), ntohs(dport)); 608*76404edcSAsim Jamshed 609*76404edcSAsim Jamshed gettimeofday(&cur_tv, NULL); 610*76404edcSAsim Jamshed prev_tv = cur_tv; 611*76404edcSAsim Jamshed 612*76404edcSAsim Jamshed while (!done[core]) { 613*76404edcSAsim Jamshed gettimeofday(&cur_tv, NULL); 614*76404edcSAsim Jamshed 615*76404edcSAsim Jamshed /* print statistics every second */ 616*76404edcSAsim Jamshed if (core == 0 && cur_tv.tv_sec > prev_tv.tv_sec) { 617*76404edcSAsim Jamshed PrintStats(); 618*76404edcSAsim Jamshed prev_tv = cur_tv; 619*76404edcSAsim Jamshed } 620*76404edcSAsim Jamshed 621*76404edcSAsim Jamshed while (/*ctx->pending*/ mtcp_get_connection_cnt(ctx->mctx) < concurrency && ctx->started < ctx->target) { 622*76404edcSAsim Jamshed if (CreateConnection(ctx) < 0) { 623*76404edcSAsim Jamshed done[core] = TRUE; 624*76404edcSAsim Jamshed break; 625*76404edcSAsim Jamshed } 626*76404edcSAsim Jamshed } 627*76404edcSAsim Jamshed 628*76404edcSAsim Jamshed nevents = mtcp_epoll_wait(mctx, ctx->ep, 629*76404edcSAsim Jamshed ctx->events, ctx->maxevents, ctx->pending ? -1 : 10); 630*76404edcSAsim Jamshed ctx->stat.waits++; 631*76404edcSAsim Jamshed 632*76404edcSAsim Jamshed if (nevents < 0) { 633*76404edcSAsim Jamshed if (errno != EINTR) { 634*76404edcSAsim Jamshed TRACE_ERROR("mtcp_epoll_wait failed! ret: %d\n", nevents); 635*76404edcSAsim Jamshed } 636*76404edcSAsim Jamshed done[core] = TRUE; 637*76404edcSAsim Jamshed break; 638*76404edcSAsim Jamshed } else { 639*76404edcSAsim Jamshed ctx->stat.events += nevents; 640*76404edcSAsim Jamshed } 641*76404edcSAsim Jamshed 642*76404edcSAsim Jamshed for (i = 0; i < nevents; i++) { 643*76404edcSAsim Jamshed 644*76404edcSAsim Jamshed if (ctx->events[i].events & MOS_EPOLLERR) { 645*76404edcSAsim Jamshed int err; 646*76404edcSAsim Jamshed socklen_t len = sizeof(err); 647*76404edcSAsim Jamshed 648*76404edcSAsim Jamshed TRACE_APP("[CPU %d] Error on socket %d\n", 649*76404edcSAsim Jamshed core, ctx->events[i].data.sockid); 650*76404edcSAsim Jamshed ctx->stat.errors++; 651*76404edcSAsim Jamshed ctx->errors++; 652*76404edcSAsim Jamshed if (mtcp_getsockopt(mctx, ctx->events[i].data.sock, 653*76404edcSAsim Jamshed SOL_SOCKET, SO_ERROR, (void *)&err, &len) == 0) { 654*76404edcSAsim Jamshed if (err == ETIMEDOUT) 655*76404edcSAsim Jamshed ctx->stat.timedout++; 656*76404edcSAsim Jamshed } 657*76404edcSAsim Jamshed CloseConnection(ctx, ctx->events[i].data.sock); 658*76404edcSAsim Jamshed 659*76404edcSAsim Jamshed } else if (ctx->events[i].events & MOS_EPOLLIN) { 660*76404edcSAsim Jamshed HandleReadEvent(ctx, 661*76404edcSAsim Jamshed ctx->events[i].data.sock, 662*76404edcSAsim Jamshed &ctx->wvars[ctx->events[i].data.sock]); 663*76404edcSAsim Jamshed 664*76404edcSAsim Jamshed } else if (ctx->events[i].events == MOS_EPOLLOUT) { 665*76404edcSAsim Jamshed struct wget_vars *wv = &ctx->wvars[ctx->events[i].data.sock]; 666*76404edcSAsim Jamshed 667*76404edcSAsim Jamshed if (!wv->request_sent) { 668*76404edcSAsim Jamshed SendHTTPRequest(ctx, ctx->events[i].data.sock, wv); 669*76404edcSAsim Jamshed } else { 670*76404edcSAsim Jamshed //TRACE_DBG("Request already sent.\n"); 671*76404edcSAsim Jamshed } 672*76404edcSAsim Jamshed 673*76404edcSAsim Jamshed } else { 674*76404edcSAsim Jamshed TRACE_ERROR("Socket %d: event: %s\n", 675*76404edcSAsim Jamshed ctx->events[i].data.sock, 676*76404edcSAsim Jamshed EventToString(ctx->events[i].events)); 677*76404edcSAsim Jamshed assert(0); 678*76404edcSAsim Jamshed } 679*76404edcSAsim Jamshed } 680*76404edcSAsim Jamshed 681*76404edcSAsim Jamshed if (ctx->done >= ctx->target) { 682*76404edcSAsim Jamshed fprintf(stdout, "Completed %d connections, " 683*76404edcSAsim Jamshed "errors: %d incompletes: %d\n", 684*76404edcSAsim Jamshed ctx->done, ctx->errors, ctx->incompletes); 685*76404edcSAsim Jamshed break; 686*76404edcSAsim Jamshed } 687*76404edcSAsim Jamshed } 688*76404edcSAsim Jamshed 689*76404edcSAsim Jamshed TRACE_INFO("Wget thread %d waiting for mtcp to be destroyed.\n", core); 690*76404edcSAsim Jamshed 691*76404edcSAsim Jamshed g_stat[core] = NULL; 692*76404edcSAsim Jamshed g_ctx[core] = NULL; 693*76404edcSAsim Jamshed DestroyContext(ctx); 694*76404edcSAsim Jamshed 695*76404edcSAsim Jamshed return; 696*76404edcSAsim Jamshed } 697*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 698*76404edcSAsim Jamshed void 699*76404edcSAsim Jamshed RunApplication(mctx_t mctx) 700*76404edcSAsim Jamshed { 701*76404edcSAsim Jamshed void *app_ctx; 702*76404edcSAsim Jamshed 703*76404edcSAsim Jamshed app_ctx = (void *)calloc(1, sizeof(void *)); 704*76404edcSAsim Jamshed if (!app_ctx) { 705*76404edcSAsim Jamshed TRACE_ERROR("calloc failure\n"); 706*76404edcSAsim Jamshed return; 707*76404edcSAsim Jamshed } 708*76404edcSAsim Jamshed 709*76404edcSAsim Jamshed TRACE_INFO("run application on core %d\n", mctx->cpu); 710*76404edcSAsim Jamshed InitWget(mctx, &(app_ctx)); 711*76404edcSAsim Jamshed RunWget(mctx, &(app_ctx)); 712*76404edcSAsim Jamshed } 713*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 714*76404edcSAsim Jamshed void * 715*76404edcSAsim Jamshed RunMTCP(void *arg) 716*76404edcSAsim Jamshed { 717*76404edcSAsim Jamshed int core = *(int *)arg; 718*76404edcSAsim Jamshed mctx_t mctx; 719*76404edcSAsim Jamshed 720*76404edcSAsim Jamshed mtcp_core_affinitize(core); 721*76404edcSAsim Jamshed 722*76404edcSAsim Jamshed /* mTCP Initialization */ 723*76404edcSAsim Jamshed mctx = mtcp_create_context(core); 724*76404edcSAsim Jamshed if (!mctx) { 725*76404edcSAsim Jamshed pthread_exit(NULL); 726*76404edcSAsim Jamshed TRACE_ERROR("Failed to craete mtcp context.\n"); 727*76404edcSAsim Jamshed return NULL; 728*76404edcSAsim Jamshed } 729*76404edcSAsim Jamshed 730*76404edcSAsim Jamshed /* Run application here */ 731*76404edcSAsim Jamshed RunApplication(mctx); 732*76404edcSAsim Jamshed 733*76404edcSAsim Jamshed /* mTCP Tear Down */ 734*76404edcSAsim Jamshed mtcp_destroy_context(mctx); 735*76404edcSAsim Jamshed pthread_exit(NULL); 736*76404edcSAsim Jamshed 737*76404edcSAsim Jamshed return NULL; 738*76404edcSAsim Jamshed } 739*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 740*76404edcSAsim Jamshed int 741*76404edcSAsim Jamshed main(int argc, char **argv) 742*76404edcSAsim Jamshed { 743*76404edcSAsim Jamshed int ret, i; 744*76404edcSAsim Jamshed int cores[MAX_CPUS]; 745*76404edcSAsim Jamshed char *fname = "config/mos.conf"; 746*76404edcSAsim Jamshed 747*76404edcSAsim Jamshed int opt; 748*76404edcSAsim Jamshed while ((opt = getopt(argc, argv, "f:")) != -1) { 749*76404edcSAsim Jamshed switch (opt) { 750*76404edcSAsim Jamshed case 'f': 751*76404edcSAsim Jamshed fname = optarg; 752*76404edcSAsim Jamshed break; 753*76404edcSAsim Jamshed default: 754*76404edcSAsim Jamshed printf("Usage: %s [-f config_file]\n", argv[0]); 755*76404edcSAsim Jamshed return 0; 756*76404edcSAsim Jamshed } 757*76404edcSAsim Jamshed 758*76404edcSAsim Jamshed } 759*76404edcSAsim Jamshed 760*76404edcSAsim Jamshed core_limit = sysconf(_SC_NPROCESSORS_ONLN); 761*76404edcSAsim Jamshed 762*76404edcSAsim Jamshed ret = mtcp_init(fname); 763*76404edcSAsim Jamshed if (ret) { 764*76404edcSAsim Jamshed TRACE_ERROR("Failed to initialize mtcp.\n"); 765*76404edcSAsim Jamshed exit(EXIT_FAILURE); 766*76404edcSAsim Jamshed } 767*76404edcSAsim Jamshed 768*76404edcSAsim Jamshed mtcp_getconf(&g_mcfg); 769*76404edcSAsim Jamshed 770*76404edcSAsim Jamshed core_limit = g_mcfg.num_cores; 771*76404edcSAsim Jamshed 772*76404edcSAsim Jamshed GlbInitWget(); 773*76404edcSAsim Jamshed 774*76404edcSAsim Jamshed for (i = 0; i < core_limit; i++) { 775*76404edcSAsim Jamshed cores[i] = i; 776*76404edcSAsim Jamshed 777*76404edcSAsim Jamshed /* Run mtcp thread */ 778*76404edcSAsim Jamshed if ((g_mcfg.cpu_mask & (1L << i)) && 779*76404edcSAsim Jamshed pthread_create(&mtcp_thread[i], NULL, RunMTCP, (void *)&cores[i])) { 780*76404edcSAsim Jamshed perror("pthread_create"); 781*76404edcSAsim Jamshed TRACE_ERROR("Failed to create msg_test thread.\n"); 782*76404edcSAsim Jamshed exit(-1); 783*76404edcSAsim Jamshed } 784*76404edcSAsim Jamshed } 785*76404edcSAsim Jamshed 786*76404edcSAsim Jamshed for (i = 0; i < core_limit; i++) { 787*76404edcSAsim Jamshed if (g_mcfg.cpu_mask & (1L << i)) 788*76404edcSAsim Jamshed pthread_join(mtcp_thread[i], NULL); 789*76404edcSAsim Jamshed TRACE_INFO("Message test thread %d joined.\n", i); 790*76404edcSAsim Jamshed } 791*76404edcSAsim Jamshed 792*76404edcSAsim Jamshed mtcp_destroy(); 793*76404edcSAsim Jamshed return 0; 794*76404edcSAsim Jamshed } 795*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 796