Flowgrind
Advanced TCP traffic generator
source.c File Reference

Routines used by Flowgrind to setup the source for a test flow. More...

#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <strings.h>
#include <signal.h>
#include <string.h>
#include <fcntl.h>
#include <math.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
#include <time.h>
#include <syslog.h>
#include <sys/time.h>
#include <netdb.h>
#include <pthread.h>
#include <float.h>
#include "debug.h"
#include "fg_error.h"
#include "fg_math.h"
#include "fg_socket.h"
#include "fg_time.h"
#include "fg_log.h"
#include "fg_pcap.h"

Go to the source code of this file.

Functions

int add_flow_source (struct request_add_flow_source *request)
 To set daemon flow as source endpoint. More...
 
int do_connect (struct flow *flow)
 Establishes a connection of a flow. More...
 
int get_tcp_info (struct flow *flow, struct tcp_info *info)
 
void init_flow (struct flow *flow, int is_source)
 To initialize all flows to the default value. More...
 
static int name2socket (struct flow *flow, char *server_name, unsigned port, struct sockaddr **saptr, socklen_t *lenp, const int read_buffer_size_req, int *read_buffer_size, const int send_buffer_size_req, int *send_buffer_size)
 
void remove_flow (unsigned i)
 
void uninit_flow (struct flow *flow)
 

Detailed Description

Routines used by Flowgrind to setup the source for a test flow.

Definition in file source.c.

Function Documentation

int add_flow_source ( struct request_add_flow_source request)

To set daemon flow as source endpoint.

To set the flow options and settings as source endpoint. Depending upon the late connection option the data connection is established to connect the destination daemon listening port address with source daemon.

Parameters
[in,out]requestContain the test option and parameter for daemon source endpoint

Definition at line 177 of file source.c.

178 {
179 #ifdef HAVE_SO_TCP_CONGESTION
180  socklen_t opt_len = 0;
181 #endif /* HAVE_SO_TCP_CONGESTION */
182  struct flow *flow;
183 
185  logging(LOG_WARNING, "can not accept another flow, already "
186  "handling %zu flows", fg_list_size(&flows));
187  request_error(&request->r,
188  "Can not accept another flow, already "
189  "handling %zu flows.", fg_list_size(&flows));
190  return -1;
191  }
192 
193  flow = malloc(sizeof(struct flow));
194  if (!flow) {
195  logging(LOG_ALERT, "could not allocate memory for flow");
196  return -1;
197  }
198 
199  init_flow(flow, 1);
200 
201  flow->settings = request->settings;
202  flow->source_settings = request->source_settings;
203  /* be greedy with buffer sizes */
204  flow->write_block = calloc(1, flow->settings.maximum_block_size);
205  flow->read_block = calloc(1, flow->settings.maximum_block_size);
206  /* Controller flow ID is set in the daemon */
207  flow->id = flow->settings.flow_id;
208  if (flow->write_block == NULL || flow->read_block == NULL) {
209  logging(LOG_ALERT, "could not allocate memory for read/write "
210  "blocks");
211  request_error(&request->r, "could not allocate memory for read/write blocks");
212  uninit_flow(flow);
213  return -1;
214  }
215  if (flow->settings.byte_counting) {
216  int byte_idx;
217  for (byte_idx = 0; byte_idx < flow->settings.maximum_block_size; byte_idx++)
218  *(flow->write_block + byte_idx) = (unsigned char)(byte_idx & 0xff);
219  }
220 
221  flow->state = GRIND_WAIT_CONNECT;
222  flow->fd = name2socket(flow, flow->source_settings.destination_host,
224  &flow->addr, &flow->addr_len,
227  if (flow->fd == -1) {
228  logging(LOG_ALERT, "could not create data socket: %s",
229  flow->error);
230  request_error(&request->r, "Could not create data socket: %s", flow->error);
231  uninit_flow(flow);
232  return -1;
233  }
234 
235  if (set_flow_tcp_options(flow) == -1) {
236  request->r.error = flow->error;
237  flow->error = NULL;
238  uninit_flow(flow);
239  return -1;
240  }
241 
242 #ifdef HAVE_SO_TCP_CONGESTION
243  opt_len = sizeof(request->cc_alg);
244  if (getsockopt(flow->fd, IPPROTO_TCP, TCP_CONGESTION,
245  request->cc_alg, &opt_len) == -1) {
246  request_error(&request->r, "failed to determine actual congestion control algorithm: %s",
247  strerror(errno));
248  uninit_flow(flow);
249  return -1;
250  }
251 #endif /* HAVE_SO_TCP_CONGESTION */
252 
253 #ifdef HAVE_LIBPCAP
254  fg_pcap_go(flow);
255 #endif /* HAVE_LIBPCAP */
256  if (!flow->source_settings.late_connect) {
257  DEBUG_MSG(4, "(early) connecting test socket (fd=%u)", flow->fd);
258  if (do_connect(flow) == -1) {
259  request->r.error = flow->error;
260  flow->error = NULL;
261  uninit_flow(flow);
262  return -1;
263  }
264  }
265 
266  request->flow_id = flow->id;
267 
268  fg_list_push_back(&flows, flow);
269 
270  return 0;
271 }
int maximum_block_size
Application buffer size in bytes (option -U).
Definition: common.h:201
int requested_send_buffer_size
Request sender buffer in bytes (option -B).
Definition: common.h:196
void logging(int priority, const char *fmt,...)
Definition: fg_log.c:69
int set_flow_tcp_options(struct flow *flow)
Definition: daemon.c:1420
int do_connect(struct flow *flow)
Establishes a connection of a flow.
Definition: source.c:153
struct flow_source_settings source_settings
Definition: daemon.h:84
char destination_host[256]
Definition: daemon.h:65
void fg_pcap_go(struct flow *flow)
Start a tcpdump to capture traffic of the provided flow.
Definition: fg_pcap.c:314
void uninit_flow(struct flow *flow)
Definition: daemon.c:161
struct flow_settings settings
Definition: daemon.h:210
#define MAX_FLOWS_DAEMON
Maximal number of parallel flows supported by one daemon instance.
Definition: common.h:65
void init_flow(struct flow *flow, int is_source)
To initialize all flows to the default value.
Definition: daemon.c:892
struct flow_settings settings
Definition: daemon.h:83
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
char * read_block
Definition: daemon.h:97
char * error
Definition: daemon.h:187
char * write_block
Definition: daemon.h:98
char * error
Definition: daemon.h:170
int fg_list_push_back(struct linked_list *const list, void *const data)
Inserts a new element at the end of the list.
Definition: fg_list.c:167
int requested_read_buffer_size
Request receiver buffer, advertised window in bytes (option -W).
Definition: common.h:198
struct request r
Definition: daemon.h:208
struct sockaddr * addr
Definition: daemon.h:119
struct flow_source_settings source_settings
Definition: daemon.h:211
enum flow_state_t state
Definition: daemon.h:77
socklen_t addr_len
Definition: daemon.h:120
int fd
Definition: daemon.h:80
char cc_alg[TCP_CA_NAME_MAX]
Definition: daemon.h:215
int flow_id
Flow ID maintained by controller.
Definition: common.h:186
int byte_counting
Enumerate bytes in payload instead of sending zeros (option -E).
Definition: common.h:229
void request_error(struct request *request, const char *fmt,...)
Definition: daemon.c:128
Definition: daemon.h:73
size_t fg_list_size(struct linked_list *const list)
Returns the number of elements in the list.
Definition: fg_list.c:211
int id
Definition: daemon.h:75
static int name2socket(struct flow *flow, char *server_name, unsigned port, struct sockaddr **saptr, socklen_t *lenp, const int read_buffer_size_req, int *read_buffer_size, const int send_buffer_size_req, int *send_buffer_size)
Definition: source.c:76
struct linked_list flows
Definition: daemon.c:99
int do_connect ( struct flow flow)

Establishes a connection of a flow.

Establishes a connection to the destination daemon listening port, and marks the flow as connected.

Parameters
[in,out]flowFlow to connect.

Definition at line 153 of file source.c.

153  {
154  int rc;
155 
156  rc = connect(flow->fd, flow->addr, flow->addr_len);
157  if (rc == -1 && errno != EINPROGRESS) {
158  flow_error(flow, "connect() failed: %s",
159  strerror(errno));
160  err("failed to connect flow %u", flow->id);
161  return rc;
162  }
163  flow->connect_called = 1;
164  flow->pmtu = get_pmtu(flow->fd);
165  return 0;
166 }
int pmtu
Definition: daemon.h:114
#define err(...)
To report an error w/ the corresponding system error message.
Definition: fg_error.h:43
char connect_called
Definition: daemon.h:111
int get_pmtu(int fd)
Definition: fg_socket.c:193
struct sockaddr * addr
Definition: daemon.h:119
socklen_t addr_len
Definition: daemon.h:120
int fd
Definition: daemon.h:80
int id
Definition: daemon.h:75
void flow_error(struct flow *flow, const char *fmt,...)
Definition: daemon.c:115
int get_tcp_info ( struct flow flow,
struct tcp_info *  info 
)
void init_flow ( struct flow flow,
int  is_source 
)

To initialize all flows to the default value.

The daemon maintain all its data in its flow statistics data structure. These data are initialize to the default value or zero value according to their metrics details.

Parameters
[in,out]flowflow structure maintained by a daemon
[in]is_sourceto determine flow endpoint i.e. source or destination

Definition at line 892 of file daemon.c.

893 {
894  memset(flow, 0, sizeof(struct flow));
895 
896  /* flow id is given by controller */
897  flow->id = -1;
898  flow->endpoint = is_source ? SOURCE : DESTINATION;
899  flow->state = is_source ? GRIND_WAIT_CONNECT : GRIND_WAIT_ACCEPT;
900  flow->fd = -1;
901  flow->listenfd_data = -1;
902 
905 
906  flow->finished[READ] = flow->finished[WRITE] = 0;
907 
908  flow->addr = 0;
909 
910  foreach(int *i, INTERVAL, FINAL) {
911  flow->statistics[*i].bytes_read = 0;
912  flow->statistics[*i].bytes_written = 0;
913 
914  flow->statistics[*i].request_blocks_read = 0;
915  flow->statistics[*i].request_blocks_written = 0;
916  flow->statistics[*i].response_blocks_read = 0;
917  flow->statistics[*i].response_blocks_written = 0;
918 
919  flow->statistics[*i].rtt_min = FLT_MAX;
920  flow->statistics[*i].rtt_max = FLT_MIN;
921  flow->statistics[*i].rtt_sum = 0.0F;
922  flow->statistics[*i].iat_min = FLT_MAX;
923  flow->statistics[*i].iat_max = FLT_MIN;
924  flow->statistics[*i].iat_sum = 0.0F;
925  flow->statistics[*i].delay_min = FLT_MAX;
926  flow->statistics[*i].delay_max = FLT_MIN;
927  flow->statistics[*i].delay_sum = 0.0F;
928  }
929 
930  DEBUG_MSG(LOG_NOTICE, "called init flow %d", flow->id);
931 }
double delay_sum
Accumulated one-way delay.
Definition: daemon.h:148
unsigned request_blocks_read
Definition: daemon.h:130
unsigned current_read_block_size
Definition: daemon.h:101
unsigned request_blocks_written
Definition: daemon.h:131
enum endpoint_t endpoint
Definition: daemon.h:78
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
Endpoint that accepts the connection.
Definition: common.h:100
double iat_min
Minimum interarrival time.
Definition: daemon.h:138
#define MIN_BLOCK_SIZE
Minium block (message) size we can send.
Definition: common.h:79
unsigned current_write_block_size
Definition: daemon.h:100
double iat_sum
Accumulated interarrival time.
Definition: daemon.h:142
Endpoint that opens the connection.
Definition: common.h:98
double rtt_min
Minimum round-trip time.
Definition: daemon.h:150
unsigned response_blocks_read
Definition: daemon.h:132
int listenfd_data
Definition: daemon.h:81
struct sockaddr * addr
Definition: daemon.h:119
double delay_max
Maximum one-way delay.
Definition: daemon.h:146
unsigned response_blocks_written
Definition: daemon.h:133
unsigned long long bytes_written
Definition: daemon.h:125
double iat_max
Maximum interarrival time.
Definition: daemon.h:140
Final report.
Definition: common.h:116
enum flow_state_t state
Definition: daemon.h:77
int fd
Definition: daemon.h:80
Read operation.
Definition: common.h:108
char finished[2]
Definition: daemon.h:112
Write operation.
Definition: common.h:106
double rtt_sum
Accumulated round-trip time.
Definition: daemon.h:154
double delay_min
Minimum one-way delay.
Definition: daemon.h:144
struct flow::statistics statistics[2]
int id
Definition: daemon.h:75
double rtt_max
Maximum round-trip time.
Definition: daemon.h:152
unsigned long long bytes_read
Definition: daemon.h:124
Intermediated interval report.
Definition: common.h:114
static int name2socket ( struct flow flow,
char *  server_name,
unsigned  port,
struct sockaddr **  saptr,
socklen_t *  lenp,
const int  read_buffer_size_req,
int *  read_buffer_size,
const int  send_buffer_size_req,
int *  send_buffer_size 
)
static
Bug:
: currently we use portable select() API, which is limited by the number of bits in an fd_set

Definition at line 76 of file source.c.

80 {
81  int fd, n;
82  struct addrinfo hints, *res, *ressave;
83  char service[7];
84 
85  bzero(&hints, sizeof(struct addrinfo));
86  hints.ai_family = AF_UNSPEC;
87  hints.ai_socktype = SOCK_STREAM;
88 
89  snprintf(service, sizeof(service), "%u", port);
90 
91  if ((n = getaddrinfo(server_name, service, &hints, &res)) != 0) {
92  flow_error(flow, "getaddrinfo() failed: %s",
93  gai_strerror(n));
94  return -1;
95  }
96  ressave = res;
97 
98  do {
99 
100  fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
101 
102  if (fd < 0)
103  continue;
104  /* FIXME: currently we use portable select() API, which
105  * is limited by the number of bits in an fd_set */
106  if (fd >= FD_SETSIZE) {
107  logging(LOG_ALERT, "too many file descriptors are"
108  "already in use by this daemon");
109  flow_error(flow, "failed to create listen socket: too many"
110  "file descriptors in use by this daemon");
111  close(fd);
112  freeaddrinfo(ressave);
113  return -1;
114  }
115 
116  if (send_buffer_size)
117  *send_buffer_size = set_window_size_directed(fd, send_buffer_size_req, SO_SNDBUF);
118  if (read_buffer_size)
119  *read_buffer_size = set_window_size_directed(fd, read_buffer_size_req, SO_RCVBUF);
120 
121  break;
122 
123  } while ((res = res->ai_next) != NULL);
124 
125  if (res == NULL) {
126  flow_error(flow, "Could not create socket for "
127  "\"%s:%d\": %s", server_name, port, strerror(errno));
128  freeaddrinfo(ressave);
129  return -1;
130  }
131 
132  if (saptr && lenp) {
133  *saptr = malloc(res->ai_addrlen);
134  if (*saptr == NULL)
135  crit("malloc(): failed");
136  memcpy(*saptr, res->ai_addr, res->ai_addrlen);
137  *lenp = res->ai_addrlen;
138  }
139 
140  freeaddrinfo(ressave);
141 
142  return fd;
143 }
void logging(int priority, const char *fmt,...)
Definition: fg_log.c:69
static unsigned port
Definition: flowgrindd.c:95
#define crit(...)
To report an critical error w/ the corresponding system error message.
Definition: fg_error.h:36
int fd
Definition: daemon.h:80
int set_window_size_directed(int fd, int window, int direction)
Definition: fg_socket.c:78
void flow_error(struct flow *flow, const char *fmt,...)
Definition: daemon.c:115
void remove_flow ( unsigned  i)
void uninit_flow ( struct flow flow)

Definition at line 161 of file daemon.c.

162 {
163  DEBUG_MSG(LOG_DEBUG,"uninit_flow() called for flow %d",flow->id);
164  if (flow->fd != -1)
165  close(flow->fd);
166  if (flow->listenfd_data != -1)
167  close(flow->listenfd_data);
168 #ifdef HAVE_LIBPCAP
169  int rc;
170  if (flow->settings.traffic_dump && flow->pcap_thread) {
171  rc = pthread_cancel(flow->pcap_thread);
172  if (rc)
173  logging(LOG_WARNING, "failed to cancel dump thread: %s",
174  strerror(rc));
175 
176  /* wait for the dump thread to react to the cancellation request */
177  rc = pthread_join(flow->pcap_thread, NULL);
178  if (rc)
179  logging(LOG_WARNING, "failed to join dump thread: %s",
180  strerror(rc));
181  }
182 #endif /* HAVE_LIBPCAP */
183  free_all(flow->read_block, flow->write_block, flow->addr, flow->error);
184  free_math_functions(flow);
185 }
void logging(int priority, const char *fmt,...)
Definition: fg_log.c:69
struct flow_settings settings
Definition: daemon.h:83
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
char * read_block
Definition: daemon.h:97
char * write_block
Definition: daemon.h:98
char * error
Definition: daemon.h:170
#define free_all(...)
To free() an arbitrary number of variables.
int listenfd_data
Definition: daemon.h:81
struct sockaddr * addr
Definition: daemon.h:119
int fd
Definition: daemon.h:80
int traffic_dump
Dump traffic using libpcap (option -M).
Definition: common.h:204
pthread_t pcap_thread
Definition: daemon.h:161
void free_math_functions(struct flow *flow)
Definition: fg_math.c:97
int id
Definition: daemon.h:75