Example #1
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);
}
Example #2
0
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);
}
Example #3
0
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;
}
Example #4
0
/*----------------------------------------------------------------------------*/
int
FlushWriteBuffer(struct mtcp_thread_context* ctx, int ifidx)
{
	int ret = 0;
	struct ps_chunk* w_chunk = ctx->w_chunk;
	mtcp_manager_t mtcp = ctx->mtcp_manager;
	int i;
	int drop = 0;
	assert(ctx != NULL);
	assert(w_chunk != NULL);
			
	if (w_chunk[ifidx].cnt > 0) {

		STAT_COUNT(mtcp->runstat.rounds_tx_try);

		ret = ps_send_chunk(ctx->handle, &w_chunk[ifidx]);
		drop = ctx->w_chunk[ifidx].cnt - ret;

		if (ret < 0) {
			TRACE_ERROR("ps_send_chunk failed to send chunks, %d:%d\n", 
					ifidx, w_chunk[ifidx].cnt);
			return ret;
		} else {
#ifdef NETSTAT
			mtcp->nstat.tx_packets[ifidx] += ret;
#endif /* NETSTAT */

			for (i = 0; i < ret; i++) {
#ifdef PKTDUMP
				DumpPacket(mtcp, 
						w_chunk[ifidx].buf + w_chunk[ifidx].info[i].offset, 
						w_chunk[ifidx].info[i].len, "OUT", ifidx);
#endif /* PKTDUMP */

#ifdef NETSTAT
				mtcp->nstat.tx_bytes[ifidx] += w_chunk[ifidx].info[i].len + 24;
#endif /* NETSTAT */
			}

#ifdef NETSTAT
			if (ret != w_chunk[ifidx].cnt) {
				mtcp->nstat.tx_drops[ifidx] += (w_chunk[ifidx].cnt - ret);
			}
#endif /* NETSTAT */

			if (ret == 0) {
				return ret;
			}
		}
		
#ifdef PKTDUMP
		thread_printf(mtcp, mtcp->log_fp, "sent chunks, ret: %d (tries: %d)\n", 
				ret, w_chunk[ifidx].cnt);
		thread_printf(mtcp, mtcp->log_fp, "======================================"
					"======================================================"
					"====================\n\n");
#endif /* PKTDUMP */

		if (drop > 0) {
			ctx->w_chunk[ifidx].cnt = drop;
			for (i = 0; i < drop; i++) {
				ctx->w_chunk[ifidx].info[i].len = 
						ctx->w_chunk[ifidx].info[ret + i].len;
				ctx->w_chunk[ifidx].info[i].offset = 
					ctx->w_chunk[ifidx].info[ret + i].offset;
			}
			ctx->w_off[ifidx] = ctx->w_chunk[ifidx].info[drop - 1].offset +
					(ctx->w_chunk[ifidx].info[drop - 1].len + 63) / 64 * 64;
			ctx->w_cur_idx[ifidx] += ret;
		} else {
			ctx->w_chunk[ifidx].cnt = 0;
			ctx->w_off[ifidx] = 0;
			ctx->w_cur_idx[ifidx] = 0;
		}

	}

	return ret;
}
Example #5
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);
}