Beispiel #1
0
static void prepare_wfds(struct timespec *now, struct _flow *flow, fd_set *wfds)
{
	int rc = 0;

	if (flow_in_delay(now, flow, WRITE)) {
		DEBUG_MSG(LOG_WARNING, "flow %i not started yet (delayed)",
			  flow->id);
		return;
	}

	if (flow_sending(now, flow, WRITE)) {
#ifdef DEBUG
		assert(!flow->finished[WRITE]);
#endif
		if (flow_block_scheduled(now, flow)) {
			DEBUG_MSG(LOG_DEBUG, "adding sock of flow %d to wfds",
				  flow->id);
			FD_SET(flow->fd, wfds);
		} else {
			DEBUG_MSG(LOG_DEBUG, "no block for flow %d scheduled "
				  "yet", flow->id);
		}
	} else if (!flow->finished[WRITE]) {
		flow->finished[WRITE] = 1;
		if (flow->settings.shutdown) {
			DEBUG_MSG(LOG_WARNING, "shutting down flow %d (WR)",
				  flow->id);
			rc = shutdown(flow->fd,SHUT_WR);
			if (rc == -1)
				warn("shutdown() SHUT_WR failed");
		}
	}

	return;
}
Beispiel #2
0
static int prepare_rfds(struct timespec *now, struct flow *flow, fd_set *rfds)
{
	int rc = 0;

	if (!flow_in_delay(now, flow, READ) && !flow_sending(now, flow, READ)) {
		if (!flow->finished[READ] && flow->settings.shutdown) {
			warnx("server flow %u missed to shutdown", flow->id);
			rc = shutdown(flow->fd, SHUT_RD);
			if (rc == -1)
				warn("shutdown SHUT_RD failed");
			flow->finished[READ] = 1;
		}
	}

	if (flow->source_settings.late_connect && !flow->connect_called ) {
		DEBUG_MSG(LOG_ERR, "late connecting test socket for flow %d "
			  "after %.3fs delay",
			  flow->id, flow->settings.delay[WRITE]);
		if (do_connect(flow) == -1) {
			return -1;
		}
	}

	/* Altough the server flow might be finished we keep the socket in
	 * rfd in order to check for buggy servers */
	if (flow->connect_called && !flow->finished[READ]) {
		DEBUG_MSG(LOG_DEBUG, "adding sock of flow %d to rfds",
			  flow->id);
		FD_SET(flow->fd, rfds);
	}

	return 0;
}
Beispiel #3
0
/*
 * Prepare a report. type is either INTERVAL or FINAL
 */
static void report_flow(struct _flow* flow, int type)
{
	DEBUG_MSG(LOG_DEBUG, "report_flow called for flow %d (type %d)",
		  flow->id, type);
	struct _report* report =
		(struct _report*)malloc(sizeof(struct _report));

	report->id = flow->id;
	report->type = type;

	if (type == INTERVAL)
		report->begin = flow->last_report_time;
	else
		report->begin = flow->first_report_time;

	gettime(&report->end);
	flow->last_report_time = report->end;

	/* abort if we were scheduled way to early for a interval report */
	if (time_diff(&report->begin,&report->end) < 0.2 *
			flow->settings.reporting_interval && type == INTERVAL){
		free(report);
		return;
	}

	report->bytes_read = flow->statistics[type].bytes_read;
	report->bytes_written = flow->statistics[type].bytes_written;
	report->request_blocks_read =
		flow->statistics[type].request_blocks_read;
	report->response_blocks_read =
		flow->statistics[type].response_blocks_read;
	report->request_blocks_written =
		flow->statistics[type].request_blocks_written;
	report->response_blocks_written =
		flow->statistics[type].response_blocks_written;

	report->rtt_min = flow->statistics[type].rtt_min;
	report->rtt_max = flow->statistics[type].rtt_max;
	report->rtt_sum = flow->statistics[type].rtt_sum;
	report->iat_min = flow->statistics[type].iat_min;
	report->iat_max = flow->statistics[type].iat_max;
	report->iat_sum = flow->statistics[type].iat_sum;
	report->delay_min = flow->statistics[type].delay_min;
	report->delay_max = flow->statistics[type].delay_max;
	report->delay_sum = flow->statistics[type].delay_sum;

	/* Currently this will only contain useful information on Linux
	 * and FreeBSD */
	report->tcp_info = flow->statistics[type].tcp_info;

	if (flow->fd != -1) {
		/* Get latest MTU */
		flow->pmtu = get_pmtu(flow->fd);
		report->pmtu = flow->pmtu;
		if (type == FINAL)
			report->imtu = get_imtu(flow->fd);
		else
			report->imtu = 0;
	} else {
		report->imtu = 0;
		report->pmtu = 0;
	}
	/* Add status flags to report */
	report->status = 0;

	if (flow->statistics[type].bytes_read == 0) {
		if (flow_in_delay(&report->end, flow, READ))
			report->status |= 'd';
		else if (flow_sending(&report->end, flow, READ))
			report->status |= 'l';
		else if (flow->settings.duration[READ] == 0)
			report->status |= 'o';
		else
			report->status |= 'f';
	} else {
		if (!flow_sending(&report->end, flow, READ) && !flow->finished)
			report->status |= 'c';
		else
			report->status |= 'n';
	}
	report->status <<= 8;

	if (flow->statistics[type].bytes_written == 0) {
		if (flow_in_delay(&report->end, flow, WRITE))
			report->status |= 'd';
		else if (flow_sending(&report->end, flow, WRITE))
			report->status |= 'l';
		else if (flow->settings.duration[WRITE] == 0)
			report->status |= 'o';
		else
			report->status |= 'f';
	} else {
		if (!flow_sending(&report->end, flow, WRITE) && !flow->finished)
			report->status |= 'c';
		else
			report->status |= 'n';
	}

	/* New report interval, reset old data */
	if (type == INTERVAL) {
		flow->statistics[INTERVAL].bytes_read = 0;
		flow->statistics[INTERVAL].bytes_written = 0;

		flow->statistics[INTERVAL].request_blocks_read = 0;
		flow->statistics[INTERVAL].response_blocks_read = 0;

		flow->statistics[INTERVAL].request_blocks_written = 0;
		flow->statistics[INTERVAL].response_blocks_written = 0;

		flow->statistics[INTERVAL].rtt_min = FLT_MAX;
		flow->statistics[INTERVAL].rtt_max = FLT_MIN;
		flow->statistics[INTERVAL].rtt_sum = 0.0F;
		flow->statistics[INTERVAL].iat_min = FLT_MAX;
		flow->statistics[INTERVAL].iat_max = FLT_MIN;
		flow->statistics[INTERVAL].iat_sum = 0.0F;
		flow->statistics[INTERVAL].delay_min = FLT_MAX;
		flow->statistics[INTERVAL].delay_max = FLT_MIN;
		flow->statistics[INTERVAL].delay_sum = 0.0F;
	}

	add_report(report);
	DEBUG_MSG(LOG_DEBUG, "report_flow finished for flow %d (type %d)",
		  flow->id, type);
}
Beispiel #4
0
static int prepare_fds() {

	DEBUG_MSG(LOG_DEBUG, "prepare_fds() called, num_flows: %d", num_flows);
	unsigned int i = 0;

	FD_ZERO(&rfds);
	FD_ZERO(&wfds);
	FD_ZERO(&efds);

	FD_SET(daemon_pipe[0], &rfds);
	maxfd = daemon_pipe[0];

	struct timespec now;
	gettime(&now);

	while (i < num_flows) {
		struct _flow *flow = &flows[i++];

		if (started &&
		    (flow->finished[READ] ||
		     !flow->settings.duration[READ] ||
		     (!flow_in_delay(&now, flow, READ) &&
		      !flow_sending(&now, flow, READ))) &&
		    (flow->finished[WRITE] ||
		     !flow->settings.duration[WRITE] ||
		     (!flow_in_delay(&now, flow, WRITE) &&
		      !flow_sending(&now, flow, WRITE)))) {

			/* On Other OSes than Linux or FreeBSD, tcp_info will contain all zeroes */
			flow->statistics[FINAL].has_tcp_info =
				get_tcp_info(flow,
					     &flow->statistics[FINAL].tcp_info)
					? 0 : 1;

			flow->pmtu = get_pmtu(flow->fd);

			if (flow->settings.reporting_interval)
				report_flow(flow, INTERVAL);
			report_flow(flow, FINAL);
			uninit_flow(flow);
			remove_flow(--i);
			continue;
		}

		if (flow->state == GRIND_WAIT_ACCEPT &&
		    flow->listenfd_data != -1) {
			FD_SET(flow->listenfd_data, &rfds);
			maxfd = MAX(maxfd, flow->listenfd_data);
		}

		if (!started)
			continue;

		if (flow->fd != -1) {
			FD_SET(flow->fd, &efds);
			maxfd = MAX(maxfd, flow->fd);
			prepare_wfds(&now, flow, &wfds);
			prepare_rfds(&now, flow, &rfds);
		}
	}

	return num_flows;
}