00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
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
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
00075
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
00096
00097
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();
00107 double timeout = max(pm->rx_tx(), tx_rx_) + 4*pollTxtime(MAC_POLLSIZE);
00108 s.schedule(&bh_, pendingPollEvent_, timeout);
00109
00110
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
00120
00121 void
00122 PollHandler::handle(Event *e)
00123 {
00124 PollEvent *pe = (PollEvent *) e;
00125 Scheduler& s = Scheduler::instance();
00126 MultihopMac* pm = mac_->peer();
00127
00128
00129
00130
00131
00132 if (mac_->checkInterfaces(MAC_IDLE)) {
00133 mac_->mode(MAC_RCV);
00134 pm = pe->peerMac();
00135 mac_->peer(pm);
00136 PollEvent *pae = new PollEvent(pm, mac_);
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
00142
00143 }
00144 }
00145
00146
00147
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());
00160 free(mac_->pendingPE());
00161 mac_->pendingPE(NULL);
00162 mac_->send(mac_->pkt());
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
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
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);
00204 s.schedule(callback_, &intr_, txt);
00205 mode_ = MAC_IDLE;
00206 }
00207
00208
00209
00210
00211 void MultihopMac::recv(Packet* p, Handler *h)
00212 {
00213 if (h == 0) {
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);
00227 }
00228 }