void dump(upro_collector_context_t *context) { int ret; int queue_id = context->queue_id; upro_collector_t *cc = &(collectors[context->id]); assert(ps_init_handle(&(cc->handle)) == 0); struct ps_queue queue; queue.ifindex = context->ifindex; queue.qidx = queue_id; printf("[Collector %d] is attaching if:queue %d:%d ...\n", context->id, queue.ifindex, queue.qidx); assert(ps_attach_rx_device(&(cc->handle), &queue) == 0); struct ps_chunk chunk; assert(ps_alloc_chunk(&(cc->handle), &chunk) == 0); chunk.recv_blocking = 1; gettimeofday(&(cc->startime), NULL); for (;;) { chunk.cnt = config->io_batch_num; ret = ps_recv_chunk(&(cc->handle), &chunk); if (ret < 0) { if (errno == EINTR) continue; assert(0); } cc->total_packets += ret; cc->total_bytes += ret * 1370; continue; } }
/*----------------------------------------------------------------------------*/ void psio_init_handle(struct mtcp_thread_context *ctxt) { int i, ret; struct psio_private_context *ppc; struct timeval cur_ts; /* create and initialize private I/O module context */ ctxt->io_private_context = calloc(1, sizeof(struct psio_private_context)); if (ctxt->io_private_context == NULL) { TRACE_ERROR("Failed to initialize ctxt->io_private_context: " "Can't allocate memory\n"); exit(EXIT_FAILURE); } ppc = (struct psio_private_context *)ctxt->io_private_context; if (ps_init_handle(&ppc->handle)) { perror("ps_init_handle"); TRACE_ERROR("Failed to initialize ps handle.\n"); exit(EXIT_FAILURE); } /* create buffer for reading ingress batch of packet */ if (ps_alloc_chunk(&ppc->handle, &ppc->chunk) != 0) { perror("ps_alloc_chunk"); TRACE_ERROR("Failed to allocate ps_chunk\n"); exit(EXIT_FAILURE); } /* create packet write chunk */ for (i = 0; i < num_devices_attached; i++) { ret = ps_alloc_chunk_buf(&ppc->handle, i, ctxt->cpu, &ppc->w_chunk_buf[i]); if (ret != 0) { TRACE_ERROR("Failed to allocate ps_chunk_buf.\n"); exit(EXIT_FAILURE); } } gettimeofday(&cur_ts, NULL); /* initialize PSIO parameters */ ppc->chunk.recv_blocking = 0; ppc->event.timeout = PS_SELECT_TIMEOUT; ppc->event.qidx = ctxt->cpu; NID_ZERO(ppc->event.rx_nids); NID_ZERO(ppc->event.tx_nids); NID_ZERO(ppc->rx_avail); //NID_ZERO(ppc->tx_avail); for (i = 0; i < CONFIG.eths_num; i++) { ppc->last_tx_set[i] = cur_ts; NID_SET(i, ppc->tx_avail); } }
void dump() { int ret; struct ps_chunk chunk; char flag = 0; struct ps_handle* handle = &handles[my_cpu]; chunk.queue.ifindex = devices_attached[0]; chunk.queue.qidx = my_cpu; ret = ps_alloc_chunk(handle, &chunk); if (ret != 0) { perror("ps_alloc_chunk"); exit(1); } chunk.cnt = 128; /* no batching */ chunk.recv_blocking = 1; for (;;) { int ret = ps_recv_chunk(handle, &chunk); if (ret < 0) { if (errno == EINTR){ printf("dump errno == EINTR\n"); continue; } if (!chunk.recv_blocking && errno == EWOULDBLOCK){ printf("dump !chunk.recv_blocking && errno == EWOULDBLOCK\n"); break; } assert(0); } if(ret > 0) { if(!flag) { flag = 1; gettimeofday(&start, NULL); } else stat_signal(0); chunk.retcnt = ret; chunk.front = (chunk.front + ret) & (MAX_CHUNK_SIZE - 1); } } }
/* XXX - ignored at the moment (this is disabled by default) */ inline void InitWriteChunks(struct ps_handle* handle, struct ps_chunk *w_chunk) { int i, ret; for (i = 0; i < ETH_NUM; i++) { ret = ps_alloc_chunk(handle, &w_chunk[i]); if (ret != 0) { perror("ps_alloc_chunk"); exit(1); } w_chunk[i].queue.ifindex = i; w_chunk[i].recv_blocking = 0; w_chunk[i].cnt = 0; } }
void echo() { struct ps_handle *handle = &handles[my_cpu]; struct ps_chunk chunk; int i; int working = 0; assert(ps_init_handle(handle) == 0); for (i = 0; i < num_devices_attached; i++) { struct ps_queue queue; if (devices[devices_attached[i]].num_rx_queues <= my_cpu) continue; if (devices[devices_attached[i]].num_tx_queues <= my_cpu) { printf("WARNING: xge%d has not enough TX queues!\n", devices_attached[i]); continue; } working = 1; queue.ifindex = devices_attached[i]; queue.qidx = my_cpu; printf("attaching RX queue xge%d:%d to CPU%d\n", queue.ifindex, queue.qidx, my_cpu); assert(ps_attach_rx_device(handle, &queue) == 0); } if (!working) goto done; assert(ps_alloc_chunk(handle, &chunk) == 0); chunk.recv_blocking = 1; for (;;) { int ret; chunk.cnt = 64; ret = ps_recv_chunk(handle, &chunk); if (ret < 0) { if (errno == EINTR) continue; if (!chunk.recv_blocking && errno == EWOULDBLOCK) break; assert(0); } if (!sink) { chunk.cnt = ret; ret = ps_send_chunk(handle, &chunk); assert(ret >= 0); } } done: ps_close_handle(handle); }
void send_packets(long packets, int chunk_size, int packet_size, int num_flows) { struct ps_handle *handle = &handles[my_cpu]; struct ps_chunk chunk; char packet[MAX_FLOWS][MAX_PACKET_SIZE]; int ret; int i, j; unsigned int next_flow[MAX_DEVICES]; long sent = 0; uint64_t seed = 0; if (num_flows == 0) seed = time(NULL) + my_cpu; for (i = 0; i < num_flows; i++) { if (ip_version == 4) build_packet(packet[i], packet_size, &seed); else if (ip_version == 6) build_packet_v6(packet[i], packet_size, &seed); } assert(ps_init_handle(handle) == 0); for (i = 0; i < num_devices_registered; i++) next_flow[i] = 0; assert(ps_alloc_chunk(handle, &chunk) == 0); chunk.queue.qidx = my_cpu; /* CPU_i holds queue_i */ assert(chunk.info); while (1) { int working = 0; for (i = 0; i < num_devices_registered; i++) { chunk.queue.ifindex = devices_registered[i]; working = 1; for (j = 0; j < chunk_size; j++) { chunk.info[j].len = packet_size; chunk.info[j].offset = j * ALIGN(packet_size, 64); if (num_flows == 0) { if (ip_version == 4) { build_packet(chunk.buf + chunk.info[j].offset, packet_size, &seed); } else { build_packet_v6(chunk.buf + chunk.info[j].offset, packet_size, &seed); } } else memcpy_aligned(chunk.buf + chunk.info[j].offset, packet[(next_flow[i] + j) % num_flows], packet_size); } if (packets - sent < chunk_size) chunk.cnt = packets - sent; else chunk.cnt = chunk_size; ret = ps_send_chunk(handle, &chunk); assert(ret >= 0); update_stats(handle); sent += ret; if (packets <= sent) done(); if (num_flows) next_flow[i] = (next_flow[i] + ret) % num_flows; } if (!working) break; } ps_close_handle(handle); }
void dump() { int ret; struct ps_chunk chunk; ret = ps_alloc_chunk(&handle, &chunk); if (ret != 0) { perror("ps_alloc_chunk"); exit(1); } chunk.cnt = 128; /* no batching */ chunk.recv_blocking = 1; gettimeofday(&startime, NULL); for (;;) { int ret = ps_recv_chunk(&handle, &chunk); //printf("%d pkts from queue %d\n", chunk.cnt, chunk.queue.qidx); if (ret < 0) { if (errno == EINTR) continue; if (!chunk.recv_blocking && errno == EWOULDBLOCK) break; assert(0); } if (ret > 0) { printf("%d ", ret); } /* if (ret > 0) { struct ps_packet packet; printf("%s:%d ", devices[chunk.queue.ifindex].name, chunk.queue.qidx); dump_packet(chunk.buf + chunk.info[0].offset, chunk.info[0].len); packet.arrived_ifindex = chunk.queue.ifindex; packet.len = chunk.info[0].len; packet.buf = chunk.buf + chunk.info[0].offset; assert(ps_slowpath_packet(&handle, &packet) == 0); } printf("--> %d\n", chunk.queue.qidx); chunk.cnt = 1; */ //assert(chunk.cnt == 128); /* if (chunk.cnt != 128) printf("(%d)", chunk.cnt); int i, j=0; for (i = 0; i < chunk.cnt; i ++) { //assert(chunk.info[i].len != 0); if (chunk.info[i].len == 0) { printf("#%d", i); j = 1; } //else printf("0"); } if (j == 1) printf("\n"); */ } }
int fire_worker_start(int queue_id) { int ret, i, j, k, prot, send_ret; fire_worker_t *cc = &(workers[queue_id]); assert(ps_init_handle(&(cc->server_handle)) == 0); assert(ps_init_handle(&(cc->client_handle)) == 0); struct ps_queue server_queue, client_queue; server_queue.ifindex = config->server_ifindex; server_queue.qidx = queue_id; client_queue.ifindex = config->client_ifindex; client_queue.qidx = queue_id; assert(ps_attach_rx_device(&(cc->server_handle), &server_queue) == 0); assert(ps_attach_rx_device(&(cc->client_handle), &client_queue) == 0); struct ps_chunk client_chunk, send_client_chunk, server_chunk, send_server_chunk; assert(ps_alloc_chunk(&(cc->client_handle), &client_chunk) == 0); assert(ps_alloc_chunk(&(cc->client_handle), &send_client_chunk) == 0); assert(ps_alloc_chunk(&(cc->server_handle), &server_chunk) == 0); assert(ps_alloc_chunk(&(cc->server_handle), &send_server_chunk) == 0); client_chunk.queue.ifindex = config->client_ifindex; client_chunk.queue.qidx = queue_id; send_client_chunk.queue.ifindex = config->client_ifindex; send_client_chunk.queue.qidx = queue_id; server_chunk.queue.ifindex = config->server_ifindex; server_chunk.queue.qidx = queue_id; send_server_chunk.queue.ifindex = config->server_ifindex; send_server_chunk.queue.qidx = queue_id; int num_pkt_to_client = 0, num_pkt_to_server = 0; int pret; gettimeofday(&(cc->startime), NULL); #if defined(HIPAC_TCB) int hipac_cnt = 0; #endif for (;;) { num_pkt_to_client = 0; num_pkt_to_server = 0; j = 0; k = 0; client_chunk.cnt = config->io_batch_num; client_chunk.recv_blocking = 0; ret = ps_recv_chunk(&(cc->client_handle), &client_chunk); if (ret <= 0) { /* Receive nothing from server, go to the start of the loop to process client again */ goto process_server; } cc->total_packets += ret; int action; for (i = 0; i < ret; i ++) { prot = process_packet(client_chunk.buf + client_chunk.info[i].offset, client_chunk.info[i].len); switch (prot) { case TCP_SYN_SENT: action = HiPAC(client_chunk.buf + client_chunk.info[i].offset, client_chunk.info[i].len, l); if(action == FORWARD) { // first handshake packet // construct the response, and send back to client //fprint(INFO, "1) TCP_SYN_SENT\n"); send_client_chunk.info[j].len = client_chunk.info[i].len; send_client_chunk.info[j].offset = j * PS_MAX_PACKET_SIZE; memcpy(send_client_chunk.buf + send_client_chunk.info[j].offset, client_chunk.buf + client_chunk.info[i].offset, client_chunk.info[i].len); form_syn_response(send_client_chunk.buf + send_client_chunk.info[j].offset, send_client_chunk.info[j].len); pret = process_packet(send_client_chunk.buf + send_client_chunk.info[j].offset, send_client_chunk.info[j].len); #if 0 if(pret != TCP_SYN_RECV){ printf("pret is %d\n", pret); printf("client:\n"); dmesg(client_chunk.buf + client_chunk.info[i].offset); printf("server:\n"); dmesg(send_client_chunk.buf + send_client_chunk.info[j].offset); exit(0); } #endif assert(pret == TCP_SYN_RECV); //fprint(INFO, "2) TCP_SYN_RECV\n"); j ++; } else{ // hipac_cnt ++; // if(hipac_cnt > 0) printf("hipac filter : %d\n", hipac_cnt); delete_tcp(client_chunk.buf + client_chunk.info[i].offset); } break; case TCP_ESTABLISHED: // the 3rd handshake packet // do nothing and wait for client's real request //fprint(INFO, "3) TCP_ESTABLISHED\n"); break; case -2: //fprint(INFO, "two buckets full\n"); break; case -1: //fprint(INFO, "Error pkt, don't forward to server.\n"); break; default: // normal packet, send to server //fprint(INFO, "4) Normal packet, send to server\n"); send_server_chunk.info[k].len = client_chunk.info[i].len; send_server_chunk.info[k].offset = k * PS_MAX_PACKET_SIZE; memcpy(send_server_chunk.buf + send_server_chunk.info[k].offset, client_chunk.buf + client_chunk.info[i].offset, client_chunk.info[i].len); k ++; break; } cc->total_bytes += client_chunk.info[i].len; } if (j > 0) { //fprint(INFO, "sending %d SYN/ACK packet to client, queue_id %d, ifindex %d\n", j, queue_id, config->client_ifindex); send_client_chunk.cnt = j; send_ret = ps_send_chunk(&(cc->client_handle), &send_client_chunk); if (send_ret < 0) fprint(ERROR, "send packet fail, ret = %d\n", send_ret); } if (k > 0) { //fprint(INFO, "sending %d packets of established connection to server, queue_id %d, ifindex %d\n", k, queue_id, config->server_ifindex); send_server_chunk.cnt = k; send_ret = ps_send_chunk(&(cc->server_handle), &send_server_chunk); if (send_ret < 0) fprint(ERROR, "send packet fail, ret = %d\n", send_ret); } #if 0 /* FIXME: cannot send all packets while (ret > 0) { chunk.cnt = ret; send_ret = ps_send_chunk(&(cc->handle), &send_chunk); if (send_ret < 0) fprint(ERROR, "send packet fail, ret = %d\n", send_ret); ret -= send_ret; //assert(ret >= 0); }*/ #endif process_server: /*----------------------------------------------------------------------------------*/ /* Now process server side packet*/ server_chunk.cnt = config->io_batch_num; //server_chunk.recv_blocking = 0; //modify at the frist time server_chunk.recv_blocking = 0; j = 0; ret = ps_recv_chunk(&(cc->server_handle), &server_chunk); if (ret <= 0) { if (errno == EINTR) continue; /* Receive nothing from server, go to the start of the loop to process client again */ continue; } for (i = 0; i < ret; i ++) { prot = process_packet(server_chunk.buf + server_chunk.info[i].offset, server_chunk.info[i].len); if (prot == 0) { send_client_chunk.info[j].len = server_chunk.info[i].len; send_client_chunk.info[j].offset = j * PS_MAX_PACKET_SIZE; memcpy(send_client_chunk.buf + send_client_chunk.info[j].offset, server_chunk.buf + server_chunk.info[i].offset, server_chunk.info[i].len); j ++; } else { fprint(ERROR, "wrong packet from server\n"); } } if (j > 0) { fprint(DEBUG, "sending packet, queue_id %d, num %d, index %d\n", queue_id, ret, config->client_ifindex); send_client_chunk.cnt = j; send_ret = ps_send_chunk(&(cc->client_handle), &send_client_chunk); if (send_ret < 0) fprint(ERROR, "send packet fail, ret = %d\n", send_ret); } } return 0; }
void echo() { struct ps_handle *handle = &handles[my_cpu]; struct ps_chunk chunk; int i; int working = 0; assert(ps_init_handle(handle) == 0); for (i = 0; i < num_devices_attached; i++) { struct ps_queue queue; if (devices[devices_attached[i]].num_rx_queues <= my_cpu) continue; if (devices[devices_attached[i]].num_tx_queues <= my_cpu) { printf("WARNING: xge%d has not enough TX queues!\n", devices_attached[i]); continue; } working = 1; queue.ifindex = devices_attached[i]; queue.qidx = my_cpu; printf("attaching RX queue xge%d:%d to CPU%d\n", queue.ifindex, queue.qidx, my_cpu); assert(ps_attach_rx_device(handle, &queue) == 0); } if (!working) goto done; assert(ps_alloc_chunk(handle, &chunk) == 0); chunk.recv_blocking = 1; for (;;) { int ret, i, j; struct ethhdr *eth; chunk.cnt = 64; ret = ps_recv_chunk(handle, &chunk); if (ret < 0) { if (errno == EINTR) continue; if (!chunk.recv_blocking && errno == EWOULDBLOCK) break; assert(0); } if (!echo_as_is) { for (i = 0; i < ret; i++) { char tmp[6]; bool drop = true; eth = (struct ethhdr *)chunk.buf + chunk.info[i].offset; if (!sink) for (j = 0; j < num_devices_attached; j++) { drop &= !(memcmp(devices[j].dev_addr, eth->h_dest, ETH_ALEN) == 0); } if (drop) { chunk.info[i].offset = -1; } else { memcpy(tmp, eth->h_dest, 6); memcpy(eth->h_dest, eth->h_source, 6); memcpy(eth->h_source, tmp, 6); } } } if (!sink) { chunk.cnt = ret; ret = ps_send_chunk(handle, &chunk); assert(ret >= 0); } } done: ps_close_handle(handle); }