Commit 4a1599b2 authored by Jonathan Jenkins's avatar Jonathan Jenkins
Browse files

Initial 'simplewan' implementation

parent dd369556
......@@ -17,6 +17,7 @@
#define CATEGORY_MAX 12
typedef struct simplenet_param simplenet_param;
typedef struct simplewan_param simplewan_param;
typedef struct dragonfly_param dragonfly_param;
typedef struct torus_param torus_param;
typedef struct loggp_param loggp_param;
......@@ -25,6 +26,7 @@ typedef struct mn_stats mn_stats;
enum NETWORKS
{
SIMPLENET,
SIMPLEWAN,
TORUS,
DRAGONFLY,
LOGGP,
......@@ -58,6 +60,12 @@ struct simplenet_param
int num_nics;
};
struct simplewan_param
{
char bw_filename[MAX_NAME_LENGTH];
char startup_filename[MAX_NAME_LENGTH];
};
struct dragonfly_param
{
int num_routers; /*Number of routers in a group*/
......
......@@ -12,5 +12,5 @@ src_libcodes_net_a_SOURCES = \
src/models/networks/model-net/simplenet-upd.c \
src/models/networks/model-net/torus.c \
src/models/networks/model-net/dragonfly.c \
src/models/networks/model-net/loggp.c
src/models/networks/model-net/loggp.c \
src/models/networks/model-net/simplewan.c
"Simplewan"
----------
Model overview:
---------------
Simplewan is an extension of simplenet to allow for arbitrary point-to-point
capacities.
Simplewan has nearly the same duplex queued transmission semantics as
simplenet, though with a few important differences. First, point-to-point
latencies and bandwidths are different. Second, each unique link is given its
own queue that do not interfere with the others. The use case for this model is
a set of sites with internal networks, with each site communicating via
simplewan; we assume the internal network is capable of servicing all
outgoing/incoming WAN transmissions at their full capacities.
Additional configuration is needed to initialize the link latencies/capacities.
In the codes-configuration file, the variables "net_startup_ns_file" and
"net_bw_mbps_file" must be set under the PARAMS group. They point (in a path
relative to the configuration file) to configurations for the startup and
bandwidth costs, respectively.
Each of the latency/bandwidth configuration files have the same format, based
on a triangular matrix. Given N modelnet LPs, it has the format:
1:2 1:3 ... 1:N
2:3 2:4 ... 2:N
...
N-1:N
where x:y is the latency or bandwidth between components x and y. Whitespace is
ignored, but linebreaks are not, and delimit rows of the matrix. The relative
simplewan identifiers 1..N are assigned to simplewan LPs in the order of
their appearance in the codes-configuration file. In the future, a full NxN
matrix may be used to facilitate asymmetric link capacities if the need arises.
This diff is collapsed.
check_PROGRAMS += tests/modelnet-test tests/modelnet-p2p-bw \
tests/concurrent-msg-recv
tests/concurrent-msg-recv tests/modelnet-simplewan-test
TESTS += tests/modelnet-test.sh \
tests/modelnet-test-torus.sh \
......@@ -19,6 +19,10 @@ tests_modelnet_test_LDADD = $(testlib) ${CODES_BASE_LIBS}
tests_modelnet_test_CFLAGS = ${CODES_BASE_CFLAGS}
tests_modelnet_test_SOURCES = tests/modelnet-test.c
tests_modelnet_simplewan_test_LDADD = $(testlib) ${CODES_BASE_LIBS}
tests_modelnet_simplewan_test_CFLAGS = ${CODES_BASE_CFLAGS}
tests_modelnet_simplewan_test_SOURCES = tests/modelnet-simplewan-test.c
tests_modelnet_p2p_bw_LDADD = $(testlib) ${CODES_BASE_LIBS}
tests_modelnet_p2p_bw_CFLAGS = ${CODES_BASE_CFLAGS}
tests_modelnet_p2p_bw_SOURCES = tests/modelnet-p2p-bw.c
......
LPGROUPS
{
MODELNET_GRP
{
repetitions="3";
server="1";
modelnet_simplewan="1";
}
}
PARAMS
{
message_size="256";
packet_size="1024";
modelnet="simplewan";
net_startup_ns_file="modelnet-test-startup.conf";
net_bw_mbps_file="modelnet-test-bw.conf";
}
/*
* Copyright (C) 2013 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*
*/
/* SUMMARY:
*
* This is a test harness for the modelnet module. It sets up a number of
* servers, each of which is paired up with a simplenet LP to serve as the
* NIC. Each server exchanges a sequence of requests and acks with one peer
* and measures the throughput in terms of payload bytes (ack size) moved
* per second.
*/
#include <string.h>
#include <assert.h>
#include <ross.h>
#include "codes/model-net.h"
#include "codes/lp-io.h"
#include "codes/codes.h"
#include "codes/codes_mapping.h"
#include "codes/configuration.h"
#include "codes/lp-type-lookup.h"
#define NUM_REQS 3 /* number of requests sent by each server */
#define PAYLOAD_SZ 2048 /* size of simulated data payload, bytes */
static int net_id = 0;
static int num_servers = 0;
typedef struct svr_msg svr_msg;
typedef struct svr_state svr_state;
/* types of events that will constitute triton requests */
enum svr_event
{
KICKOFF, /* initial event */
REQ, /* request event */
ACK, /* ack event */
LOCAL /* local event */
};
struct svr_state
{
int msg_sent_count; /* requests sent */
int msg_recvd_count; /* requests recvd */
int local_recvd_count; /* number of local messages received */
tw_stime start_ts; /* time that we started sending requests */
};
struct svr_msg
{
enum svr_event svr_event_type;
// enum net_event net_event_type;
tw_lpid src; /* source of this request or ack */
int incremented_flag; /* helper for reverse computation */
};
static void svr_init(
svr_state * ns,
tw_lp * lp);
static void svr_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp);
static void svr_rev_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp);
static void svr_finalize(
svr_state * ns,
tw_lp * lp);
tw_lptype svr_lp = {
(init_f) svr_init,
(event_f) svr_event,
(revent_f) svr_rev_event,
(final_f) svr_finalize,
(map_f) codes_mapping,
sizeof(svr_state),
};
extern const tw_lptype* svr_get_lp_type();
static void svr_add_lp_type();
static tw_stime ns_to_s(tw_stime ns);
static tw_stime s_to_ns(tw_stime ns);
static void handle_kickoff_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp);
static void handle_ack_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp);
static void handle_req_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp);
static void handle_local_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp);
static void handle_local_rev_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp);
static void handle_kickoff_rev_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp);
static void handle_ack_rev_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp);
static void handle_req_rev_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp);
const tw_optdef app_opt [] =
{
TWOPT_GROUP("Model net test case" ),
TWOPT_END()
};
int main(
int argc,
char **argv)
{
int nprocs;
int rank;
//printf("\n Config count %d ",(int) config.lpgroups_count);
g_tw_ts_end = s_to_ns(60*60*24*365); /* one year, in nsecs */
lp_io_handle handle;
tw_opt_add(app_opt);
tw_init(&argc, &argv);
if(argc < 2)
{
printf("\n Usage: mpirun <args> --sync=2/3 mapping_file_name.conf (optional --nkp) ");
MPI_Finalize();
return 0;
}
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
configuration_load(argv[2], MPI_COMM_WORLD, &config);
net_id=model_net_set_params();
svr_add_lp_type();
codes_mapping_setup();
num_servers = codes_mapping_get_group_reps("MODELNET_GRP") * codes_mapping_get_lp_count("MODELNET_GRP", "server");
assert(num_servers == 3);
if(lp_io_prepare("modelnet-test", LP_IO_UNIQ_SUFFIX, &handle, MPI_COMM_WORLD) < 0)
{
return(-1);
}
tw_run();
model_net_report_stats(net_id);
if(lp_io_flush(handle, MPI_COMM_WORLD) < 0)
{
return(-1);
}
tw_end();
return 0;
}
const tw_lptype* svr_get_lp_type()
{
return(&svr_lp);
}
static void svr_add_lp_type()
{
lp_type_register("server", svr_get_lp_type());
}
static void svr_init(
svr_state * ns,
tw_lp * lp)
{
tw_event *e;
svr_msg *m;
tw_stime kickoff_time;
memset(ns, 0, sizeof(*ns));
/* each server sends a dummy event to itself that will kick off the real
* simulation
*/
//printf("\n Initializing servers %d ", (int)lp->gid);
/* skew each kickoff event slightly to help avoid event ties later on */
kickoff_time = g_tw_lookahead + tw_rand_unif(lp->rng);
e = codes_event_new(lp->gid, kickoff_time, lp);
m = tw_event_data(e);
m->svr_event_type = KICKOFF;
tw_event_send(e);
return;
}
static void svr_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp)
{
switch (m->svr_event_type)
{
case REQ:
handle_req_event(ns, b, m, lp);
break;
case ACK:
handle_ack_event(ns, b, m, lp);
break;
case KICKOFF:
handle_kickoff_event(ns, b, m, lp);
break;
case LOCAL:
handle_local_event(ns, b, m, lp);
break;
default:
printf("\n Invalid message type %d ", m->svr_event_type);
assert(0);
break;
}
}
static void svr_rev_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp)
{
switch (m->svr_event_type)
{
case REQ:
handle_req_rev_event(ns, b, m, lp);
break;
case ACK:
handle_ack_rev_event(ns, b, m, lp);
break;
case KICKOFF:
handle_kickoff_rev_event(ns, b, m, lp);
break;
case LOCAL:
handle_local_rev_event(ns, b, m, lp);
break;
default:
assert(0);
break;
}
return;
}
static void svr_finalize(
svr_state * ns,
tw_lp * lp)
{
double t = ns_to_s(tw_now(lp) - ns->start_ts);
printf("server %llu recvd %d bytes in %f seconds, %f MiB/s sent_count %d recvd_count %d local_count %d \n", (unsigned long long)lp->gid, PAYLOAD_SZ*ns->msg_recvd_count, t,
((double)(PAYLOAD_SZ*NUM_REQS)/(double)(1024*1024)/t), ns->msg_sent_count, ns->msg_recvd_count, ns->local_recvd_count);
return;
}
/* convert ns to seconds */
static tw_stime ns_to_s(tw_stime ns)
{
return(ns / (1000.0 * 1000.0 * 1000.0));
}
/* convert seconds to ns */
static tw_stime s_to_ns(tw_stime ns)
{
return(ns * (1000.0 * 1000.0 * 1000.0));
}
/* handle initial event */
static void handle_kickoff_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp)
{
svr_msg m_local, m_remote;
// m_local.svr_event_type = REQ;
m_local.svr_event_type = LOCAL;
m_local.src = lp->gid;
memcpy(&m_remote, &m_local, sizeof(svr_msg));
m_remote.svr_event_type = REQ;
//printf("handle_kickoff_event(), lp %llu.\n", (unsigned long long)lp->gid);
/* record when transfers started on this server */
ns->start_ts = tw_now(lp);
/* each server sends a request to the next highest server */
int dest_id;
switch (lp->gid / 2){
case 0: dest_id = 4; break;
case 1: dest_id = 4; break;
case 2: return; /* LP 4 doesn't send messages */
}
model_net_event(net_id, "test", dest_id, PAYLOAD_SZ, sizeof(svr_msg), &m_remote, sizeof(svr_msg), &m_local, lp);
ns->msg_sent_count++;
}
static void handle_local_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp)
{
ns->local_recvd_count++;
}
static void handle_local_rev_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp)
{
ns->local_recvd_count--;
}
/* reverse handler for req event */
static void handle_req_rev_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp)
{
ns->msg_recvd_count--;
model_net_event_rc(net_id, lp, PAYLOAD_SZ);
return;
}
/* reverse handler for kickoff */
static void handle_kickoff_rev_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp)
{
ns->msg_sent_count--;
model_net_event_rc(net_id, lp, PAYLOAD_SZ);
return;
}
/* reverse handler for ack*/
static void handle_ack_rev_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp)
{
if(m->incremented_flag)
{
model_net_event_rc(net_id, lp, PAYLOAD_SZ);
ns->msg_sent_count--;
}
return;
}
/* handle recving ack */
static void handle_ack_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp)
{
svr_msg m_local;
svr_msg m_remote;
m_local.svr_event_type = LOCAL;
m_local.src = lp->gid;
memcpy(&m_remote, &m_local, sizeof(svr_msg));
m_remote.svr_event_type = REQ;
if(ns->msg_sent_count < NUM_REQS)
{
model_net_event(net_id, "test", m->src, PAYLOAD_SZ, sizeof(svr_msg), &m_remote, sizeof(svr_msg), &m_local, lp);
ns->msg_sent_count++;
m->incremented_flag = 1;
}
else
{
m->incremented_flag = 0;
}
return;
}
/* handle receiving request */
static void handle_req_event(
svr_state * ns,
tw_bf * b,
svr_msg * m,
tw_lp * lp)
{
svr_msg m_local;
svr_msg m_remote;
m_local.svr_event_type = LOCAL;
m_local.src = lp->gid;
memcpy(&m_remote, &m_local, sizeof(svr_msg));
m_remote.svr_event_type = ACK;
ns->msg_recvd_count++;
// mm Q: What should be the size of an ack message? may be a few bytes? or larger..?
model_net_event(net_id, "test", m->src, PAYLOAD_SZ, sizeof(svr_msg), &m_remote, sizeof(svr_msg), &m_local, lp);
}
/*
* Local variables:
* c-indent-level: 4
* c-basic-offset: 4
* End:
*
* vim: ft=c ts=8 sts=4 sw=4 expandtab
*/
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment