[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [ns] Mac/Null mac-null.cc class from CMU
Here is a mac-null.cc which works with ns-2.1b6 (Courtesy of Li LI).
infinite bandwith.
add it to your makefile and replace
set opt(mac) Mac/802_11
by
set opt(mac) Mac/NULL
in your tcl simulation script to use it.
check out some other bugs of mac 802.11 at:
http://www.isi.edu/nsnam/archive/ns-users/webarch/2000/msg04162.html
/* mac-null.cc
$Id: mac-null.cc,v 1.1.1.1 2000/02/24 05:08:08 ns Exp $
implement a mac layer that IGNORES collisions. This layer allows the
simultaneous receipt of multiple packets.
If the variable no_delay_send_ is set to true
The layer delays packet 1 tx time on receipt, but sends back to back
packets immeadiately one after the other. Together, the effect is as
if the link had infinite BW, and the txtime is reassigned to propagation
delay.
else, the txtime is used to pace the sending of packets
*/
#include <packet.h>
#include <random.h>
// #define DEBUG
//#include <debug.h>
#include <mac.h>
#include <mac-802_11.h>
#include <cmu-trace.h>
/* LILI: in the new Mac implementation, index becomes index_,
* it is int type instead of unsigned int type
*/
class MacNULL;
class MacNULLTimer : public Handler {
public:
MacNULLTimer(MacNULL* m) : mac_(m), busy_(0) {}
virtual void handle(Event *e) = 0;
virtual inline void cancel() {
assert(0);
}
virtual void schedule(double t, Packet *p);
inline int busy(void) { return busy_; }
inline double expire(void) { return intr.time_; }
protected:
MacNULL *mac_;
Event intr;
int busy_;
};
class MacNULLSend : public MacNULLTimer {
public:
MacNULLSend(MacNULL* m) : MacNULLTimer(m) {}
virtual void handle(Event *e);
};
class MacNULLRecv : public MacNULLTimer {
public:
MacNULLRecv(MacNULL* m) : MacNULLTimer(m) {}
virtual void handle(Event *e);
virtual void schedule(double t, Packet *p);
};
class MacNULL : public Mac {
friend MacNULLSend;
friend MacNULLRecv;
public:
MacNULL();
void recv(Packet *p, Handler *h);
private:
int command(int argc, const char*const* argv);
void discard(Packet *p, const char* why);
void send(Packet *p, Handler *h);
MacNULLSend send_timer_;
MacNULLRecv recv_timer_;
void sendComplete(Packet *p);
void recvComplete(Packet *p);
Handler *upcall_;
int no_delay_send_; // if true, packets can be sent back-to-back
/*
* logging functions
*/
virtual void Terminate() {
/* nothing to do */
}
virtual void cnt_air_time(MacState) { abort(); }
virtual void end_air_time(MacState, int) { abort(); }
virtual void log_mib_data(void) { /* nothing to do */ }
virtual void netif_idle(void) { abort(); }
virtual void netif_busy(void) { abort(); }
virtual double netif_power(int /* dst */) { abort(); }
/*
* Debugging Functions.
*/
void trace_pkt(Packet *p);
void dump(char* fname);
inline int initialized() {
return (Mac::initialized());
}
virtual void init() {
return;
}
private:
/* ============================================================
Internal MAC State
============================================================ */
int min_frame_len;
};
static class MacNULLClass : public TclClass {
public:
MacNULLClass() : TclClass("Mac/NULL") {}
TclObject* create(int, const char*const*) {
return (new MacNULL);
}
} class_macNULL;
/* ======================================================================
Mac Class Functions
====================================================================== */
MacNULL::MacNULL(): send_timer_(this), recv_timer_(this),
upcall_(0), no_delay_send_(1) //LILI: LILI_ATTENTION 0 before, changed to 1 for in-order delivery
{
//bind("no_delay_send_", &no_delay_send_);
#ifdef notdef
fprintf(stderr,
"WARNING: null MAC layer selected. ignoring collisions\n");
#endif
}
int
MacNULL::command(int argc, const char*const* argv)
{
return Mac::command(argc, argv);
}
/* ======================================================================
Debugging Routines
====================================================================== */
void
MacNULL::trace_pkt(Packet *p) {
struct hdr_cmn *ch = HDR_CMN(p);
fprintf(stderr, "\t_%d_ %s %d\n",
index_, packet_info.name(ch->ptype()), ch->size());
}
void
MacNULL::dump(char *fname)
{
fprintf(stderr,
"\n%s --- (INDEX: %d, time: %2.9f)\n",
fname, index_, Scheduler::instance().clock());
}
/* ======================================================================
Incoming Packet Routines
====================================================================== */
void
MacNULL::recv(Packet *p, Handler *h)
{
struct hdr_cmn *hdr = HDR_CMN(p);
hdr_mac* mh = (hdr_mac*)p->access(hdr_mac::offset_);
/*
* Sanity Check
*/
assert(initialized());
/*
* Handle outgoing packets.
*/
if(h) {
// give target a copy, so we can still use p
downtarget()->recv(p->copy(), h);
if (no_delay_send_) {
// tell IFQ to send down the next packet immeadiately
// NOTE: see comments at top of file
upcall_ = h;
sendComplete(p);
} else {
assert(upcall_ == 0);
upcall_ = h;
send_timer_.schedule(netif_->txtime(p),p);
}
return;
}
/*
* Handle incoming packets.
*
* We just received the 1st bit of a packet on the network
* interface.
*
*/
if (mh->macDA_ != index_ &&
mh->macDA_ != MAC_BROADCAST) {
/*
* We don't want to log this event, so we just free
* the packet instead of calling the drop routine.
*/
Packet::free(p);
goto done;
}
if (hdr->error() ) {
discard(p, DROP_MAC_PACKET_ERROR);
goto done;
}
/*
* reception of this packet will finish in
* txtime seconds. schedule completion then
*/
recv_timer_.schedule(netif_->txtime(p), p);
done:
return;
}
void
MacNULL::discard(Packet *p, const char* why)
{
hdr_mac * mh = (hdr_mac *)p->access(hdr_mac::offset_);
if (mh->macDA_ == index_)
drop(p, why);
else
Packet::free(p);
}
void
MacNULL::send(Packet *, Handler *)
{
fprintf(stderr,"DFU: shouldn't ever reach here %s\n",
__PRETTY_FUNCTION__);
abort();
}
void
MacNULL::sendComplete(Packet *p)
{
hdr_mac* mh = (hdr_mac*)p->access(hdr_mac::offset_);
// provide a mac layer failure indication if needed.
// this is completely bogus, but this is a test-only MAC
// layer anyway
if (mh->macDA_ != MAC_BROADCAST) {
// fprintf(stderr,"LILI***shouldn't be here...index_:%d\t macDA:%x\t macSA:%x\n",
// index_, HDR_MAC(p)->macDA_, HDR_MAC(p)->macSA_ );
if (mh->macSA_ != mh->macDA_
&& God::instance()->hops(mh->macSA_, mh->macDA_) == 0) {
fprintf(stderr,"Mac/NULL mac layer requires that scenario file have\n"
" god data added. see calcdest or setdest\n");
abort();
}
if (God::instance()->hops(mh->macSA_, mh->macDA_) > 1) {
//tell the callback the send operation failed
hdr_cmn *ch = HDR_CMN(p);
if (ch->xmit_failure_) {
ch->xmit_reason_ = XMIT_REASON_RTS;
ch->xmit_failure_(p->copy(), ch->xmit_failure_data_);
}
}
}
Packet::free(p); // no drop reason needed
// have the upper layer (probably the IFQ) unblock itself now
assert(upcall_ != 0);
Handler *h = upcall_;
upcall_ = 0;
h->handle((Event *) 0);
}
void
MacNULL::recvComplete(Packet *p)
{
p->incoming = 1;
if (tap_) {
tap_->tap(p);
}
// LILI 10/26/00 modify ch header.
struct hdr_cmn *ch = HDR_CMN(p);
ch->num_forwards() += 1;
uptarget()->recv(p, (Handler *) 0);
}
void
MacNULLTimer::schedule(double t, Packet *p)
{
Scheduler& s = Scheduler::instance();
assert(busy_ == 0);
s.schedule(this, p, t);
busy_ = 1;
}
void
MacNULLSend::handle(Event *e)
{
Packet *p = (Packet *)e; // cast of trust
busy_ = 0;
mac_->sendComplete(p);
}
void
MacNULLRecv::schedule(double t, Packet *p)
{
Scheduler& s = Scheduler::instance();
busy_++;
s.schedule(this, p, t);
}
void
MacNULLRecv::handle(Event *e)
{
Packet *p = (Packet *)e; // cast of trust
busy_--;
mac_->recvComplete(p);
}