Commit c9d76b45 authored by Caitlin Ross's avatar Caitlin Ross
Browse files

Merge branch 'analysis-lp' into codes-nemo-sampling

parents ef443c39 9950b0f8
......@@ -85,6 +85,8 @@ struct terminal_custom_message
tw_stime saved_total_time;
tw_stime saved_sample_time;
tw_stime msg_start_time;
tw_stime saved_busy_time_ross;
tw_stime saved_fin_chunks_ross;
};
#ifdef __cplusplus
......
......@@ -327,10 +327,12 @@ struct nw_message
// for callbacks - time message was received
double msg_send_time;
int req_id;
int matched_req;
int tag;
int app_id;
int found_match;
short wait_completed;
short rend_send;
} fwd;
struct
{
......@@ -347,7 +349,7 @@ struct nw_message
} rc;
};
static void send_ack_back(nw_state* s, tw_bf * bf, nw_message * m, tw_lp * lp, mpi_msgs_queue * mpi_op);
static void send_ack_back(nw_state* s, tw_bf * bf, nw_message * m, tw_lp * lp, mpi_msgs_queue * mpi_op, int matched_req);
static void send_ack_back_rc(nw_state* s, tw_bf * bf, nw_message * m, tw_lp * lp);
/* executes MPI isend and send operations */
......@@ -1289,6 +1291,7 @@ static int rm_matching_rcv(nw_state * ns,
{
int matched = 0;
int index = 0;
int is_rend = 0;
struct qlist_head *ent = NULL;
mpi_msgs_queue * qi = NULL;
......@@ -1317,21 +1320,28 @@ static int rm_matching_rcv(nw_state * ns,
/* Matching receive found, need to notify the sender to transmit
* the data * (only works in sequential mode)*/
bf->c10 = 1;
send_ack_back(ns, bf, m, lp, qitem);
is_rend = 1;
send_ack_back(ns, bf, m, lp, qitem, qi->req_id);
}
m->rc.saved_recv_time = ns->recv_time;
ns->recv_time += (tw_now(lp) - m->fwd.sim_start_time);
if(qi->op_type == CODES_WK_IRECV)
else
{
m->rc.saved_recv_time = ns->recv_time;
ns->recv_time += (tw_now(lp) - m->fwd.sim_start_time);
}
if(qi->op_type == CODES_WK_IRECV && !is_rend)
{
bf->c9 = 1;
/*if(ns->nw_id == (tw_lpid)TRACK_LP)
{
printf("\n Completed irecv req id %d ", qi->req_id);
}*/
update_completed_queue(ns, bf, m, lp, qi->req_id);
}
else if(qi->op_type == CODES_WK_RECV)
else if(qi->op_type == CODES_WK_RECV && !is_rend)
{
bf->c8 = 1;
codes_issue_next_event(lp);
}
qlist_del(&qi->ql);
......@@ -1370,14 +1380,16 @@ static int rm_matching_send(nw_state * ns,
if(enable_msg_tracking && (qi->num_bytes < EAGER_THRESHOLD))
update_message_size(ns, lp, bf, m, qi, 1, 0);
m->fwd.matched_req = qitem->req_id;
int is_rend = 0;
if(qitem->num_bytes >= EAGER_THRESHOLD)
{
/* Matching receive found, need to notify the sender to transmit
* the data */
bf->c10 = 1;
send_ack_back(ns, bf, m, lp, qi);
is_rend = 1;
send_ack_back(ns, bf, m, lp, qi, qitem->req_id);
}
rc_stack_push(lp, qi, free, ns->processed_ops);
m->rc.saved_recv_time = ns->recv_time;
ns->recv_time += (tw_now(lp) - qitem->req_init_time);
......@@ -1388,11 +1400,16 @@ static int rm_matching_send(nw_state * ns,
print_completed_queue(lp, &ns->completed_reqs);
}*/
if(qitem->op_type == CODES_WK_IRECV)
if(qitem->op_type == CODES_WK_IRECV && !is_rend)
{
bf->c9 = 1;
update_completed_queue(ns, bf, m, lp, qitem->req_id);
}
qlist_del(&qi->ql);
rc_stack_push(lp, qi, free, ns->processed_ops);
return index;
}
return -1;
......@@ -1485,11 +1502,12 @@ static void codes_exec_mpi_recv_rc(
index++;
}
}
if(m->op_type == CODES_WK_IRECV)
if(bf->c9)
{
update_completed_queue_rc(ns, bf, m, lp);
}
codes_issue_next_event_rc(lp);
if(bf->c6)
codes_issue_next_event_rc(lp);
}
else if(m->fwd.found_match < 0)
{
......@@ -1550,12 +1568,14 @@ static void codes_exec_mpi_recv(
/* for mpi irecvs, this is a non-blocking receive so just post it and move on with the trace read. */
if(mpi_op->op_type == CODES_WK_IRECV)
{
bf->c6 = 1;
codes_issue_next_event(lp);
return;
}
}
else
{
bf->c6 = 1;
m->fwd.found_match = found_matching_sends;
codes_issue_next_event(lp);
}
......@@ -1597,6 +1617,7 @@ static void codes_exec_mpi_send(nw_state* s,
bf->c1 = 0;
bf->c4 = 0;
int is_eager = 0;
/* model-net event */
int global_dest_rank = mpi_op->u.send.dest_rank;
......@@ -1638,16 +1659,18 @@ static void codes_exec_mpi_send(nw_state* s,
local_m.op_type = mpi_op->op_type;
local_m.msg_type = MPI_SEND_POSTED;
local_m.fwd.tag = mpi_op->u.send.tag;
local_m.fwd.rend_send = 0;
local_m.fwd.num_bytes = mpi_op->u.send.num_bytes;
local_m.fwd.req_id = mpi_op->u.send.req_id;
local_m.fwd.app_id = s->app_id;
local_m.fwd.matched_req = m->fwd.matched_req;
if(mpi_op->u.send.num_bytes < EAGER_THRESHOLD)
{
/* directly issue a model-net send */
bf->c15 = 1;
is_eager = 1;
s->num_sends++;
tw_stime copy_overhead = copy_per_byte_eager * mpi_op->u.send.num_bytes;
local_m.fwd.sim_start_time = tw_now(lp);
......@@ -1683,6 +1706,7 @@ static void codes_exec_mpi_send(nw_state* s,
/* initiate the actual data transfer, local completion message is sent
* for any blocking sends. */
local_m.fwd.sim_start_time = mpi_op->sim_start_time;
local_m.fwd.rend_send = 1;
remote_m = local_m;
remote_m.msg_type = MPI_REND_ARRIVED;
......@@ -1702,7 +1726,7 @@ static void codes_exec_mpi_send(nw_state* s,
tw_now(lp), s->app_id, LLU(s->nw_id), global_dest_rank, mpi_op->u.send.tag, mpi_op->u.send.num_bytes);
}
/* isend executed, now get next MPI operation from the queue */
if(mpi_op->op_type == CODES_WK_ISEND && !is_rend)
if(mpi_op->op_type == CODES_WK_ISEND && (!is_rend || is_eager))
{
bf->c4 = 1;
codes_issue_next_event(lp);
......@@ -1788,6 +1812,7 @@ static void update_completed_queue(nw_state* s,
struct pending_waits* wait_elem = s->wait_op;
rc_stack_push(lp, wait_elem, free, s->processed_wait_op);
s->wait_op = NULL;
codes_issue_next_event(lp);
}
}
......@@ -1799,7 +1824,7 @@ static void send_ack_back_rc(nw_state* s, tw_bf * bf, nw_message * m, tw_lp * lp
/* Send an ack back to the sender */
model_net_event_rc2(lp, &m->event_rc);
}
static void send_ack_back(nw_state* s, tw_bf * bf, nw_message * m, tw_lp * lp, mpi_msgs_queue * mpi_op)
static void send_ack_back(nw_state* s, tw_bf * bf, nw_message * m, tw_lp * lp, mpi_msgs_queue * mpi_op, int matched_req)
{
(void)bf;
......@@ -1821,6 +1846,7 @@ static void send_ack_back(nw_state* s, tw_bf * bf, nw_message * m, tw_lp * lp, m
remote_m.fwd.tag = mpi_op->tag;
remote_m.fwd.num_bytes = mpi_op->num_bytes;
remote_m.fwd.req_id = mpi_op->req_id;
remote_m.fwd.matched_req = matched_req;
m->event_rc = model_net_event_mctx(net_id, &group_ratio, &group_ratio,
"test", dest_rank, CONTROL_MSG_SZ, (self_overhead + soft_delay_mpi + nic_delay),
......@@ -1865,9 +1891,9 @@ static void update_arrival_queue_rc(nw_state* s,
index++;
}
}
if(qi->op_type == CODES_WK_IRECV)
if(bf->c9)
update_completed_queue_rc(s, bf, m, lp);
else if(qi->op_type == CODES_WK_RECV)
else if(bf->c8)
codes_issue_next_event_rc(lp);
}
else if(m->fwd.found_match < 0)
......@@ -2198,6 +2224,21 @@ void nw_test_event_handler(nw_state* s, tw_bf * bf, nw_message * m, tw_lp * lp)
m_callback->msg_type = MPI_SEND_ARRIVED_CB;
m_callback->fwd.msg_send_time = tw_now(lp) - m->fwd.sim_start_time;
tw_event_send(e_callback);
/* request id pending completion */
if(m->fwd.matched_req >= 0)
{
bf->c8 = 1;
update_completed_queue(s, bf, m, lp, m->fwd.matched_req);
}
else /* blocking receive pending completion*/
{
bf->c10 = 1;
codes_issue_next_event(lp);
}
m->rc.saved_recv_time = s->recv_time;
s->recv_time += (tw_now(lp) - m->fwd.sim_start_time);
}
break;
......@@ -2225,19 +2266,27 @@ void nw_test_event_handler(nw_state* s, tw_bf * bf, nw_message * m, tw_lp * lp)
case MPI_SEND_POSTED:
{
if(m->op_type == CODES_WK_SEND)
int is_eager = 0;
if(m->fwd.num_bytes < EAGER_THRESHOLD)
is_eager = 1;
if(m->op_type == CODES_WK_SEND && (is_eager == 1 || m->fwd.rend_send == 1))
{
bf->c29 = 1;
codes_issue_next_event(lp);
}
else
if(m->op_type == CODES_WK_ISEND)
if(m->op_type == CODES_WK_ISEND && (is_eager == 1 || m->fwd.rend_send == 1))
{
//tw_output(lp, "\n isend req id %llu ", m->fwd.req_id);
update_completed_queue(s, bf, m, lp, m->fwd.req_id);
bf->c28 = 1;
update_completed_queue(s, bf, m, lp, m->fwd.req_id);
}
else
tw_error(TW_LOC, "\n Invalid op type ");
}
break;
case MPI_OP_GET_NEXT:
case MPI_OP_GET_NEXT:
get_next_mpi_operation(s, bf, m, lp);
break;
......@@ -2699,9 +2748,9 @@ void nw_test_event_handler_rc(nw_state* s, tw_bf * bf, nw_message * m, tw_lp * l
case MPI_SEND_POSTED:
{
if(m->op_type == CODES_WK_SEND)
if(bf->c29)
codes_issue_next_event_rc(lp);
else if(m->op_type == CODES_WK_ISEND)
else if(bf->c28)
update_completed_queue_rc(s, bf, m, lp);
}
break;
......@@ -2713,7 +2762,17 @@ void nw_test_event_handler_rc(nw_state* s, tw_bf * bf, nw_message * m, tw_lp * l
break;
case MPI_REND_ARRIVED:
{
codes_local_latency_reverse(lp);
if(bf->c10)
codes_issue_next_event_rc(lp);
if(bf->c8)
update_completed_queue_rc(s, bf, m, lp);
s->recv_time = m->rc.saved_recv_time;
}
break;
case MPI_OP_GET_NEXT:
......@@ -2826,8 +2885,11 @@ st_model_types nw_lp_model_types[] = {
(ev_trace_f) nw_lp_event_collect,
sizeof(int),
(model_stat_f) nw_lp_model_stat_collect,
0,
NULL,
NULL,
0},
{NULL, 0, NULL, 0, NULL, 0}
{NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0}
};
static const st_model_types *nw_lp_get_model_stat_types(void)
......@@ -2978,7 +3040,7 @@ int modelnet_mpi_replay(MPI_Comm comm, int* argc, char*** argv )
nw_add_lp_type();
model_net_register();
if (g_st_ev_trace || g_st_model_stats)
if (g_st_ev_trace || g_st_model_stats || g_st_use_analysis_lps)
nw_lp_register_model();
net_ids = model_net_configure(&num_nets);
......
......@@ -107,6 +107,53 @@ tw_lptype svr_lp = {
sizeof(svr_state),
};
/* setup for the ROSS event tracing
* can have a different function for rbev_trace_f and ev_trace_f
* but right now it is set to the same function for both
*/
void custom_svr_event_collect(svr_msg *m, tw_lp *lp, char *buffer, int *collect_flag)
{
(void)lp;
(void)collect_flag;
int type = (int) m->svr_event_type;
memcpy(buffer, &type, sizeof(type));
}
/* can add in any model level data to be collected along with simulation engine data
* in the ROSS instrumentation. Will need to update the last field in
* svr_model_types[0] for the size of the data to save in each function call
*/
void custom_svr_model_stat_collect(svr_state *s, tw_lp *lp, char *buffer)
{
(void)s;
(void)lp;
(void)buffer;
return;
}
st_model_types custom_svr_model_types[] = {
{(rbev_trace_f) custom_svr_event_collect,
sizeof(int),
(ev_trace_f) custom_svr_event_collect,
sizeof(int),
(model_stat_f) custom_svr_model_stat_collect,
0,
NULL,
NULL,
0},
{NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0}
};
static const st_model_types *custom_svr_get_model_stat_types(void)
{
return(&custom_svr_model_types[0]);
}
void custom_svr_register_model_types()
{
st_model_type_register("nw-lp", custom_svr_get_model_stat_types());
}
const tw_optdef app_opt [] =
{
TWOPT_GROUP("Model net synthetic traffic " ),
......@@ -381,6 +428,9 @@ int main(
model_net_register();
svr_add_lp_type();
if (g_st_ev_trace || g_st_model_stats || g_st_use_analysis_lps)
custom_svr_register_model_types();
codes_mapping_setup();
net_ids = model_net_configure(&num_nets);
......
......@@ -137,8 +137,11 @@ st_model_types svr_model_types[] = {
(ev_trace_f) svr_event_collect,
sizeof(int),
(model_stat_f) svr_model_stat_collect,
0,
NULL,
NULL,
0},
{NULL, 0, NULL, 0, NULL, 0}
{NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0}
};
static const st_model_types *svr_get_model_stat_types(void)
......@@ -424,7 +427,7 @@ int main(
model_net_register();
svr_add_lp_type();
if (g_st_ev_trace || g_st_model_stats)
if (g_st_ev_trace || g_st_model_stats || g_st_use_analysis_lps)
svr_register_model_types();
codes_mapping_setup();
......
......@@ -276,6 +276,14 @@ struct terminal_state
/* for logging forward and reverse events */
long fwd_events;
long rev_events;
/* following used for ROSS model-level stats collection */
long fin_chunks_ross_sample;
long data_size_ross_sample;
long fin_hops_ross_sample;
tw_stime fin_chunks_time_ross_sample;
tw_stime busy_time_ross_sample;
struct dfly_cn_sample ross_sample;
};
/* terminal event type (1-4) */
......@@ -357,7 +365,44 @@ struct router_state
long fwd_events;
long rev_events;
/* following used for ROSS model-level stats collection */
tw_stime* busy_time_ross_sample;
int64_t * link_traffic_ross_sample;
struct dfly_router_sample ross_rsample;
};
/* had to pull some of the ROSS model stats collection stuff up here */
void custom_dragonfly_event_collect(terminal_custom_message *m, tw_lp *lp, char *buffer, int *collect_flag);
void custom_dragonfly_model_stat_collect(terminal_state *s, tw_lp *lp, char *buffer);
void custom_dfly_router_model_stat_collect(router_state *s, tw_lp *lp, char *buffer);
static void ross_custom_dragonfly_rsample_fn(router_state * s, tw_bf * bf, tw_lp * lp, struct dfly_router_sample *sample);
static void ross_custom_dragonfly_rsample_rc_fn(router_state * s, tw_bf * bf, tw_lp * lp, struct dfly_router_sample *sample);
static void ross_custom_dragonfly_sample_fn(terminal_state * s, tw_bf * bf, tw_lp * lp, struct dfly_cn_sample *sample);
static void ross_custom_dragonfly_sample_rc_fn(terminal_state * s, tw_bf * bf, tw_lp * lp, struct dfly_cn_sample *sample);
st_model_types custom_dragonfly_model_types[] = {
{(rbev_trace_f) custom_dragonfly_event_collect,
sizeof(int),
(ev_trace_f) custom_dragonfly_event_collect,
sizeof(int),
(model_stat_f) custom_dragonfly_model_stat_collect,
sizeof(tw_lpid) + sizeof(long) * 2 + sizeof(double) + sizeof(tw_stime) *2,
(sample_event_f) ross_custom_dragonfly_sample_fn,
(sample_revent_f) ross_custom_dragonfly_sample_rc_fn,
sizeof(struct dfly_cn_sample) } ,
{(rbev_trace_f) custom_dragonfly_event_collect,
sizeof(int),
(ev_trace_f) custom_dragonfly_event_collect,
sizeof(int),
(model_stat_f) custom_dfly_router_model_stat_collect,
0, //updated in router_setup() since it's based on the radix
(sample_event_f) ross_custom_dragonfly_rsample_fn,
(sample_revent_f) ross_custom_dragonfly_rsample_rc_fn,
0 } , //updated in router_setup() since it's based on the radix
{NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0}
};
/* End of ROSS model stats collection */
static short routing = MINIMAL;
......@@ -930,6 +975,8 @@ void router_custom_setup(router_state * r, tw_lp * lp)
r->fwd_events = 0;
r->rev_events = 0;
r->ross_rsample.fwd_events = 0;
r->ross_rsample.rev_events = 0;
r->global_channel = (int*)malloc(p->num_global_channels * sizeof(int));
......@@ -956,6 +1003,16 @@ void router_custom_setup(router_state * r, tw_lp * lp)
r->busy_time = (tw_stime*)malloc(p->radix * sizeof(tw_stime));
r->busy_time_sample = (tw_stime*)malloc(p->radix * sizeof(tw_stime));
/* set up for ROSS stats sampling */
r->link_traffic_ross_sample = (int64_t*)calloc(p->radix, sizeof(int64_t));
r->busy_time_ross_sample = (tw_stime*)calloc(p->radix, sizeof(tw_stime));
if (g_st_model_stats)
lp->model_types->mstat_sz = sizeof(tw_lpid) + (sizeof(int64_t) + sizeof(tw_stime)) * p->radix;
if (g_st_use_analysis_lps)
lp->model_types->sample_struct_sz = sizeof(struct dfly_router_sample) + (sizeof(tw_stime) + sizeof(int64_t)) * p->radix;
r->ross_rsample.busy_time = (tw_stime*)calloc(p->radix, sizeof(tw_stime));
r->ross_rsample.link_traffic_sample = (int64_t*)calloc(p->radix, sizeof(int64_t));
rc_stack_create(&r->st);
for(int i = 0; i < p->num_router_rows; i++)
......@@ -1295,6 +1352,8 @@ static void packet_send_rc(terminal_state * s, tw_bf * bf, terminal_custom_messa
s->busy_time = msg->saved_total_time;
s->last_buf_full[0] = msg->saved_busy_time;
s->busy_time_sample = msg->saved_sample_time;
s->ross_sample.busy_time_sample = msg->saved_sample_time;
s->busy_time_ross_sample = msg->saved_busy_time_ross;
}
}
return;
......@@ -1417,6 +1476,8 @@ static void packet_send(terminal_state * s, tw_bf * bf, terminal_custom_message
s->busy_time += (tw_now(lp) - s->last_buf_full[0]);
s->busy_time_sample += (tw_now(lp) - s->last_buf_full[0]);
s->ross_sample.busy_time_sample += (tw_now(lp) - s->last_buf_full[0]);
s->busy_time_ross_sample += (tw_now(lp) - s->last_buf_full[0]);
s->last_buf_full[0] = 0.0;
}
}
......@@ -1439,12 +1500,18 @@ static void packet_arrive_rc(terminal_state * s, tw_bf * bf, terminal_custom_mes
N_finished_chunks--;
s->finished_chunks--;
s->fin_chunks_sample--;
s->ross_sample.fin_chunks_sample--;
s->fin_chunks_ross_sample--;
total_hops -= msg->my_N_hop;
s->total_hops -= msg->my_N_hop;
s->fin_hops_sample -= msg->my_N_hop;
s->ross_sample.fin_hops_sample -= msg->my_N_hop;
s->fin_hops_ross_sample -= msg->my_N_hop;
dragonfly_total_time = msg->saved_total_time;
s->fin_chunks_time = msg->saved_sample_time;
s->ross_sample.fin_chunks_time = msg->saved_sample_time;
s->fin_chunks_time_ross_sample = msg->saved_fin_chunks_ross;
s->total_time = msg->saved_avg_time;
struct qhash_head * hash_link = NULL;
......@@ -1487,6 +1554,8 @@ static void packet_arrive_rc(terminal_state * s, tw_bf * bf, terminal_custom_mes
total_msg_sz -= msg->total_size;
s->total_msg_size -= msg->total_size;
s->data_size_sample -= msg->total_size;
s->ross_sample.data_size_sample -= msg->total_size;
s->data_size_ross_sample -= msg->total_size;
struct dfly_qhash_entry * d_entry_pop = (dfly_qhash_entry *)rc_stack_pop(s->st);
qhash_add(s->rank_tbl, &key, &(d_entry_pop->hash_link));
......@@ -1608,6 +1677,8 @@ static void packet_arrive(terminal_state * s, tw_bf * bf, terminal_custom_messag
s->finished_chunks++;
/* Finished chunks per sample */
s->fin_chunks_sample++;
s->ross_sample.fin_chunks_sample++;
s->fin_chunks_ross_sample++;
/* WE do not allow self messages through dragonfly */
assert(lp->gid != msg->src_terminal_id);
......@@ -1634,6 +1705,9 @@ static void packet_arrive(terminal_state * s, tw_bf * bf, terminal_custom_messag
/* save the sample time */
msg->saved_sample_time = s->fin_chunks_time;
s->fin_chunks_time += (tw_now(lp) - msg->travel_start_time);
s->ross_sample.fin_chunks_time += (tw_now(lp) - msg->travel_start_time);
msg->saved_fin_chunks_ross = s->fin_chunks_time_ross_sample;
s->fin_chunks_time_ross_sample += (tw_now(lp) - msg->travel_start_time);
/* save the total time per LP */
msg->saved_avg_time = s->total_time;
......@@ -1644,6 +1718,8 @@ static void packet_arrive(terminal_state * s, tw_bf * bf, terminal_custom_messag
total_hops += msg->my_N_hop;
s->total_hops += msg->my_N_hop;
s->fin_hops_sample += msg->my_N_hop;
s->ross_sample.fin_hops_sample += msg->my_N_hop;
s->fin_hops_ross_sample += msg->my_N_hop;
mn_stats* stat = model_net_find_stats(msg->category, s->dragonfly_stats_array);
msg->saved_rcv_time = stat->recv_time;
......@@ -1731,6 +1807,8 @@ static void packet_arrive(terminal_state * s, tw_bf * bf, terminal_custom_messag
bf->c7 = 1;
s->data_size_sample += msg->total_size;
s->ross_sample.data_size_sample += msg->total_size;
s->data_size_ross_sample += msg->total_size;
N_finished_msgs++;
total_msg_sz += msg->total_size;
s->total_msg_size += msg->total_size;
......@@ -1749,6 +1827,94 @@ static void packet_arrive(terminal_state * s, tw_bf * bf, terminal_custom_messag
return;
}
static void ross_custom_dragonfly_rsample_fn(router_state * s, tw_bf * bf, tw_lp * lp, struct dfly_router_sample *sample)
{
(void)lp;
(void)bf;
const dragonfly_param * p = s->params;
int i = 0;
sample->router_id = s->router_id;
sample->end_time = tw_now(lp);
sample->fwd_events = s->ross_rsample.fwd_events;
sample->rev_events = s->ross_rsample.rev_events;
sample->busy_time = (tw_stime*)((&sample->rev_events) + 1);
sample->link_traffic_sample = (int64_t*)((&sample->busy_time[0]) + p->radix);
for(; i < p->radix; i++)
{
sample->busy_time[i] = s->ross_rsample.busy_time[i];
sample->link_traffic_sample[i] = s->ross_rsample.link_traffic_sample[i];
}