[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: C on ns
Sender: [email protected]
Date: Mon, 01 Dec 1997 15:58:52 +0100
From: Arioli Carlo <[email protected]>
Reply-To: [email protected]
Organization: CEFRIEL
I'm a new users who should start a project for my own degree thesys
using
ns as a simulator. The problem I need to solve is whether it is
possible to include a code written in C for an agenet on a node of ns
simulator.
Where can I find some information on this procedure ?? I'm new and I
wanto to know
whether it is possible to use ns for my purpose . Thank you very much to
anybody who could help me
I've actually just done this. I have reliable multicast code based on
IMM that I rewrote in C. In order to intergrate it into NS, I created
a base class derived from Agent that had all of the NS stuff in it.
That code then just calls the C code. The only little annoyance was
calling C++ from C. I couldn't get it to work the way I wanted it to
due to the name mangling, so I had to hack around it with #defines.
You probably just need the Sudafed class. The MiniSched is used to
interface with some event driven stuff I have in my live code.
In my C code, I had to add the following define for example:
#ifdef SIMULATOR
#undef event_post
#define event_post(args...) event_post__FPvPFv_ide(src->agent, ## args)
#endif
in order to call the event_post() function defined below.
The nice part of all of this is that my code now works in NS or live
with the same core source files.
I've included the C++ code below.
----------------------------------------------------------------------------
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "tclcl.h"
#include "agent.h"
#include "packet.h"
#include "ip.h"
#include "rtp.h"
#include "trace.h"
#include "random.h"
extern "C"
{
#include "cqueue.h"
#include "list.h"
#include "log.h"
#include "congestion.h"
#include "imm-protocol.h"
#include "imm.h"
#include "action.h"
int ns_send_buffer (void *agent, char *buffer, int length);
void event_cancel (void *agent, Action *action);
void *event_post (void *agent, int (*action) (), TIME how_soon, ...);
double unit_variate ();
}
#define CURRENT_TIME Scheduler::instance().clock()
double current_time;
class SudafedAgent;
class MiniSched : public TimerHandler
{
public:
// MiniSched(SudafedAgent *a) : queue (NULL), TimerHandler() { a_ = a; }
MiniSched(SudafedAgent *a) : queue (NULL), TimerHandler() { a_ = a; }
Action *va_post (int func(), double time, va_list ap);
void reschedule ();
void cancel (Action *a);
void print ();
protected:
void expire(Event *e);
Action *queue;
SudafedAgent *a_;
};
class SudafedAgent : public Agent
{
protected:
RMSource *rm_source;
RMReceiver *rm_receiver;
void sendpkt();
int off_cmn_;
int off_rtp;
int i_am_a_server;
public:
MiniSched mini_sched;
SudafedAgent();
int command(int argc, const char*const* argv);
void recv(Packet* p, Handler* h);
void send_packet (unsigned char *buffer, int length);
};
static class SudafedAgentClass : public TclClass {
public:
SudafedAgentClass() : TclClass("Agent/Sudafed") {}
TclObject* create(int, const char*const*) {
return (new SudafedAgent());
}
} class_Sudafed_agent;
SudafedAgent::SudafedAgent()
: Agent(PT_RTP),
mini_sched(this),
rm_source(NULL)
{
bind("off_cmn_", &off_cmn_);
/* bind("packetSize_", &packetSize_);*/
rm_receiver = rm_receiver_new ();
rm_receiver->addr = addr_;
rm_receiver->agent = this;
}
void
SudafedAgent::send_packet (unsigned char *buffer, int length)
{
Packet* p = Agent::allocpkt(length);
unsigned char *data = p->accessdata();
hdr_cmn* ch = (hdr_cmn*) p->access(off_cmn_);
memcpy (data, buffer, length);
ch->size() = length;
send (p, 0);
}
void
SudafedAgent::recv(Packet* p, Handler* h)
{
hdr_ip* ih = (hdr_ip*) p->access(off_ip_);
hdr_cmn* ch = (hdr_cmn*) p->access(off_cmn_);
unsigned char *data = p->accessdata();
int length = ch->size();
current_time = CURRENT_TIME;
if (ih->src () == addr_)
return;
if (rm_source)
{
rm_receiver->addr = addr_;
imm_server_receive (rm_source, &ih->src(), data, length);
}
else
{
rm_receiver->addr = addr_;
imm_client_receive (rm_receiver, &ih->src(), data, length);
}
Packet::free (p);
}
int
SudafedAgent::command(int argc, const char*const* argv)
{
Tcl& tcl = Tcl::instance();
/* current_time = CURRENT_TIME;*/
if (argc == 2)
{
if (strcmp(argv[1], "start") == 0)
{
// deliver ("foo", "bar", 1024*32, 0, 20);
return (TCL_OK);
}
if (strcmp(argv[1], "stop") == 0)
{
// stop();
return (TCL_OK);
}
} if (argc == 3)
{
int size;
if (strcmp (argv[1], "send-file") == 0)
{
if (rm_source == NULL)
{
rm_source = rm_source_new ();
rm_source->addr = addr_;
rm_source->dest = dst_;
rm_source->agent = this;
}
imm_send_file_or_directory (rm_source, argv[2]);
return (TCL_OK);
}
}
return Agent::command(argc, argv);
}
void
MiniSched::print ()
{
Action **p;
printf ("MiniSched 0x%x", this);
for (p = &queue; *p != 0; p = &(*p)->next)
{
printf ("\n ");
action_print (*p);
}
printf ("\n");
}
Action *
MiniSched::va_post (int func(), double time, va_list ap)
{
Action** p;
Action *action;
double t;
// printf ("MiniSched:va_post start\n");
// print();
action = va_action_new (time, func, ap);
/* insert action into list */
t = action->time;
for (p = &queue; *p != 0; p = &(*p)->next)
if (t < (*p)->time)
break;
action->next = *p;
*p = action;
if (queue == action)
reschedule ();
// printf ("MiniSched:va_post finish\n");
// print();
return (action);
}
void
MiniSched::cancel(Action *a)
{
Action** p;
// printf ("MiniSched::cancel\n");
// print();
for (p = &queue; *p != a; p = &(*p)->next)
if (*p == 0)
abort();
*p = (*p)->next;
action_free (a);
reschedule ();
// printf ("MiniSched::cancel(after)\n");
// print();
}
// schedule the first thing in the list
void
MiniSched::reschedule ()
{
double delay;
if (queue)
{
delay = queue->time - current_time;
resched (delay);
}
else
{
TimerHandler::cancel();
}
}
void
MiniSched::expire (Event *e)
{
Action *action;
/* since we expired, there must be something on the queue. Take
* the first thing and do it.
*/
current_time = CURRENT_TIME;
action = queue;
queue = action->next;
action->next = NULL;
action_execute (action);
action_free (action);
if (queue)
reschedule ();
}
/* some glue functions for C. Requires bizzare #defines in localdefs.h
* to handle name mangeling.
*/
void *
event_post (void *agent, int (*action) (), TIME how_soon, ...)
{
SudafedAgent *a = (SudafedAgent *)agent;
void *result;
va_list ap;
va_start (ap, how_soon);
result = a->mini_sched.va_post(action, how_soon, ap);
va_end (ap);
return (result);
}
void
event_cancel (void *agent, Action *action)
{
SudafedAgent *a = (SudafedAgent *)agent;
a->mini_sched.cancel (action);
}
int
ns_send_buffer (void *agent, unsigned char *buffer, int length)
{
SudafedAgent *a = (SudafedAgent *)agent;
a->send_packet (buffer, length);
return (length);
}
double
unit_variate ()
{
return Random::uniform();
}