Commit e442c723 authored by David Johnson's avatar David Johnson

Add UDP to the synthetic app (including application message

fragmentation).  Add block numbers and timestamps collected
along the way to a message header.
parent 60589bdb
...@@ -34,4 +34,43 @@ typedef uint32_t slen_t; ...@@ -34,4 +34,43 @@ typedef uint32_t slen_t;
#define MAX_NAME_LEN 255 #define MAX_NAME_LEN 255
/* currently, just setting same as freebsd 6.x to get "same" behavior... */
#ifndef UDPCTL_MAXDGRAM
#define UDPCTL_MAXDGRAM 9216
#endif
/**
* This struct doubles as a tx block hdr and a stats collector.
*/
typedef struct block_hdr {
uint32_t msg_id;
uint32_t block_id;
uint32_t frag_id;
/* NOTE: times are when the first bytes were sent with write/sendto! */
/** sender time */
uint32_t tv_send_send_s;
uint32_t tv_send_send_us;
/** middleman times */
uint32_t tv_mid_recv_s;
uint32_t tv_mid_recv_us;
uint32_t tv_mid_send_s;
uint32_t tv_mid_send_us;
/**
* receiver time (only used in stats; just here cause it doesn't make
* any difference to have in the packet, cause the packet is filled with
* deadbeef anyway).
*/
uint32_t tv_recv_recv_s;
uint32_t tv_recv_recv_us;
} block_hdr_t;
int marshall_block_hdr_send(char *buf,
uint32_t msg_id,uint32_t block_id,uint32_t frag_id,
struct timeval *tv_send_send);
int marshall_block_hdr_mid( char *buf,
struct timeval *tv_mid_recv,
struct timeval *tv_mid_send);
block_hdr_t *unmarshall_block_hdr(char *buf,block_hdr_t *fill_hdr);
#endif /* __DEFS_H__ */ #endif /* __DEFS_H__ */
...@@ -28,6 +28,8 @@ char *deadbeef = "deadbeef"; ...@@ -28,6 +28,8 @@ char *deadbeef = "deadbeef";
int pushback = 0; int pushback = 0;
int udp = 0;
/** /**
* defs * defs
*/ */
...@@ -36,11 +38,12 @@ void usage(char *bin) { ...@@ -36,11 +38,12 @@ void usage(char *bin) {
"USAGE: %s -scohSRudb (option defaults in parens)\n" "USAGE: %s -scohSRudb (option defaults in parens)\n"
" -s <block_size> tx block size (%d)\n" " -s <block_size> tx block size (%d)\n"
" -c <block_count> tx block size (%d)\n" " -c <block_count> tx block size (%d)\n"
" -h <hostname> Listen on this host/addr (INADDR_ANY)\n" " -m <hostname> Listen on this host/addr (INADDR_ANY)\n"
" -S <port> Listen on this port for one sender at a time (%d)\n" " -S <port> Listen on this port for one sender at a time (%d)\n"
" -R <port> Listen on this port for receivers (%d)\n" " -R <port> Listen on this port for receivers (%d)\n"
" -o Only encrypt (instead of dec/enc)\n" " -o Only encrypt (instead of dec/enc)\n"
" -b Ack all received blocks from sender AFTER crypto\n" " -b Ack all received blocks from sender AFTER crypto\n"
" -U Use udp instead of tcp\n"
" -d[d..d] Enable various levels of debug output\n" " -d[d..d] Enable various levels of debug output\n"
" -u Print this msg\n", " -u Print this msg\n",
bin,block_size,block_count,srv_send_port,srv_recv_port bin,block_size,block_count,srv_send_port,srv_recv_port
...@@ -51,7 +54,7 @@ void parse_args(int argc,char **argv) { ...@@ -51,7 +54,7 @@ void parse_args(int argc,char **argv) {
int c; int c;
char *ep = NULL; char *ep = NULL;
while ((c = getopt(argc,argv,"s:c:S:R:h:oudb")) != -1) { while ((c = getopt(argc,argv,"s:c:S:R:m:oudbU")) != -1) {
switch(c) { switch(c) {
case 's': case 's':
block_size = (int)strtol(optarg,&ep,10); block_size = (int)strtol(optarg,&ep,10);
...@@ -67,7 +70,7 @@ void parse_args(int argc,char **argv) { ...@@ -67,7 +70,7 @@ void parse_args(int argc,char **argv) {
exit(-1); exit(-1);
} }
break; break;
case 'h': case 'm':
srv_host = optarg; srv_host = optarg;
break; break;
case 'S': case 'S':
...@@ -96,6 +99,9 @@ void parse_args(int argc,char **argv) { ...@@ -96,6 +99,9 @@ void parse_args(int argc,char **argv) {
case 'b': case 'b':
pushback = 1; pushback = 1;
break; break;
case 'U':
udp = 1;
break;
default: default:
break; break;
} }
...@@ -128,6 +134,10 @@ int main(int argc,char **argv) { ...@@ -128,6 +134,10 @@ int main(int argc,char **argv) {
fd_set static_rfds; fd_set static_rfds;
int current_send_rc; int current_send_rc;
int block_count = 0; int block_count = 0;
struct sockaddr_in udp_recv_client_sins[MIDDLEMAN_MAX_CLIENTS];
int udp_msg_size = 0;
struct timeval t0;
int bytesRead = 0;
/* grab some quick args */ /* grab some quick args */
parse_args(argc,argv); parse_args(argc,argv);
...@@ -135,6 +145,12 @@ int main(int argc,char **argv) { ...@@ -135,6 +145,12 @@ int main(int argc,char **argv) {
/* initialize ourself... */ /* initialize ourself... */
srand(time(NULL)); srand(time(NULL));
if (udp) {
memset(udp_recv_client_sins,
0,
MIDDLEMAN_MAX_CLIENTS * sizeof(struct sockaddr_in));
}
/* grab the bufs... */ /* grab the bufs... */
if ((buf = (char *)malloc(sizeof(char)*block_size)) == NULL) { if ((buf = (char *)malloc(sizeof(char)*block_size)) == NULL) {
efatal("no memory for data buf"); efatal("no memory for data buf");
...@@ -167,10 +183,12 @@ int main(int argc,char **argv) { ...@@ -167,10 +183,12 @@ int main(int argc,char **argv) {
} }
/* startup server... */ /* startup server... */
if ((srv_send_sock = socket(PF_INET,SOCK_STREAM,0)) == -1) { if ((srv_send_sock = socket(PF_INET,(udp)?SOCK_DGRAM:SOCK_STREAM,0))
== -1) {
efatal("could not get send listen socket"); efatal("could not get send listen socket");
} }
if ((srv_recv_sock = socket(PF_INET,SOCK_STREAM,0)) == -1) { if ((srv_recv_sock = socket(PF_INET,(udp)?SOCK_DGRAM:SOCK_STREAM,0))
== -1) {
efatal("could not get send listen socket"); efatal("could not get send listen socket");
} }
...@@ -187,15 +205,17 @@ int main(int argc,char **argv) { ...@@ -187,15 +205,17 @@ int main(int argc,char **argv) {
efatal("could not bind"); efatal("could not bind");
} }
/* only listen for len 1 cause we won't accept on this guy if we if (!udp) {
* already have a sender /* only listen for len 1 cause we won't accept on this guy if we
*/ * already have a sender
if (listen(srv_send_sock,1) < 0) { */
efatal("could not listen"); if (listen(srv_send_sock,1) < 0) {
} efatal("could not listen");
/* more sane listen queue for this one */ }
if (listen(srv_recv_sock,8) < 0) { /* more sane listen queue for this one */
efatal("could not listen"); if (listen(srv_recv_sock,8) < 0) {
efatal("could not listen");
}
} }
/* daemonize... */ /* daemonize... */
...@@ -213,15 +233,29 @@ int main(int argc,char **argv) { ...@@ -213,15 +233,29 @@ int main(int argc,char **argv) {
FD_SET(srv_recv_sock,&static_rfds); FD_SET(srv_recv_sock,&static_rfds);
max_fd = (srv_send_sock > srv_recv_sock) ? srv_send_sock : srv_recv_sock; max_fd = (srv_send_sock > srv_recv_sock) ? srv_send_sock : srv_recv_sock;
if (debug > 1) {
fprintf(stdout,"DEBUG: server running...\n");
}
/* listen and read forever */ /* listen and read forever */
while (1) { while (1) {
/* reset fdsets */ /* reset fdsets */
memcpy(&rfds,&static_rfds,sizeof(static_rfds)); memcpy(&rfds,&static_rfds,sizeof(static_rfds));
if (debug > 3) {
printf("DEBUG: calling select\n");
}
retval = select(max_fd+1,&rfds,NULL,NULL,NULL); retval = select(max_fd+1,&rfds,NULL,NULL,NULL);
printf("AAA\n");
if (retval > 0) { if (retval > 0) {
if (FD_ISSET(srv_send_sock,&rfds) /*
* do we have input on port listening for senders, and not
* currently have a sender?
*/
if (!udp && FD_ISSET(srv_send_sock,&rfds)
&& send_client_fd < 0) { && send_client_fd < 0) {
struct sockaddr_in client_sin; struct sockaddr_in client_sin;
socklen_t slen; socklen_t slen;
...@@ -255,60 +289,125 @@ int main(int argc,char **argv) { ...@@ -255,60 +289,125 @@ int main(int argc,char **argv) {
current_send_rc = 0; current_send_rc = 0;
block_count = 0; block_count = 0;
} }
/* add a sender udp client */
//else if (FD_ISSET(srv_send_sock,&rfds) && udp) {
//}
/* add a new sfreceiver client */
else if (FD_ISSET(srv_recv_sock,&rfds)) { else if (FD_ISSET(srv_recv_sock,&rfds)) {
struct sockaddr_in client_sin; struct sockaddr_in client_sin;
socklen_t slen; socklen_t slen;
int client_fd; int client_fd;
char tmpbuf[255];
slen = sizeof(client_sin); slen = sizeof(client_sin);
if ((client_fd = accept(srv_recv_sock, if (udp) {
(struct sockaddr *)&client_sin, if (recvfrom(srv_recv_sock,tmpbuf,sizeof(tmpbuf),0,
&slen)) < 0) { (struct sockaddr *)&client_sin,&slen) < 0) {
warn("accept failed"); ewarn("in recvfrom while getting a new receiver "
} "client");
else if (recv_client_cnt >= MIDDLEMAN_MAX_CLIENTS) { }
warn("already at max clients"); else {
close(client_fd); /*
* if this is a client we haven't heard from,
* add it; else remove it. Basic "connection."
*/
int first_zero_idx = -1;
for (i = 0; i < MIDDLEMAN_MAX_CLIENTS; ++i) {
if (udp_recv_client_sins[i].sin_addr.s_addr == 0
&& first_zero_idx < 0) {
first_zero_idx = i;
}
else if ((udp_recv_client_sins[i].sin_addr.s_addr
== client_sin.sin_addr.s_addr)
&& (udp_recv_client_sins[i].sin_port
== client_sin.sin_port)) {
/* old client, wants to "disconnect" */
if (debug > 1) {
fprintf(stdout,
"removed udp client %s\n",
inet_ntoa(client_sin.sin_addr));
}
memset(&udp_recv_client_sins[i],
0,
sizeof(struct sockaddr_in));
break;
}
}
if (i == MIDDLEMAN_MAX_CLIENTS) {
/* new client */
if (first_zero_idx < 0) {
ewarn("could not add new client, max reached");
}
else {
memcpy(&udp_recv_client_sins[first_zero_idx],
&client_sin,
sizeof(struct sockaddr_in));
if (debug > 1) {
fprintf(stdout,
"added new udp receiver client %s\n",
inet_ntoa(client_sin.sin_addr));
}
}
}
}
} }
else { else {
/* add new recv client... */ if ((client_fd = accept(srv_recv_sock,
for (i = 0; i < MIDDLEMAN_MAX_CLIENTS; ++i) { (struct sockaddr *)&client_sin,
if (recv_clientfds[i] == -1) { &slen)) < 0) {
break; warn("accept failed");
}
} }
else if (recv_client_cnt >= MIDDLEMAN_MAX_CLIENTS) {
recv_clientfds[i] = client_fd; warn("already at max clients");
if (client_fd > max_fd) { close(client_fd);
max_fd = client_fd;
} }
else {
FD_SET(client_fd,&static_rfds); /* add new recv client... */
for (i = 0; i < MIDDLEMAN_MAX_CLIENTS; ++i) {
char *addr = inet_ntoa(client_sin.sin_addr); if (recv_clientfds[i] == -1) {
int addrlen = strlen(addr); break;
}
if (debug > 1) { }
fprintf(stdout,
"DEBUG: connect from %s:%d\n", recv_clientfds[i] = client_fd;
if (client_fd > max_fd) {
max_fd = client_fd;
}
FD_SET(client_fd,&static_rfds);
char *addr = inet_ntoa(client_sin.sin_addr);
int addrlen = strlen(addr);
if (debug > 1) {
fprintf(stdout,
"DEBUG: connect from %s:%d\n",
addr,
ntohs(client_sin.sin_port));
}
strncpy(recv_clientsas[i],
addr, addr,
ntohs(client_sin.sin_port)); (addrlen > MAX_NAME_LEN)?MAX_NAME_LEN:addrlen);
} /* null term if strncpy couldn't */
if (addrlen > MAX_NAME_LEN) {
strncpy(recv_clientsas[i], recv_clientsas[i][MAX_NAME_LEN] = '\0';
addr, }
(addrlen > MAX_NAME_LEN)?MAX_NAME_LEN:addrlen);
/* null term if strncpy couldn't */ ++recv_client_cnt;
if (addrlen > MAX_NAME_LEN) {
recv_clientsas[i][MAX_NAME_LEN] = '\0';
} }
++recv_client_cnt;
} }
} }
else if (send_client_fd > 0 else if ((send_client_fd > 0
&& FD_ISSET(send_client_fd,&rfds)) { && FD_ISSET(send_client_fd,&rfds))
|| (udp && FD_ISSET(srv_send_sock,&rfds))) {
/** /**
* ok, here we need to read a block from this guy for awhile, * ok, here we need to read a block from this guy for awhile,
* then [decrypt/munge]/encrypt (according to command line * then [decrypt/munge]/encrypt (according to command line
...@@ -330,65 +429,107 @@ int main(int argc,char **argv) { ...@@ -330,65 +429,107 @@ int main(int argc,char **argv) {
//printf("going for another read\n"); //printf("going for another read\n");
retval = read(send_client_fd,
&buf[current_send_rc],
block_size - current_send_rc);
if (retval < 0) { if (!udp) {
if (errno == ECONNRESET) { retval = read(send_client_fd,
&buf[current_send_rc],
block_size - current_send_rc);
if (retval < 0) {
if (errno == ECONNRESET) {
/* dead sender */
close(send_client_fd);
FD_CLR(send_client_fd,&static_rfds);
send_client_fd = -1;
current_send_rc = 0;
block_count = 0;
if (debug > 1) {
fprintf(stderr,
"DEBUG: (send client!) disconnect from %s\n",
recv_clientsas[i]);
}
}
else if (errno == EAGAIN) {
// ignore, doh
//ewarn("while reading");
}
else {
//ewarn("unexpected while reading");
}
}
else if (retval == 0) {
/* dead sender */ /* dead sender */
close(send_client_fd); close(send_client_fd);
FD_CLR(send_client_fd,&static_rfds); FD_CLR(send_client_fd,&static_rfds);
send_client_fd = -1; send_client_fd = -1;
current_send_rc = 0; current_send_rc = 0;
block_count = 0; block_count = 0;
if (debug > 1) { if (debug > 1) {
fprintf(stderr, fprintf(stderr,
"DEBUG: (send client!) disconnect from %s\n", "DEBUG: (send client!) disconnect!\n");
recv_clientsas[i]);
} }
} }
else if (errno == EAGAIN) {
// ignore, doh
//ewarn("while reading");
}
else { else {
//ewarn("unexpected while reading"); current_send_rc += retval;
} }
} }
else if (retval == 0) { else {
/* dead sender */ /*
close(send_client_fd); * NOTE: we do not establish that there's only one
FD_CLR(send_client_fd,&static_rfds); * sender! We just forward msgs that come to us.
send_client_fd = -1; */
struct sockaddr_in client_sin;
current_send_rc = 0; socklen_t slen;
block_count = 0; slen = sizeof(client_sin);
if (debug > 3) {
fprintf(stdout,"DEBUG: calling recvfrom on sender\n");
}
retval = recvfrom(srv_send_sock,buf,block_size,0,
(struct sockaddr *)&client_sin,&slen);
if (retval < 0) {
ewarn("error in recvfrom on sending client");
udp_msg_size = 0;
}
else {
udp_msg_size = retval;
if (debug > 1) {
fprintf(stderr,
"DEBUG: udp dgram\n",
udp_msg_size);
}
if (debug > 1) {
fprintf(stderr,
"DEBUG: (send client!) disconnect!\n");
} }
} }
else {
current_send_rc += retval;
}
bytesRead = (udp)?udp_msg_size:current_send_rc;
/* grab recv timestamp */
gettimeofday(&t0,NULL);
if ((!udp && current_send_rc == block_size)
|| (udp && udp_msg_size > 0)) {
block_hdr_t hdr;
if (current_send_rc == block_size) {
current_send_rc = 0; current_send_rc = 0;
++block_count; /* unmarshall header */
unmarshall_block_hdr(buf,&hdr);
/* wait to send ack until after crypto */ /* wait to send ack until after crypto */
/* end of block, do the encryption op and note times... */ /* end of block, do the encryption op and note times... */
if (debug > 1) { if (debug > 1) {
fprintf(stderr, fprintf(stderr,
"DEBUG: read %d bytes (a block)\n", "DEBUG: read %d bytes\n",
block_size); bytesRead);
} }
DES_cblock *iv = sgeniv(); DES_cblock *iv = sgeniv();
...@@ -398,17 +539,17 @@ int main(int argc,char **argv) { ...@@ -398,17 +539,17 @@ int main(int argc,char **argv) {
if (only_encrypt) { if (only_encrypt) {
gettimeofday(&t1,NULL); gettimeofday(&t1,NULL);
sencrypt(buf,outbuf,block_size, sencrypt(buf,outbuf,bytesRead,
k1,k2,iv); k1,k2,iv);
gettimeofday(&t2,NULL); gettimeofday(&t2,NULL);
} }
else { else {
/* do a decrypt, then choose new iv, then encrypt. */ /* do a decrypt, then choose new iv, then encrypt. */
gettimeofday(&t1,NULL); gettimeofday(&t1,NULL);
sdecrypt(buf,outbuf,block_size, sdecrypt(buf,outbuf,bytesRead,
k1,k2,iv); k1,k2,iv);
iv = sgeniv(); iv = sgeniv();
sencrypt(buf,outbuf,block_size, sencrypt(buf,outbuf,bytesRead,
k1,k2,iv); k1,k2,iv);
gettimeofday(&t2,NULL); gettimeofday(&t2,NULL);
} }
...@@ -420,18 +561,30 @@ int main(int argc,char **argv) { ...@@ -420,18 +561,30 @@ int main(int argc,char **argv) {
t3.tv_usec += 1000000; t3.tv_usec += 1000000;
} }
fprintf(stdout, fprintf(stdout,
"BLOCKTIME(%s): %d %d at %.6f\n", "BLOCKTIME(%s): m%d b%d f%d %d at %.6f\n",
(only_encrypt)?"e":"de", (only_encrypt)?"e":"de",
block_count, hdr.msg_id,hdr.block_id,hdr.frag_id,
t3.tv_sec * 1000 + t3.tv_usec, t3.tv_sec * 1000 + t3.tv_usec,
t2.tv_sec + t2.tv_usec / 1000000.0f); t2.tv_sec + t2.tv_usec / 1000000.0f);
fflush(stdout); fflush(stdout);
if (!udp) {
/* no app fragmentation with tcp */
++block_count;
}
else {
/* have to actually unmarshall the header to see
* which block and frag numbers we have.
*/
}
/** /**
* send the ack after crypto ops... * send the ack after crypto ops...
*/ */
if (pushback) {