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

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