[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);
}