Commit 50c40e8a authored by 's avatar
Browse files

Major clean up of code, testing in progress.


git-svn-id: file:///home/svn/mapi/trunk@344 8d5bb341-7cf1-0310-8cf6-ba355fef3186
parent bab33b6d
......@@ -9,9 +9,8 @@ LIB_DIRS=
RLIB_DIRS=
INCLUDE_DIRS=
TARGETS=abw_measure abw_dummy test_abw_time test_config
OBJS=abw_measure.o abw_mysql.o abw_time.o abw_dummy.o test_abw_time.o \
test_config.o abw_conf.o
TARGETS=abw abw_measure abw_dummy test_abw_time test_config
# OBJS=abw.o abw_common.o abw_measure.o abw_mysql.o abw_time.o abw_dummy.o test_abw_time.o test_config.o abw_conf.o
all: $(TARGETS)
......@@ -22,8 +21,11 @@ all: $(TARGETS)
# $(AR) rv $@ $(LIBSCAMPI_OBJS)
# $(RANLIB) $@
abw_measure: abw_measure.o abw_mysql.o abw_time.o abw_conf.o
$(LD) -o $@ abw.o abw_mysql.o abw_time.o abw_conf.o $(LIB_DIRS) $(LIBS) -Wl,-rpath,$(RLIB_DIRS)
abw: abw.o abw_common.o abw_mysql.o abw_time.o abw_conf.o
$(LD) -o $@ abw.o abw_common.o abw_mysql.o abw_time.o abw_conf.o $(LIB_DIRS) $(LIBS) -Wl,-rpath,$(RLIB_DIRS)
abw_measure: abw_measure.o abw_common.o abw_mysql.o abw_time.o abw_conf.o
$(LD) -o $@ abw_measure.o abw_common.o abw_mysql.o abw_time.o abw_conf.o $(LIB_DIRS) $(LIBS) -Wl,-rpath,$(RLIB_DIRS)
abw_dummy: abw_dummy.o
$(LD) -o $@ abw_dummy.o $(LIB_DIRS) $(LIBS) -Wl,-rpath,$(RLIB_DIRS)
......
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <unistd.h>
#define __USE_XOPEN
#include <time.h>
#include <sys/time.h>
......@@ -16,319 +16,108 @@
#include "abw_time.h"
#include "abw_conf.h"
flow_spec_t *flow_spec[MAX_FLOWS];
global_spec_t global_spec;
flow_run_t *flow_run[MAX_FLOWS];
void usage() {
char *progname="abw";
fprintf(stderr, "%s: Usage: %s [options] [header_filter]\n", progname, progname);
fprintf(stderr, " -d device device (e.g., /dev/combosix/0, /dev/dag0, default %s)\n", DEFAULT_DEVICE);
fprintf(stderr, " -m {d | b | p} sampling mode (default deterministic)\n");
fprintf(stderr, " d - deterministic\n");
fprintf(stderr, " b - byte deterministic\n");
fprintf(stderr, " p - probabilistic\n");
fprintf(stderr, " -r threshold pass packet when threshold is reached\n");
fprintf(stderr, " number of packets for d mode (default 1)\n");
fprintf(stderr, " number of bytes for b mode (default 3000)\n");
fprintf(stderr, " pass probability for p mode (default 0.5)\n");
fprintf(stderr, " -p string string to be searched in payload, multiple -p arguments\n");
fprintf(stderr, " can be specified, packet passes when at least one match\n");
fprintf(stderr, " -c characteristics comma-separated list of characteristics (default all)\n");
fprintf(stderr, " -f filename file to read multi-flow specification (e.g., abw.cfg)\n");
fprintf(stderr, " -i interval seconds between measurements (default 1)\n");
fprintf(stderr, " -s DD.MM.YYYY-HH:MM:SS start time (default %s)\n", DEFAULT_START_TIME_STRING);
fprintf(stderr, " -e DD.MM.YYYY-HH:MM:SS end time (default %s)\n", DEFAULT_END_TIME_STRING);
fprintf(stderr, " -l mbps link installed bandwidth (default %d)\n", DEFAULT_LINK_MBPS);
fprintf(stderr, " -q quiet - do not print results on stdout\n");
fprintf(stderr, " -b do not insert results into MySQL dataBase\n");
fprintf(stderr, " -h this help message\n");
exit(-1);
}
flow_spec_t *new_flow_spec(void) {
flow_spec_t *p;
if ((p=malloc(sizeof(flow_spec_t)))==NULL) {
fprintf(stderr, "%s: malloc() failed\n", __func__);
return NULL;
}
memset(p, 0, sizeof(flow_spec_t));
p->device=DEFAULT_DEVICE;
p->header_filter[0]='\0';
p->sau_mode='d';
p->sau_packet_threshold=1;
p->sau_byte_threshold=3000;
p->sau_pass_probability=0.5;
p->payload_strings_no=0;
p->characteristics=NULL;
p->interval.tv_sec=1;
p->interval.tv_usec=0;
p->start_time_string=DEFAULT_START_TIME_STRING;
p->end_time_string=DEFAULT_END_TIME_STRING;
p->link_mbps=DEFAULT_LINK_MBPS;
return p;
} /* new_flow_spec() */
flow_run_t *new_flow_run(void) {
flow_run_t *p;
if ((p=malloc(sizeof(flow_run_t)))==NULL) {
fprintf(stderr, "%s: malloc() failed\n", __func__);
return NULL;
}
memset(p, 0, sizeof(flow_run_t));
return p;
} /* new_flow_run() */
flow_spec_t *flow_spec[MAX_FLOWS];
int main(int argc, char *argv[])
{
int i;
int opt;
int i, j;
struct timeval tm;
struct timezone tz;
/* int payload_strings_no; */
int direct_flow;
flow_spec_t **pp;
flow_spec_t *p;
flow_run_t **qq;
flow_run_t *q;
struct timeval next, wait;
/* Set initial values */
global_spec.conf_filename=NULL;
/* TODO get the following MySQL settings from configuration */
global_spec.user="abw";
global_spec.passwd="lab10";
global_spec.db="abw";
int subject_id, parameters_id;
if (gethostname(global_spec.hostname, MAX_HOSTNAME+1)<0) {
fprintf(stderr, "%s: gethostname() failed\n", __func__);
exit(-1);
}
{ char domainname[MAX_HOSTNAME+1];
if (getdomainname(domainname, MAX_HOSTNAME+1)<0) {
if (!strchr(global_spec.hostname, ',')) {
char domainname[MAX_HOSTNAME+1];
if (getdomainname(domainname, MAX_HOSTNAME+1)<0) {
fprintf(stderr, "%s: getdomainname() failed\n", __func__);
exit(-1);
}
strcat(global_spec.hostname, domainname);
}
if (strlen(domainname))
strcat(global_spec.hostname, domainname);
else
fprintf(stderr, "%s: WARNING: could not obtain local domain name, local hostname (without domain name) will be used as subject specification\n", __func__);
}
/* TODO: getdomainname() returns empty string, temporary hack here */
strcat(global_spec.hostname, ".cesnet.cz");
printf("hostname: %s\n", global_spec.hostname);
for (i=0; i<MAX_FLOWS; i++) {
flow_spec[i]=NULL;
flow_run[i]=NULL;
}
if ((flow_spec[0]=new_flow_spec())==NULL) {
fprintf(stderr, "%s: new_flow_spec() failed\n", __func__);
exit(-1);
}
/* payload_strings_no=0; */
direct_flow=0;
/* Read command line */
while ((opt=getopt(argc, argv, ARGS)) != -1) {
printf("%s: option: %c\n", __func__, opt);
switch(opt) {
case 'f':
if (direct_flow) {
fprintf(stderr, "%s: cannot specify -f and direct flow at the same time\n", __func__);
exit(-1);
}
global_spec.conf_filename=optarg;
break;
case 'd':
direct_flow=1;
flow_spec[0]->device=optarg;
break;
case 'm':
direct_flow=1;
if (strlen(optarg)>1) {
fprintf(stderr, "%s: sampling mode must be d, b or p\n", __func__);
exit(-1);
}
flow_spec[0]->sau_mode=optarg[0];
break;
case 'r':
direct_flow=1;
if (flow_spec[0]->sau_mode=='p')
sscanf(optarg, "%f", &(flow_spec[0]->sau_pass_probability));
else if (flow_spec[0]->sau_mode=='b')
flow_spec[0]->sau_byte_threshold=atoi(optarg);
else
flow_spec[0]->sau_packet_threshold=atoi(optarg);
break;
case 'p':
direct_flow=1;
if (flow_spec[0]->payload_strings_no >= MAX_PAYLOAD_STRINGS) {
fprintf(stderr, "%s: max. %d strings can be searched in payload\n", __func__, MAX_PAYLOAD_STRINGS);
exit(-1);
}
if (strlen(optarg) > MAX_PAYLOAD_STRING) {
fprintf(stderr, "%s: max. %d characters long strings can be searched in payload\n", __func__, MAX_PAYLOAD_STRING);
exit(-1);
}
if ((flow_spec[0]->payload_strings[flow_spec[0]->payload_strings_no]=
malloc(strlen(optarg)+1))==NULL) {
fprintf(stderr, "%s: malloc() failed\n", __func__);
exit(-1);
}
strcpy(flow_spec[0]->payload_strings[flow_spec[0]->payload_strings_no],
optarg);
flow_spec[0]->payload_strings_no++;
break;
case 'c':
direct_flow=1;
if ((flow_spec[0]->characteristics=malloc(strlen(optarg)+1))==NULL) {
fprintf(stderr, "%s: malloc() failed\n", __func__);
return -1;
}
strcpy(flow_spec[0]->characteristics, optarg);
break;
case 'i':
{ double interval;
direct_flow=1;
interval=atof(optarg);
if (interval<=0) {
fprintf(stderr, "%s: interval must be positive\n", __func__);
exit(-1);
}
flow_spec[0]->interval.tv_sec=floor(interval);
flow_spec[0]->interval.tv_usec=
(suseconds_t)floor((interval - flow_spec[0]->interval.tv_sec)*1000000);
}
break;
case 's':
direct_flow=1;
flow_spec[0]->start_time_string=optarg;
break;
case 'e':
direct_flow=1;
flow_spec[0]->end_time_string=optarg;
break;
case 'l':
direct_flow=1;
flow_spec[0]->link_mbps=atoi(optarg);
if (flow_spec[0]->link_mbps<=0) {
fprintf(stderr, "%s: link installed bandwidth must be positive\n", __func__);
exit(-1);
}
break;
case ':':
if (optopt=='q') {
global_spec.no_stdout=1;
break;
}
else if (optopt=='b') {
global_spec.no_mysql=1;
break;
}
else {
usage();
exit(-1);
}
case 'h':
usage();
exit(0);
default:
usage();
exit(-1);
}
}
if (read_command_line(argc, argv, &global_spec, flow_spec)<0) {
fprintf(stderr, "%s: read_command_line() failed\n", __func__);
return -1;
}
/* Read configuration file */
if (global_spec.conf_filename) {
if (read_conf_file(global_spec.conf_filename, flow_spec)<0) {
if (read_conf_file(&global_spec, flow_spec)<0) {
fprintf(stderr, "%s: read_conf_file() failed\n", __func__);
exit(-1);
return -1;
}
}
/* Check if specified values are within acceptable limits */
if (check_conf(flow_spec)<0) {
if (check_conf(&global_spec, flow_spec)<0) {
fprintf(stderr, "%s: check_conf() failed\n", __func__);
exit(-1);
}
/* Remaining command-line arguments form a header filter string */
for (i=optind; i<argc; i++) {
if ((strlen(flow_spec[0]->header_filter) + strlen(argv[i])) <
MAX_HEADER_FILTER) {
if (i>optind)
strcat(flow_spec[0]->header_filter, " ");
strcat(flow_spec[0]->header_filter, argv[i]);
}
else {
fprintf(stderr, "%s: header filter string must not be longer than %d characters\n", __func__, MAX_HEADER_FILTER);
exit(-1);
}
/* Remaining command-line arguments should form a header filter string */
if (read_header_filter(argc, argv, &(flow_spec[0]->header_filter))<0) {
fprintf(stderr, "%s: read_header_filter() failed\n", __func__);
return -1;
}
/* Print configuration */
print_conf(flow_spec);
if (!global_spec.no_mysql) {
print_conf(&global_spec, flow_spec);
if (mysql_server_init(0, NULL, NULL)) {
fprintf(stderr, "%s: mysql_server_init() failed\n", __func__);
exit(-1);
if (global_spec.db) {
if (abw_mysql_start(&global_spec)<0) {
fprintf(stderr, "%s: abw_start_mysql() failed\n", __func__);
return -1;
}
printf("mysql_server_init() ok\n");
if ((global_spec.mysql=mysql_init(NULL))==NULL) {
fprintf(stderr, "%s: mysql_init() failed\n", __func__);
exit(-1);
}
printf("mysql_init() ok\n");
if (mysql_real_connect(global_spec.mysql, NULL,
global_spec.user,
global_spec.passwd,
global_spec.db, 0, NULL, 0)==NULL) {
fprintf(stderr, "%s: mysql_real_connect() failed\n", __func__);
exit(-1);
}
printf("mysql_real_connect() ok\n");
}
}
/*
* Go over all specified flows and for each flow:
* - find its subject and parameters in database or add them
* - go over all its protocols and for each protocol:
* - create a MAPI flow
* - apply MAPI functions to this flow according to flow spec.
* - connect MAPI to this flow
*/
pp=flow_spec;
p=*pp;
qq=flow_run;
i=0;
while (p && i<MAX_FLOWS) {
while (i<MAX_FLOWS && *pp) {
if ((*qq=new_flow_run())==NULL) {
fprintf(stderr, "%s: new_flow_run() failed\n", __func__);
exit(-1);
}
q=*qq;
if (!(global_spec.no_mysql)) {
p=*pp;
if (global_spec.db) {
/* Find this node in tSubject or INSERT it */
if ((q->subject_id=
abw_mysql_get_subject_id(&global_spec, p))<0) {
/* Find subject of this flow in tSubject or INSERT it */
if ((subject_id=abw_mysql_get_subject_id(&global_spec, p))<0) {
fprintf(stderr, "%s: abw_mysql_get_subject_id() failed\n",
__func__);
exit(-1);
return -1;
}
/* Find these parameters in tParameters or INSERT it */
if ((q->parameters_id=
/* Find parameters of this flow in tParameters or INSERT it */
if ((parameters_id=
abw_mysql_get_parameters_id(&global_spec, p))<0) {
fprintf(stderr, "%s: abw_mysql_get_parameters_id() failed\n",
__func__);
......@@ -336,72 +125,117 @@ int main(int argc, char *argv[])
}
}
if ((q->fd=mapi_create_flow(p->device))<0) {
fprintf(stderr, "%s: mapi_create_flow(%s) failed\n", __func__,
p->device);
exit(-1);
/* Split string of protocols into individual protocols */
if (split_protocols(p->protocols, p->protocols_array)<0) {
fprintf(stderr, "%s: split_protocols() failed\n", __func__);
return -1;
}
if (strlen(p->header_filter)) {
if ((q->bpf_filter_fid=
mapi_apply_function(q->fd, "BPF_FILTER", p->header_filter))<0) {
fprintf(stderr, "%s: BPF_FILTER for flow %d failed\n", __func__,
i);
exit(-1);
j=0;
while (j<MAX_PROTOCOLS && p->protocols_array[j]) {
if ((p->flow_run[j]=new_flow_run())==NULL) {
fprintf(stderr, "%s: new_flow_run() failed\n", __func__);
return -1;
}
q=p->flow_run[j];
if (global_spec.db) {
q->subject_id=subject_id;
q->parameters_id=parameters_id;
}
}
if (p->sau_mode == 'd' && p->sau_packet_threshold != 1) {
if ((q->sample_fid=
mapi_apply_function(q->fd, "SAMPLE", p->sau_packet_threshold),
PERIODIC)<0) {
fprintf(stderr, "%s: SAMPLE for flow %d failed\n", __func__, i);
exit(-1);
/* Prepare header filter for this protocol */
if (p->protocols_array[j] && p->protocols_array[j][0]) {
if ((q->protocol=malloc(strlen(p->protocols_array[j])+1))==NULL) {
fprintf(stderr, "%s: malloc() failed\n", __func__);
return -1;
}
strcpy(q->protocol, p->protocols_array[j]);
if (protocol_filter(p->header_filter, q->protocol,
&(q->header_filter))<0) {
fprintf(stderr, "%s: protocols_filter() failed\n", __func__);
return -1;
}
}
else
q->header_filter=p->header_filter;
if ((q->fd=mapi_create_flow(p->device))<0) {
fprintf(stderr, "%s: mapi_create_flow(%s) failed\n", __func__,
p->device);
return -1;
}
/* Note that BPF_FILTER uses compiled header filter string that
selects packets of the given protocol */
if (q->header_filter) {
if ((q->bpf_filter_fid=
mapi_apply_function(q->fd, "BPF_FILTER", q->header_filter))<0) {
fprintf(stderr, "%s: BPF_FILTER for flow %d failed\n",
__func__, i);
return -1;
}
}
if (p->sau_mode == 'd' && p->sau_packet_threshold != 1) {
if ((q->sample_fid=
mapi_apply_function(q->fd, "SAMPLE", p->sau_packet_threshold),
PERIODIC)<0) {
fprintf(stderr, "%s: SAMPLE for flow %d failed\n",
__func__, i);
return -1;
}
}
else if (p->sau_mode == 'p' && p->sau_pass_probability != 1) {
if ((q->sample_fid=
mapi_apply_function(q->fd, "SAMPLE",
(p->sau_pass_probability)*100),
PROBABILISTIC)<0) {
fprintf(stderr, "%s: SAMPLE for flow %d failed\n",
__func__, i);
return -1;
}
}
}
else if (p->sau_mode == 'p' && p->sau_pass_probability != 1) {
if ((q->sample_fid=
mapi_apply_function(q->fd, "SAMPLE", (p->sau_pass_probability)*100),
PROBABILISTIC)<0) {
fprintf(stderr, "%s: SAMPLE for flow %d failed\n", __func__, i);
exit(-1);
}
}
if (p->payload_strings[0]) {
if ((q->str_search_fid=
mapi_apply_function(q->fd, "STR_SEARCH", p->payload_strings[0],
0, 0))<0) {
fprintf(stderr, "%s: STR_SEARCH for flow %d failed\n", __func__,
i);
exit(-1);
}
}
if (p->payload_strings[0]) {
if ((q->str_search_fid=
mapi_apply_function(q->fd, "STR_SEARCH", p->payload_strings[0],
0, 0))<0) {
fprintf(stderr, "%s: STR_SEARCH for flow %d failed\n",
__func__, i);
return -1;
}
}
if ((q->pkt_counter_fid=
if ((q->pkt_counter_fid=
mapi_apply_function(q->fd, "PKT_COUNTER"))<0) {
fprintf(stderr, "%s: PKT_COUNTER for flow %d failed\n", __func__,
i);
exit(-1);
}
return -1;
}
if ((q->byte_counter_fid=
if ((q->byte_counter_fid=
mapi_apply_function(q->fd, "BYTE_COUNTER"))<0) {
fprintf(stderr, "%s: BYTE_COUNTER for flow %d failed\n",
__func__, i);
exit(-1);
}
return -1;
}
if (mapi_connect(q->fd)<0) {
fprintf(stderr, "%s: mapi_connect() for flow %d failed\n", __func__,
i);
exit(-1);
}
if (mapi_connect(q->fd)<0) {
fprintf(stderr, "%s: mapi_connect() for flow %d failed\n",
__func__, i);
return -1;
}
j++;
} /* while (j<MAX_PROTOCOLS && p->protocols_array[j]) */
pp++; p=*pp;
qq++; q=*qq;
pp++;
i++;
} /* while (p) */
} /* while (i<MAX_FLOWS && *pp) */
while (1) {
if (gettimeofday(&tm, &tz)<0) {
......@@ -413,57 +247,64 @@ int main(int argc, char *argv[])
printf("%u.%u", (unsigned int)(tm.tv_sec), (unsigned int)(tm.tv_usec));
pp=flow_spec;
p=*pp;
qq=flow_run;
q=*qq;
i=0;
while (p) {
if ((q->pkt_counter=
mapi_read_results(q->fd, q->pkt_counter_fid, TRUE))==NULL) {
fprintf(stderr, "%s: mapi_read_results() for flow %d failed\n",
__func__, i);
exit(-1);
}
if ((q->byte_counter=
mapi_read_results(q->fd, q->byte_counter_fid, TRUE))==NULL) {
fprintf(stderr, "%s: mapi_read_results() for flow %d failed\n",
__func__, i);
exit(-1);
}
if (!global_spec.no_stdout) {
printf(" %u/%u", *(q->pkt_counter)-q->old_pkt_counter,
*(q->byte_counter)-q->old_byte_counter);
}
if (!global_spec.no_mysql) {
while (i<MAX_FLOWS && *pp) {
if (abw_mysql_insert_value(&global_spec, q,
tm.tv_sec, tm.tv_usec,
"packets all",
*(q->pkt_counter)-q->old_pkt_counter, 0, NULL)<0) {
fprintf(stderr, "%s: abw_mysql_insert() failed\n", __func__);
exit(-1);
p=*pp;
j=0;