mac-802_3.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * mac-802_3.cc
00004  * $Id: mac-802_3.cc,v 1.16 2002/06/14 23:15:03 yuri Exp $
00005  */
00006 #include <packet.h>
00007 #include <random.h>
00008 #include <arp.h>
00009 #include <ll.h> 
00010 #include <mac-802_3.h>
00011 
00012 //#define MAC_DEBUG
00013 
00014 #ifndef MAC_DEBUG
00015 #define FPRINTF(s, f, t, index, func) do {} while (0)
00016 #else
00017    static double xtime= 0.0;
00018 #  define FPRINTF(s, f, t, index, func) \
00019          do { fprintf(s, f, t, index, func); xtime= t; } while (0)
00020 #endif //MAC_DEBUG
00021 
00022 #define PRNT_MAC_FUNCS(mac) \
00023     FPRINTF(stderr, "%.15f : %d : %s\n", \
00024         Scheduler::instance().clock(), (mac)->index_, __PRETTY_FUNCTION__)
00025 
00026 inline void MacHandler::cancel() {
00027     PRNT_MAC_FUNCS(mac);
00028     Scheduler& s = Scheduler::instance();
00029     assert(busy_);
00030     s.cancel(&intr);
00031     // No need to free the event intr since it's statically allocated.
00032     busy_ = 0;
00033 }
00034 
00035 inline void Mac8023HandlerSend::cancel() {
00036     PRNT_MAC_FUNCS(mac);
00037     assert(busy_);
00038     Scheduler &s= Scheduler::instance();
00039     s.cancel(&intr);
00040     busy_= 0;
00041     p_= 0;
00042 }
00043 
00044 inline void MacHandlerRecv::cancel() {
00045     PRNT_MAC_FUNCS(mac);
00046     Scheduler& s = Scheduler::instance();
00047     assert(busy_ && p_);
00048     s.cancel(&intr);
00049     busy_ = 0;
00050     Packet::free(p_);
00051     p_= 0;
00052 }
00053 
00054 inline void MacHandlerRetx::cancel() {
00055     PRNT_MAC_FUNCS(mac);
00056     Scheduler& s = Scheduler::instance();
00057     assert(busy_ && p_);
00058     s.cancel(&intr);
00059 }
00060 
00061 inline void MacHandlerIFS::cancel() {
00062     PRNT_MAC_FUNCS(mac);
00063     //fprintf (stderr, "cancelled dtime= %.15f\n", intr.time_- Scheduler::instance().clock());
00064     MacHandler::cancel();
00065 }
00066 static class Mac802_3Class : public TclClass {
00067 public:
00068     Mac802_3Class() : TclClass("Mac/802_3") {}
00069     TclObject* create(int, const char*const*) {
00070         return (new Mac802_3);
00071     }
00072 } class_mac802_3;
00073 
00074 void Mac8023HandlerSend::handle(Event*) {
00075     PRNT_MAC_FUNCS(mac);
00076     assert(p_);
00077     /* Transmission completed successfully */
00078     busy_ = 0;
00079     p_= 0;
00080     mac->mhRetx_.free();
00081     mac->mhRetx_.reset();
00082     mac->mhIFS_.schedule(mac->netif_->txtime(int(IEEE_8023_IFS_BITS/8.0)));
00083 }
00084 
00085 void Mac8023HandlerSend::schedule(const Packet *p, double t) {
00086     PRNT_MAC_FUNCS(mac);
00087     Scheduler& s = Scheduler::instance();
00088     assert(!busy_);
00089     s.schedule(this, &intr, t);
00090     busy_ = 1;
00091     p_= p;
00092 }
00093 
00094 void MacHandlerRecv::handle(Event* ) {
00095     /* Reception Successful */
00096     PRNT_MAC_FUNCS(mac);
00097     busy_ = 0;
00098     mac->recv_complete(p_);
00099     p_= 0;
00100 }
00101 
00102 void MacHandlerRecv::schedule(Packet *p, double t) {
00103     PRNT_MAC_FUNCS(mac);
00104     Scheduler& s = Scheduler::instance();
00105     assert(p && !busy_);
00106     s.schedule(this, &intr, t);
00107     busy_ = 1;
00108     p_ = p;
00109 }
00110 
00111 bool MacHandlerRetx::schedule(double delta) {
00112     PRNT_MAC_FUNCS(mac);
00113     Scheduler& s = Scheduler::instance();
00114     assert(p_ && !busy_);
00115     int k, r;
00116     if(try_ < IEEE_8023_ALIMIT) {
00117         k = min(try_, IEEE_8023_BLIMIT);
00118         r = Random::integer(1 << k);
00119         s.schedule(this, &intr, r * mac->netif_->txtime((int)(IEEE_8023_SLOT_BITS/8.0)) + delta);
00120         busy_ = 1;
00121         return true;
00122     }
00123     return false;
00124 }
00125 
00126 void MacHandlerRetx::handle(Event *) {
00127     PRNT_MAC_FUNCS(mac);
00128     assert(p_);
00129     busy_= 0;
00130     ++try_;
00131     mac->transmit(p_);
00132 }
00133 
00134 inline void MacHandlerIFS::schedule(double t) {
00135     PRNT_MAC_FUNCS(mac);
00136     assert(!busy_);
00137     Scheduler &s= Scheduler::instance();
00138     s.schedule(this, &intr, t);
00139     busy_= 1;
00140 }
00141 inline void MacHandlerIFS::handle(Event*) { 
00142     PRNT_MAC_FUNCS(mac);
00143     busy_= 0; 
00144     mac->resume(); 
00145 }
00146 
00147 
00148 Mac802_3::Mac802_3() : trace_(0), 
00149     mhRecv_(this), mhRetx_(this), mhIFS_(this), mhSend_(this) {
00150         // Bind mac trace variable 
00151         bind_bool("trace_",&trace_);
00152 }
00153 
00154 void Mac802_3::sendUp(Packet *p, Handler *) {
00155     PRNT_MAC_FUNCS(this);
00156     /* just received the 1st bit of a packet */
00157     if (state_ != MAC_IDLE && mhIFS_.busy()) {
00158 #define EPS 1.0e-15 /* can be considered controller clock resolution */
00159         if (mhIFS_.expire() - Scheduler::instance().clock() > EPS) {
00160             // This can happen when 3 nodes TX:
00161             // 1 was TX, then IFS, then TX again;
00162             // 2,3 were in RX (from 1), then IFS, then TX, then collision with 1 and IFS
00163             // while 3 in IFS it RX from 2 and vice versa.
00164             // We ignore it and let the ifs timer take care of things.
00165                 Packet::free(p);
00166             return;
00167         } else {
00168             // This means that mhIFS_ is about to expire now. We assume that IFS is over 
00169             // and resume, because we want to give this guy a chance - otherwise the guy 
00170             // who TX before will TX again (fairness); if we have anything to
00171             // TX, this forces a collision.
00172             mhIFS_.cancel();
00173             resume();
00174         }
00175 #undef EPS
00176     } 
00177     if(state_ == MAC_IDLE) {
00178         state_ = MAC_RECV;
00179         assert(!mhRecv_.busy());
00180         /* the last bit will arrive in txtime seconds */
00181         mhRecv_.schedule(p, netif_->txtime(p));
00182     } else {
00183         collision(p); //received packet while sending or receiving
00184     }
00185 }
00186 
00187 void Mac802_3::sendDown(Packet *p, Handler *h) {
00188     PRNT_MAC_FUNCS(this);
00189     assert(initialized());
00190     assert(h);
00191     assert(netif_->txtime(IEEE_8023_MINFRAME) > 
00192            2*netif_->channel()->maxdelay()); /* max prop. delay is limited by specs: 
00193                             about 25us for 10Mbps
00194                             and   2.5us for 100Mbps
00195                          */
00196 
00197     int size= (HDR_CMN(p)->size() += ETHER_HDR_LEN); //XXX also preamble?
00198     hdr_mac *mh= HDR_MAC(p);
00199     mh->padding_= 0;
00200     if (size > IEEE_8023_MAXFRAME) {
00201         static bool warnedMAX= false;
00202         if (!warnedMAX) {
00203             fprintf(stderr, "Mac802_3: frame is too big: %d\n", size);
00204             warnedMAX= true;
00205         }
00206     } else if (size < IEEE_8023_MINFRAME) {
00207         // pad it to fit MINFRAME
00208         mh->padding_= IEEE_8023_MINFRAME - size;
00209         HDR_CMN(p)->size() += mh->padding_;
00210     }
00211     callback_ = h;
00212     mhRetx_.packet(p); //packet's buffered by mhRetx in case of retransmissions
00213 
00214     transmit(p);
00215 }
00216 
00217 
00218 void Mac802_3::transmit(Packet *p) {
00219     PRNT_MAC_FUNCS(this);
00220     assert(callback_);
00221     if(mhSend_.packet()) {
00222         fprintf(stderr, "index: %d\n", index_);
00223         fprintf(stderr, "Retx Timer: %d\n", mhRetx_.busy());
00224         fprintf(stderr, "IFS  Timer: %d\n", mhIFS_.busy());
00225         fprintf(stderr, "Recv Timer: %d\n", mhRecv_.busy());
00226         fprintf(stderr, "Send Timer: %d\n", mhSend_.busy());
00227         exit(1);
00228     }
00229 
00230     /* Perform carrier sense  - if we were sending before, never mind state_ */
00231     if (mhIFS_.busy() || (state_ != MAC_IDLE)) {
00232         /* we'll try again when IDLE. It'll happen either when
00233                    reception completes, or if collision.  Either way,
00234                    we call resume() */
00235         return;
00236     }
00237 
00238     double txtime = netif_->txtime(p);
00239     /* Schedule transmission of the packet's last bit */
00240     mhSend_.schedule(p, txtime);
00241 
00242     // pass the packet to the PHY: need to send a copy, 
00243     // because there may be collision and it may be freed
00244     Packet *newp = p->copy();
00245     HDR_CMN(newp)->direction()= hdr_cmn::DOWN; //down
00246     
00247     downtarget_->recv(newp);
00248 
00249     state_= MAC_SEND;
00250 }
00251 
00252 void Mac802_3::collision(Packet *p) {
00253 
00254     PRNT_MAC_FUNCS(this);
00255 
00256     if (mhIFS_.busy()) mhIFS_.cancel();
00257 
00258     double ifstime= netif_->txtime(int((IEEE_8023_JAMSIZE+IEEE_8023_IFS_BITS)/8.0)); //jam time + ifs
00259     mhIFS_.schedule(ifstime);
00260 
00261     switch(state_) {
00262     case MAC_SEND:
00263       // If mac trace feature is on generate a collision trace for this packet. 
00264             if (trace_)
00265                drop(p);
00266             else
00267                Packet::free(p);
00268         if (mhSend_.busy()) mhSend_.cancel();
00269         if (!mhRetx_.busy()) {
00270             /* schedule retransmissions */
00271             if (!mhRetx_.schedule(ifstime)) {
00272                 p= mhRetx_.packet();
00273                 hdr_cmn *th = hdr_cmn::access(p);
00274                 HDR_CMN(p)->size() -= (ETHER_HDR_LEN + HDR_MAC(p)->padding_);
00275                 fprintf(stderr,"BEB limit exceeded:Dropping packet %d\n",th->uid());
00276                                 fflush(stderr);
00277                 drop(p); // drop if backed off far enough
00278                 mhRetx_.reset();
00279             }
00280         }
00281         break;
00282     case MAC_RECV:
00283             Packet::free(p);
00284         // more than 2 packets collisions possible
00285         if (mhRecv_.busy()) mhRecv_.cancel();
00286         break;
00287     default:
00288         assert("SHOULD NEVER HAPPEN" == 0);
00289     }
00290 }
00291 
00292 void Mac802_3::recv_complete(Packet *p) {
00293     PRNT_MAC_FUNCS(this);
00294     assert(!mhRecv_.busy());
00295     assert(!mhSend_.busy());
00296     hdr_cmn *ch= HDR_CMN(p);
00297     /* Address Filtering */
00298     hdr_mac *mh= HDR_MAC(p);
00299     int dst= mh->macDA();
00300 
00301     if ((dst != BCAST_ADDR) && (dst != index_)) {
00302         Packet::free(p);
00303         goto done;
00304     }
00305     /* Strip off the mac header and padding if any */
00306     ch->size() -= (ETHER_HDR_LEN + mh->padding_);
00307 
00308     /* xxx FEC here */
00309     if( ch->error() ) {
00310                 fprintf(stderr,"\nChecksum error\nDropping packet");
00311                 fflush(stderr);
00312         // drop(p);
00313                 Packet::free(p);
00314         goto done;
00315     }
00316 
00317 
00318     /* we could schedule an event to account for mac-delay */
00319     
00320     if ((p->ref_count() > 0) /* so the channel is using ref-copying */
00321         && (dst == BCAST_ADDR)) {
00322         /* make a real copy only if broadcasting, otherwise
00323          * all nodes except the receiver are going to free
00324          * this packet 
00325          */
00326         uptarget_->recv(p->copy(), (Handler*) 0);
00327         Packet::free(p); // this will decrement ref counter
00328     } else {
00329         uptarget_->recv(p, (Handler*) 0);
00330     }
00331 
00332  done:
00333     mhIFS_.schedule(netif_->txtime(int(IEEE_8023_IFS_BITS/8.0)));// wait for one IFS, then resume
00334 }
00335 
00336 /* we call resume() in these cases:
00337    - successful transmission
00338    - whole packet's received
00339    - collision and backoffLimit's exceeded
00340    - collision while receiving */
00341 void Mac802_3::resume() {
00342     PRNT_MAC_FUNCS(this);
00343     assert(!mhRecv_.busy());
00344     assert(!mhSend_.busy());
00345     assert(!mhIFS_.busy());
00346 
00347     state_= MAC_IDLE;
00348 
00349     if (mhRetx_.packet()) {
00350         if (!mhRetx_.busy()) {
00351             // we're not backing off and not sensing carrier right now: send
00352             transmit(mhRetx_.packet());
00353         }
00354     } else {
00355         if (callback_ && !mhRetx_.busy()) {
00356             //WARNING: calling callback_->handle may change the value of callback_
00357             Handler* h= callback_; 
00358             callback_= 0;
00359             h->handle(0);
00360         }
00361     }
00362 }
00363 

Generated on Tue Mar 6 16:47:47 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6