mac-simple.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * mac-simple.cc
00004  * Copyright (C) 2003 by the University of Southern California
00005  * $Id: mac-simple.cc,v 1.7 2005/09/21 20:52:46 haldar Exp $
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00019  *
00020  *
00021  * The copyright of this module includes the following
00022  * linking-with-specific-other-licenses addition:
00023  *
00024  * In addition, as a special exception, the copyright holders of
00025  * this module give you permission to combine (via static or
00026  * dynamic linking) this module with free software programs or
00027  * libraries that are released under the GNU LGPL and with code
00028  * included in the standard release of ns-2 under the Apache 2.0
00029  * license or under otherwise-compatible licenses with advertising
00030  * requirements (or modified versions of such code, with unchanged
00031  * license).  You may copy and distribute such a system following the
00032  * terms of the GNU GPL for this module and the licenses of the
00033  * other code concerned, provided that you include the source code of
00034  * that other code when and as the GNU GPL requires distribution of
00035  * source code.
00036  *
00037  * Note that people who make modified versions of this module
00038  * are not obligated to grant this special exception for their
00039  * modified versions; it is their choice whether to do so.  The GNU
00040  * General Public License gives permission to release a modified
00041  * version without this exception; this exception also makes it
00042  * possible to release a modified version which carries forward this
00043  * exception.
00044  *
00045  */
00046 
00047 #include "ll.h"
00048 #include "mac.h"
00049 #include "mac-simple.h"
00050 #include "random.h"
00051 
00052 // Added by Sushmita to support event tracing (singal@nunki.usc.edu)
00053 #include "agent.h"
00054 #include "basetrace.h"
00055 
00056 #include "cmu-trace.h"
00057 
00058 static class MacSimpleClass : public TclClass {
00059 public:
00060     MacSimpleClass() : TclClass("Mac/Simple") {}
00061     TclObject* create(int, const char*const*) {
00062         return new MacSimple();
00063     }
00064 } class_macsimple;
00065 
00066 
00067 // Added by Sushmita to support event tracing (singal@nunki.usc.edu).
00068 void MacSimple::trace_event(char *eventtype, Packet *p)
00069 {
00070     if (et_ == NULL) return;
00071     char *wrk = et_->buffer();
00072     char *nwrk = et_->nbuffer();
00073 
00074     hdr_ip *iph = hdr_ip::access(p);
00075     char *src_nodeaddr =
00076         Address::instance().print_nodeaddr(iph->saddr());
00077     char *dst_nodeaddr =
00078         Address::instance().print_nodeaddr(iph->daddr());
00079 
00080     if (wrk != 0) 
00081     {
00082         sprintf(wrk, "E -t "TIME_FORMAT" %s %s %s",
00083             et_->round(Scheduler::instance().clock()),
00084             eventtype,
00085             src_nodeaddr,
00086             dst_nodeaddr);
00087     }
00088     if (nwrk != 0)
00089     {
00090         sprintf(nwrk, "E -t "TIME_FORMAT" %s %s %s",
00091         et_->round(Scheduler::instance().clock()),
00092         eventtype,
00093         src_nodeaddr,
00094         dst_nodeaddr);
00095     }
00096     et_->dump();
00097 }
00098 
00099 MacSimple::MacSimple() : Mac() {
00100     rx_state_ = tx_state_ = MAC_IDLE;
00101     tx_active_ = 0;
00102     waitTimer = new MacSimpleWaitTimer(this);
00103     sendTimer = new MacSimpleSendTimer(this);
00104     recvTimer = new MacSimpleRecvTimer(this);
00105     // Added by Sushmita to support event tracing (singal@nunki.usc.edu)
00106     et_ = new EventTrace();
00107     busy_ = 0;
00108     bind("fullduplex_mode_", &fullduplex_mode_);
00109 }
00110 
00111 // Added by Sushmita to support event tracing (singal@nunki.usc.edu)
00112 int 
00113 MacSimple::command(int argc, const char*const* argv)
00114 {
00115     if (argc == 3) {
00116         if(strcmp(argv[1], "eventtrace") == 0) {
00117             et_ = (EventTrace *)TclObject::lookup(argv[2]);
00118             return (TCL_OK);
00119         }
00120     }
00121     return Mac::command(argc, argv);
00122 }
00123 
00124 void MacSimple::recv(Packet *p, Handler *h) {
00125 
00126     struct hdr_cmn *hdr = HDR_CMN(p);
00127     /* let MacSimple::send handle the outgoing packets */
00128     if (hdr->direction() == hdr_cmn::DOWN) {
00129         send(p,h);
00130         return;
00131     }
00132 
00133     /* handle an incoming packet */
00134 
00135     /*
00136      * If we are transmitting, then set the error bit in the packet
00137      * so that it will be thrown away
00138      */
00139     
00140     // in full duplex mode it can recv and send at the same time
00141     if (!fullduplex_mode_ && tx_active_)
00142     {
00143         hdr->error() = 1;
00144 
00145     }
00146 
00147     /*
00148      * check to see if we're already receiving a different packet
00149      */
00150     
00151     if (rx_state_ == MAC_IDLE) {
00152         /*
00153          * We aren't already receiving any packets, so go ahead
00154          * and try to receive this one.
00155          */
00156         rx_state_ = MAC_RECV;
00157         pktRx_ = p;
00158         /* schedule reception of the packet */
00159         recvTimer->start(txtime(p));
00160     } else {
00161         /*
00162          * We are receiving a different packet, so decide whether
00163          * the new packet's power is high enough to notice it.
00164          */
00165         if (pktRx_->txinfo_.RxPr / p->txinfo_.RxPr
00166             >= p->txinfo_.CPThresh) {
00167             /* power too low, ignore the packet */
00168             Packet::free(p);
00169         } else {
00170             /* power is high enough to result in collision */
00171             rx_state_ = MAC_COLL;
00172 
00173             /*
00174              * look at the length of each packet and update the
00175              * timer if necessary
00176              */
00177 
00178             if (txtime(p) > recvTimer->expire()) {
00179                 recvTimer->stop();
00180                 Packet::free(pktRx_);
00181                 pktRx_ = p;
00182                 recvTimer->start(txtime(pktRx_));
00183             } else {
00184                 Packet::free(p);
00185             }
00186         }
00187     }
00188 }
00189 
00190 
00191 double
00192 MacSimple::txtime(Packet *p)
00193  {
00194      struct hdr_cmn *ch = HDR_CMN(p);
00195      double t = ch->txtime();
00196      if (t < 0.0)
00197         t = 0.0;
00198      return t;
00199  }
00200 
00201 
00202 
00203 void MacSimple::send(Packet *p, Handler *h)
00204 {
00205     hdr_cmn* ch = HDR_CMN(p);
00206 
00207     /* store data tx time */
00208     ch->txtime() = Mac::txtime(ch->size());
00209 
00210     // Added by Sushmita to support event tracing (singal@nunki.usc.edu)
00211     trace_event("SENSING_CARRIER",p);
00212 
00213     /* check whether we're idle */
00214     if (tx_state_ != MAC_IDLE) {
00215         // already transmitting another packet .. drop this one
00216         // Note that this normally won't happen due to the queue
00217         // between the LL and the MAC .. the queue won't send us
00218         // another packet until we call its handler in sendHandler()
00219 
00220         Packet::free(p);
00221         return;
00222     }
00223 
00224     pktTx_ = p;
00225     txHandler_ = h;
00226     // rather than sending packets out immediately, add in some
00227     // jitter to reduce chance of unnecessary collisions
00228     double jitter = Random::random()%40 * 100/bandwidth_;
00229 
00230     if(rx_state_ != MAC_IDLE) {
00231         trace_event("BACKING_OFF",p);
00232     }
00233 
00234     if (rx_state_ == MAC_IDLE ) {
00235         // we're idle, so start sending now
00236         waitTimer->restart(jitter);
00237         sendTimer->restart(jitter + ch->txtime());
00238     } else {
00239         // we're currently receiving, so schedule it after
00240         // we finish receiving
00241         waitTimer->restart(jitter);
00242         sendTimer->restart(jitter + ch->txtime()
00243                  + HDR_CMN(pktRx_)->txtime());
00244     }
00245 }
00246 
00247 
00248 void MacSimple::recvHandler()
00249 {
00250     hdr_cmn *ch = HDR_CMN(pktRx_);
00251     Packet* p = pktRx_;
00252     MacState state = rx_state_;
00253     pktRx_ = 0;
00254     int dst = hdr_dst((char*)HDR_MAC(p));
00255     
00256     //busy_ = 0;
00257 
00258     rx_state_ = MAC_IDLE;
00259 
00260     // in full duplex mode we can send and recv at the same time
00261     // as different chanels are used for tx and rx'ing
00262     if (!fullduplex_mode_ && tx_active_) {
00263         // we are currently sending, so discard packet
00264         Packet::free(p);
00265     } else if (state == MAC_COLL) {
00266         // recv collision, so discard the packet
00267         drop(p, DROP_MAC_COLLISION);
00268         //Packet::free(p);
00269     } else if (dst != index_ && (u_int32_t)dst != MAC_BROADCAST) {
00270         
00271         /*  address filtering
00272          *  We don't want to log this event, so we just free
00273          *  the packet instead of calling the drop routine.
00274          */
00275         Packet::free(p);
00276     } else if (ch->error()) {
00277         // packet has errors, so discard it
00278         //Packet::free(p);
00279         drop(p, DROP_MAC_PACKET_ERROR);
00280     
00281     } else {
00282         uptarget_->recv(p, (Handler*) 0);
00283     }
00284 }
00285 
00286 void MacSimple::waitHandler()
00287 {
00288     tx_state_ = MAC_SEND;
00289     tx_active_ = 1;
00290 
00291     downtarget_->recv(pktTx_, txHandler_);
00292 }
00293 
00294 void MacSimple::sendHandler()
00295 {
00296     Handler *h = txHandler_;
00297     Packet *p = pktTx_;
00298 
00299     pktTx_ = 0;
00300     txHandler_ = 0;
00301     tx_state_ = MAC_IDLE;
00302     tx_active_ = 0;
00303 
00304     //busy_ = 1;
00305     //busy_ = 0;
00306     
00307     
00308     // I have to let the guy above me know I'm done with the packet
00309     h->handle(p);
00310 }
00311 
00312 
00313 
00314 
00315 //  Timers
00316 
00317 void MacSimpleTimer::restart(double time)
00318 {
00319     if (busy_)
00320         stop();
00321     start(time);
00322 }
00323 
00324     
00325 
00326 void MacSimpleTimer::start(double time)
00327 {
00328     Scheduler &s = Scheduler::instance();
00329 
00330     assert(busy_ == 0);
00331     
00332     busy_ = 1;
00333     stime = s.clock();
00334     rtime = time;
00335     assert(rtime >= 0.0);
00336 
00337     s.schedule(this, &intr, rtime);
00338 }
00339 
00340 void MacSimpleTimer::stop(void)
00341 {
00342     Scheduler &s = Scheduler::instance();
00343 
00344     assert(busy_);
00345     s.cancel(&intr);
00346     
00347     busy_ = 0;
00348     stime = rtime = 0.0;
00349 }
00350 
00351 
00352 void MacSimpleWaitTimer::handle(Event *e)
00353 {
00354     busy_ = 0;
00355     stime = rtime = 0.0;
00356 
00357     mac->waitHandler();
00358 }
00359 
00360 void MacSimpleSendTimer::handle(Event *e)
00361 {
00362     busy_ = 0;
00363     stime = rtime = 0.0;
00364 
00365     mac->sendHandler();
00366 }
00367 
00368 void MacSimpleRecvTimer::handle(Event *e)
00369 {
00370     busy_ = 0;
00371     stime = rtime = 0.0;
00372 
00373     mac->recvHandler();
00374 }
00375 
00376 

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