mac-multihop.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) 1997 Regents of the University of California.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *  This product includes software developed by the Daedalus Research
00017  *  Group at the University of California Berkeley.
00018  * 4. Neither the name of the University nor of the research group may be used
00019  *    to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  */
00034 
00035 #ifndef lint
00036 static const char rcsid[] =
00037     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/mac/mac-multihop.cc,v 1.14 2000/11/02 22:46:37 johnh Exp $ (UCB)";
00038 #endif
00039 
00040 #include "template.h"
00041 #include "channel.h"
00042 #include "mac-multihop.h"
00043 
00044 /* 
00045  * For debugging.
00046  */
00047 void dump_iphdr(hdr_ip *iph) 
00048 {
00049         printf("\tsrc = %d, ", iph->saddr());
00050         printf("\tdst = %d\n", iph->daddr());
00051 }       
00052 
00053 static class MultihopMacClass : public TclClass {
00054 public:
00055     MultihopMacClass() : TclClass("Mac/Multihop") {}
00056     TclObject* create(int, const char*const*) {
00057         return (new MultihopMac);
00058     }
00059 } class_mac_multihop;
00060 
00061 MultihopMac::MultihopMac() : mode_(MAC_IDLE), peer_(0),
00062     pendingPollEvent_(0), pkt_(0),
00063     ph_(this), pah_(this), pnh_(this), pth_(this), bh_(this)
00064 {
00065     /* Bind a bunch of variables to access from Tcl */
00066     bind_time("tx_rx_", &tx_rx_);
00067     bind_time("rx_tx_", &rx_tx_);
00068     bind_time("rx_rx_", &rx_rx_);
00069     bind_time("backoffBase_", &backoffBase_);
00070     backoffTime_ = backoffBase_;
00071 }
00072 
00073 /*
00074  * Returns 1 iff the specified MAC is in the prescribed state, AND all
00075  * the other MACs are IDLE.
00076  */
00077 int MultihopMac::checkInterfaces(int state) 
00078 {
00079     MultihopMac *p;
00080     
00081     if (!(mode_ & state))
00082         return 0;
00083     else if (macList_ == 0)
00084         return 1;
00085     for (p = (MultihopMac *)macList_; p != this && p != NULL; 
00086          p = (MultihopMac *)(p->macList())) {
00087         if (p->mode() != MAC_IDLE) {
00088             return 0;
00089         }
00090     }
00091     return 1;
00092 }
00093 
00094 /*
00095  * Poll a peer node prior to a send.  There can be at most one POLL 
00096  * outstanding from a node at any point in time.  This is achieved implicitly
00097  * because there can be at most one packet down from LL (thru IFQ) to this MAC.
00098  */
00099 void MultihopMac::poll(Packet *p)
00100 {
00101     Scheduler& s = Scheduler::instance();
00102     MultihopMac *pm = (MultihopMac*) getPeerMac(p);
00103     PollEvent *pe = new PollEvent(pm, this);
00104 
00105     pendingPollEvent_ = new PollEvent(pm, this);
00106     pkt_ = p->copy();   /* local copy for poll retries */
00107     double timeout = max(pm->rx_tx(), tx_rx_) + 4*pollTxtime(MAC_POLLSIZE);
00108     s.schedule(&bh_, pendingPollEvent_, timeout);
00109 
00110     /*  If the other interfaces are idle, then go ahead, else not. */
00111     if (checkInterfaces(MAC_IDLE)) { 
00112         mode_ = MAC_POLLING;
00113         peer_ = pm;
00114         s.schedule(pm->ph(), (Event *)pe, pollTxtime(MAC_POLLSIZE));
00115     }
00116 }
00117 
00118 /*
00119  * Handle a POLL request from a peer node's MAC.
00120  */
00121 void
00122 PollHandler::handle(Event *e)
00123 {
00124     PollEvent *pe = (PollEvent *) e;
00125     Scheduler& s = Scheduler::instance();
00126     MultihopMac* pm = mac_->peer(); /* sensible val only in MAC_RCV mode */
00127     
00128     /*
00129      * Send POLLACK if either IDLE or currently receiving 
00130      * from same mac as the poller.
00131      */
00132     if (mac_->checkInterfaces(MAC_IDLE)) { // all interfaces must be IDLE
00133         mac_->mode(MAC_RCV);
00134         pm = pe->peerMac();
00135         mac_->peer(pm);
00136         PollEvent *pae = new PollEvent(pm, mac_); // POLLACK event
00137         double t = mac_->pollTxtime(MAC_POLLACKSIZE) + 
00138             max(mac_->tx_rx(), pm->rx_tx());
00139         s.schedule(pm->pah(), pae, t);
00140     } else {
00141         // printf("ignoring poll %d\n", mac_->label());
00142         // could send NACKPOLL but don't (at least for now)
00143     }
00144 }
00145 
00146 /*
00147  * Handle a POLLACK from a peer node's MAC.
00148  */
00149 void
00150 PollAckHandler::handle(Event *e)
00151 {
00152     PollEvent *pe = (PollEvent *) e;
00153     Scheduler& s = Scheduler::instance();
00154 
00155     if (mac_->checkInterfaces(MAC_POLLING | MAC_IDLE)) {
00156         mac_->backoffTime(mac_->backoffBase());
00157         mac_->mode(MAC_SND);
00158         mac_->peer(pe->peerMac());
00159         s.cancel(mac_->pendingPE()); /* cancel pending timeout */
00160         free(mac_->pendingPE());  // and free the event
00161         mac_->pendingPE(NULL);
00162         mac_->send(mac_->pkt()); /* send saved packet */
00163     }
00164 }
00165 
00166 void
00167 PollNackHandler::handle(Event *)
00168 {
00169 }
00170 
00171 void
00172 BackoffHandler::handle(Event *)
00173 {
00174     Scheduler& s = Scheduler::instance();
00175     if (mac_->mode() == MAC_POLLING) 
00176         mac_->mode(MAC_IDLE);
00177     double bTime = mac_->backoffTime(2*mac_->backoffTime());
00178     bTime = (1+Random::integer(MAC_TICK)*1./MAC_TICK)*bTime + 
00179         2*mac_->backoffBase();
00180 
00181 //  printf("backing off %d\n", mac_->label());
00182     s.schedule(mac_->pth(), mac_->pendingPE(), bTime);
00183 }
00184 
00185 void 
00186 PollTimeoutHandler::handle(Event *)
00187 {
00188     mac_->poll(mac_->pkt());
00189 }
00190 
00191 
00192 /*
00193  * Actually send the data frame.
00194  */
00195 void MultihopMac::send(Packet *p)
00196 {
00197     Scheduler& s = Scheduler::instance();
00198     if (mode_ != MAC_SND)
00199         return;
00200 
00201     double txt = txtime(p);
00202     hdr_mac::access(p)->txtime() = txt;
00203     channel_->send(p, txt); // target is peer's mac handler
00204     s.schedule(callback_, &intr_, txt); // callback to higher layer (LL)
00205     mode_ = MAC_IDLE;
00206 }
00207 
00208 /*
00209  * This is the call from the higher layer of the protocol stack (i.e., LL)
00210  */
00211 void MultihopMac::recv(Packet* p, Handler *h)
00212 {
00213     if (h == 0) {       /* from MAC classifier (pass pkt to LL) */
00214         mode_ = MAC_IDLE;
00215         Scheduler::instance().schedule(target_, p, delay_);
00216         return;
00217     }
00218     callback_ = h;
00219     hdr_mac* mh = hdr_mac::access(p);
00220     mh->macSA() = addr_;
00221     if (mh->ftype() == MF_ACK) {
00222         mode_ = MAC_SND;
00223         send(p);
00224     } else {
00225         mh->ftype() = MF_DATA;
00226         poll(p);        /* poll first */
00227     }
00228 }

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