Commit a9cd0174 authored by Leigh B. Stoller's avatar Leigh B. Stoller
Browse files

Support for using the delay agent with linkdelays (which means running

on end nodes). Add support for lans (only duplex links were really
supported). Finish up simplex vs duplex stuff wrt the delay_mapping
file. Some cleanup, but this program needs a total rewrite and I was
not in the mood.
parent 65b17f18
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2002 University of Utah and the Flux Group.
* All rights reserved.
*/
/*
* agent-callback-dummy.c --
*
* Delay node agent callback handling.
*/
/******************************* INCLUDES **************************/
#include "main-d.h"
/******************************* INCLUDES **************************/
/******************************* EXTERNS **************************/
extern structlink_map link_map[MAX_LINKS];
extern int link_index;
extern int s_dummy;
/******************************* EXTERNS **************************/
/********************************FUNCTION DEFS *******************/
/*************************** agent_callback **********************
This function is called from the event system when an event
notification is recd. from the server. It checks whether the
notification is valid (sanity check). If not print a warning,else
call handle_pipes which does the rest of thejob
*************************** agent_callback **********************/
void agent_callback(event_handle_t handle,
event_notification_t notification, void *data)
{
#define MAX_LEN 50
char objname[MAX_LEN];
char eventtype[MAX_LEN];
int l_index = -1;
#ifdef DEBUG
info ("entering callback \n");
#endif
/* get the name of the object, eg. link0 or link1*/
if(event_notification_get_string(handle,
notification,
"OBJNAME", objname, MAX_LEN) == 0){
error("could not get the objname \n");
return;
}
/* check we are handling the objectname for which we have recd an event */
if ((l_index = check_object(objname)) == -1){
error("not handling events for this object\n");
return;
}
/* get the eventtype, eg up/down/modify*/
if(event_notification_get_string(handle,
notification,
"EVENTTYPE", eventtype, MAX_LEN) == 0){
error("could not get the eventtype \n");
return;
}
/* call function to handle this event for this object */
handle_event(objname, eventtype, notification,handle);
#ifdef DEBUG
info ("exiting callback \n");
#endif
return;
}
/******************** handle_pipes ***************************************
******************** handle_pipes ***************************************/
void handle_event (char *objname, char *eventtype,
event_notification_t notification, event_handle_t handle)
{
#ifdef DEBUG
info ("entering handle_event \n");
#endif
if(strcmp(eventtype, TBDB_EVENTTYPE_UP) == 0){
handle_link_up(objname);
}
else if(strcmp(eventtype, TBDB_EVENTTYPE_DOWN) == 0){
handle_link_down(objname);
}
else if(strcmp(eventtype, TBDB_EVENTTYPE_MODIFY) == 0){
handle_link_modify(objname, handle, notification);
}
else error("unknown link event type\n");
#ifdef DEBUG
info ("exiting handle_event \n");
#endif
}
void handle_link_up(char * linkname){
#ifdef DEBUG
info ("entering handle_link_up \n");
#endif
info("recd. UP event for link = %s\n", linkname);
#ifdef DEBUG
info ("exiting handle_link_up \n");
#endif
}
void handle_link_down(char * linkname)
{
#ifdef DEBUG
info ("entering handle_link_down \n");
#endif
info("recd. DOWN event for link = %s\n", linkname);
#ifdef DEBUG
info ("exiting handle_link_down \n");
#endif
}
void handle_link_modify(char *linkname, event_handle_t handle,
event_notification_t notification)
{
char argvalue[50];
char * argtype;
int bw = 0, delay = 0;
#ifdef DEBUG
info ("entering handle_link_modify \n");
#endif
info("recd. MODIFY event for link = %s\n", linkname);
if(event_notification_get_string(handle,
notification,
"ARGS", argvalue, 50) != 0){
argtype = strtok(argvalue,"=");
if(strcmp(argtype,"BANDWIDTH")== 0){
bw = atoi(strtok(NULL," "));
info("Bandwidth = %d \n", bw);
}else if (strcmp(argtype,"DELAY")== 0){
delay = atoi(strtok(NULL," "));
info("Delay = %d \n", delay);
}else error("unrecognized argument\n");
}
#ifdef DEBUG
info ("exiting handle_link_modify \n");
#endif
}
int check_object (char *objname)
{
return search(objname);
}
/*********************** search ********************************
This function does a linear search on the link_map and returns
the index of the link_map entry which matches with the objectname
from the event notification
There will hardly be a few entries in this table, so we dont need
anything fancier than a linear search.
*********************** search ********************************/
int search(char* objname){
/* for now we do a linear search, maybe bin search later*/
int i;
for(i = 0; i < link_index; i++){
if(strcmp(link_map[i].linkname, objname) == 0)
return i;
}
return -1;
}
/* /*
* EMULAB-COPYRIGHT * EMULAB-COPYRIGHT
* Copyright (c) 2000-2002 University of Utah and the Flux Group. * Copyright (c) 2000-2003 University of Utah and the Flux Group.
* All rights reserved. * All rights reserved.
*/ */
...@@ -42,7 +42,7 @@ void agent_callback(event_handle_t handle, ...@@ -42,7 +42,7 @@ void agent_callback(event_handle_t handle,
char objname[MAX_LEN]; char objname[MAX_LEN];
char eventtype[MAX_LEN]; char eventtype[MAX_LEN];
int l_index; int i;
/* get the name of the object, eg. link0 or link1*/ /* get the name of the object, eg. link0 or link1*/
if(event_notification_get_string(handle, if(event_notification_get_string(handle,
...@@ -52,12 +52,6 @@ void agent_callback(event_handle_t handle, ...@@ -52,12 +52,6 @@ void agent_callback(event_handle_t handle,
return; return;
} }
/* check we are handling the objectname for which we have recd an event */
if ((l_index = check_object(objname)) == -1){
error("not handling events for this object\n");
return;
}
/* get the eventtype, eg up/down/modify*/ /* get the eventtype, eg up/down/modify*/
if(event_notification_get_string(handle, if(event_notification_get_string(handle,
notification, notification,
...@@ -66,10 +60,17 @@ void agent_callback(event_handle_t handle, ...@@ -66,10 +60,17 @@ void agent_callback(event_handle_t handle,
return; return;
} }
/* call function to handle this event for this object */ /*
handle_pipes(objname, eventtype,notification, handle,l_index); * We could be an agent for several nodes on the same lan, so need to
* loop over the pipe sets and possibly repeat all the work multiple
return; * times. Sigh.
*/
for(i = 0; i < link_index; i++){
if(!strcmp(link_map[i].linkname, objname) ||
!strcmp(link_map[i].linkvnodes[0], objname) ||
!strcmp(link_map[i].linkvnodes[1], objname))
handle_pipes(objname, eventtype, notification, handle, i);
}
} }
/******************** handle_pipes *************************************** /******************** handle_pipes ***************************************
...@@ -84,30 +85,16 @@ void handle_pipes (char *objname, char *eventtype, ...@@ -84,30 +85,16 @@ void handle_pipes (char *objname, char *eventtype,
/*link_map[index] contains the relevant info*/ /*link_map[index] contains the relevant info*/
/* as of now, we only support duplex links in the testbed. Also we if(strcmp(eventtype, TBDB_EVENTTYPE_UP) == 0){
require that both pipes of the duplex link are changed during the handle_link_up(objname, l_index);
event callback. Later when we add simplex links, we will also add }
support to send event which will have effect on only one side of a else if(strcmp(eventtype, TBDB_EVENTTYPE_DOWN) == 0){
duplex link. handle_link_down(objname, l_index);
*/ }
if(strcmp(link_map[l_index].linktype,"duplex") == 0){ else if(strcmp(eventtype, TBDB_EVENTTYPE_MODIFY) == 0){
handle_link_modify(objname, l_index, handle, notification);
if(strcmp(eventtype, TBDB_EVENTTYPE_UP) == 0){
handle_link_up(objname, l_index);
}
else if(strcmp(eventtype, TBDB_EVENTTYPE_DOWN) == 0){
handle_link_down(objname, l_index);
}
else if(strcmp(eventtype, TBDB_EVENTTYPE_MODIFY) == 0){
handle_link_modify(objname, l_index, handle, notification);
}
else error("unknown link event type\n");
} }
else { else error("unknown link event type\n");
error( "not handling simplex links yet ");
return;
}
if(debug){ if(debug){
system ("echo ======================================== >> /tmp/ipfw.log"); system ("echo ======================================== >> /tmp/ipfw.log");
...@@ -115,36 +102,6 @@ void handle_pipes (char *objname, char *eventtype, ...@@ -115,36 +102,6 @@ void handle_pipes (char *objname, char *eventtype,
} }
} }
/***************** checkevent **************************************
* checks if we are handling the link for which we got the event
***************** checkevent **************************************/
int check_object (char *objname)
{
return search(objname);
}
/*********************** search ********************************
This function does a linear search on the link_map and returns
the index of the link_map entry which matches with the objectname
from the event notification
There will hardly be a few entries in this table, so we dont need
anything fancier than a linear search.
*********************** search ********************************/
int search(char* objname){
/* for now we do a linear search, maybe bin search later*/
int i;
for(i = 0; i < link_index; i++){
if(strcmp(link_map[i].linkname, objname) == 0)
return i;
}
return -1;
}
/******************* handle_link_up ************************** /******************* handle_link_up **************************
This handles the link_up event. If link is already up, it returns This handles the link_up event. If link is already up, it returns
without doing anything. If link is down, it calls set_link_params without doing anything. If link is down, it calls set_link_params
...@@ -158,22 +115,14 @@ void handle_link_up(char * linkname, int l_index) ...@@ -158,22 +115,14 @@ void handle_link_up(char * linkname, int l_index)
link_map table. Set the pipe params in dummynet link_map table. Set the pipe params in dummynet
*/ */
info("==========================================\n"); info("==========================================\n");
info("recd. UP event for link = %s\n", linkname); info("recd. UP event for link = %s\n", linkname);
/* no need to do anything if link is already up*/ /* no need to do anything if link is already up*/
if(link_map[l_index].stat == LINK_UP) if(link_map[l_index].stat == LINK_UP)
return; return;
#if 1 link_map[l_index].stat = LINK_UP;
/* 0 => dont blackhole, get the plr from the link map table set_link_params(l_index, 0, -1);
2 => both pipes
-1 => both pipes*/
set_link_params(l_index, 0, 2, -1);
link_map[l_index].stat = LINK_UP;
info("==========================================\n");
#endif
} }
/******************* handle_link_down ************************** /******************* handle_link_down **************************
...@@ -191,24 +140,17 @@ void handle_link_down(char * linkname, int l_index) ...@@ -191,24 +140,17 @@ void handle_link_down(char * linkname, int l_index)
* Change the pipe config so that plr = 1.0 * Change the pipe config so that plr = 1.0
* so that packets are blackholed * so that packets are blackholed
*/ */
info("==========================================\n"); info("==========================================\n");
info("recd. DOWN event for link = %s\n", linkname); info("recd. DOWN event for link = %s\n", linkname);
if(link_map[l_index].stat == LINK_DOWN)
return;
/* if link is already down, no need to do anything*/
if(link_map[l_index].stat == LINK_DOWN)
return;
#if 1
if(get_link_params(l_index) == 1){ if(get_link_params(l_index) == 1){
/* 1 => set plr = 1.0 to blackhole packets
2 => both pipes
-1 => both pipes*/
set_link_params(l_index, 1, 2, -1);
link_map[l_index].stat = LINK_DOWN; link_map[l_index].stat = LINK_DOWN;
set_link_params(l_index, 1, -1);
} }
else error("could not get params\n"); else error("could not get params\n");
#endif
info("==========================================\n");
} }
/*********** handle_link_modify ***************************** /*********** handle_link_modify *****************************
...@@ -226,12 +168,29 @@ void handle_link_modify(char * linkname, int l_index, ...@@ -226,12 +168,29 @@ void handle_link_modify(char * linkname, int l_index,
update the new set of params by setting the params in update the new set of params by setting the params in
dummynet dummynet
*/ */
int p_which = -1; int i, p_which = -1;
int n_pipes = 0;
// char argstring[50];
info("==========================================\n"); info("==========================================\n");
info("recd. MODIFY event for link = %s\n", linkname); info("recd. MODIFY event for link = %s\n", linkname);
/*
* As a convience to the user, we create virt_agents entries
* for each "link-vnode" so that users can talk to a specific
* side of a duplex link, or a specific node in a lan (in which
* case it refers to both pipes, not just one). Look at the
* object name to determine ahead of time which pipe. Note that
* for the lan node case, the virt agent entry exists strictly
* to direct the event to this agent; there might be an actual
* pipe spec inside the event if the user wants to one side
* of the link (to the switch or from the switch).
*/
if (!link_map[l_index].islan) {
for (i = 0; i < link_map[l_index].numpipes; i++) {
if(!strcmp(link_map[l_index].linkvnodes[i], linkname)) {
p_which = i;
}
}
}
/* if the link is up, then get the params from dummynet, /* if the link is up, then get the params from dummynet,
get the params from the notification and then merge get the params from the notification and then merge
...@@ -239,18 +198,11 @@ void handle_link_modify(char * linkname, int l_index, ...@@ -239,18 +198,11 @@ void handle_link_modify(char * linkname, int l_index,
*/ */
if(link_map[l_index].stat == LINK_UP){ if(link_map[l_index].stat == LINK_UP){
if(get_link_params(l_index) == 1) if(get_link_params(l_index) == 1)
if(get_new_link_params(l_index, handle, notification, if(get_new_link_params(l_index, handle, notification, &p_which) == 1)
&n_pipes,&p_which) == 1) set_link_params(l_index, 0, p_which);
/* 0 => dont blackhole, get the plr
* from the link map table*/
/*info(" n_pipes = %d p_which = %d\n", n_pipes, p_which);*/
set_link_params(l_index, 0, n_pipes, p_which);
} else } else
/* link is down, so just change in the link_map*/ /* link is down, so just change in the link_map*/
get_new_link_params(l_index, handle, notification, get_new_link_params(l_index, handle, notification, &p_which);
&n_pipes, &p_which);
} }
/****************** get_link_params *************************** /****************** get_link_params ***************************
...@@ -267,7 +219,7 @@ int get_link_params(int l_index) ...@@ -267,7 +219,7 @@ int get_link_params(int l_index)
void * data = NULL; void * data = NULL;
int p_index = 0; int p_index = 0;
int pipe_num; int pipe_num;
while( p_index < 2){ while( p_index < link_map[l_index].numpipes ){
pipe_num = link_map[l_index].pipes[p_index]; pipe_num = link_map[l_index].pipes[p_index];
...@@ -439,19 +391,19 @@ for both the pipes of the duplex link, set the pipe params ...@@ -439,19 +391,19 @@ for both the pipes of the duplex link, set the pipe params
sing setsockopt getting the param values from the link_map table sing setsockopt getting the param values from the link_map table
**************************************************************/ **************************************************************/
void set_link_params(int l_index, int blackhole,int t_pipes, int p_which) void set_link_params(int l_index, int blackhole, int p_which)
{ {
/* Grab the pipe params from the link_map table and then /* Grab the pipe params from the link_map table and then
set them into dummynet by calling setsockopt set them into dummynet by calling setsockopt
*/ */
/*bw, delay, plr, buckets, qsize, mask, qtype*/ int p_index;
int p_index = 0; for (p_index = 0; p_index < link_map[l_index].numpipes; p_index++) {
/*
while(p_index < 2) * Want to do all the pipes, or just the one pipe that was
{ * specified.
if((t_pipes == 2) || (t_pipes == 0) || (p_which == p_index)) */
{ if(p_which == -1 || p_which == p_index) {
struct dn_pipe pipe; struct dn_pipe pipe;
/* get the params stored in the link table*/ /* get the params stored in the link table*/
structpipe_params *p_params structpipe_params *p_params
...@@ -472,30 +424,22 @@ void set_link_params(int l_index, int blackhole,int t_pipes, int p_which) ...@@ -472,30 +424,22 @@ void set_link_params(int l_index, int blackhole,int t_pipes, int p_which)
then we set all other pipe params same, but change the then we set all other pipe params same, but change the
plr to 1.0 plr to 1.0
*/ */
{
if(blackhole == 1){ double d = p_params->plr;
double d = 1.0;
if (blackhole)
d = 1.0;
pipe.fs.plr = (int)(d*0x7fffffff); pipe.fs.plr = (int)(d*0x7fffffff);
} }
else{ /* we want to change plr*/
/* if the pipe was initially down, and if the user wants it up and he
has not specied any plr, then use the default plr = 0.0*/
if((int)(p_params->plr) == 1)
pipe.fs.plr = (int)(0*0x7fffffff);
else
pipe.fs.plr = (int)(p_params->plr*0x7fffffff);
}
/* set the queue size*/ /* set the queue size*/
pipe.fs.qsize = p_params->q_size; pipe.fs.qsize = p_params->q_size;
/* set the number of buckets used for dynamic queues*/ /* set the number of buckets used for dynamic queues*/
pipe.fs.rq_size = p_params->buckets; pipe.fs.rq_size = p_params->buckets;
#if 0 #if 0
pipe.fs.rq_elements = num_qs; pipe.fs.rq_elements = num_qs;
#endif #endif
/* initialise pipe flags to zero */ /* initialise pipe flags to zero */
pipe.fs.flags_fs = 0; pipe.fs.flags_fs = 0;
...@@ -604,10 +548,7 @@ void set_link_params(int l_index, int blackhole,int t_pipes, int p_which) ...@@ -604,10 +548,7 @@ void set_link_params(int l_index, int blackhole,int t_pipes, int p_which)
< 0) < 0)
error("IP_DUMMYNET_CONFIGURE setsockopt failed\n"); error("IP_DUMMYNET_CONFIGURE setsockopt failed\n");
} }
/* go on to the next pipe in the duplex link*/
p_index++;
} }
} }
/********* get_new_link_params *************************** /********* get_new_link_params ***************************
...@@ -616,23 +557,28 @@ void set_link_params(int l_index, int blackhole,int t_pipes, int p_which) ...@@ -616,23 +557,28 @@ void set_link_params(int l_index, int blackhole,int t_pipes, int p_which)
********************************************************/ ********************************************************/
int get_new_link_params(int l_index, event_handle_t handle, int get_new_link_params(int l_index, event_handle_t handle,
event_notification_t notification, int* p_pipes, event_notification_t notification, int *pipe_which)
int * pipe_which)
{ {
/* get the params of the pipe that were sent in the notification and /* get the params of the pipe that were sent in the notification and
store those values into the link_map table store those values into the link_map table
*/ */
char argstring[50]; char argstring[256];
char * argtype = NULL; char * argtype = NULL;
char * argvalue = NULL; char * argvalue = NULL;
int tot_pipes = 0; int p_num = 0;
int p_num = -1; int gotpipe = 0;
int islan = link_map[l_index].islan;
char *temp = NULL; char *temp = NULL;
/* Allow upper level to init the pipe */
if (*pipe_which >= 0) {
gotpipe = 1;
p_num = *pipe_which;
}