Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

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 Apr 20 12:14:23 2004 for NS2.26SourcesOriginal by doxygen 1.3.3