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
00036
00037 #ifndef lint
00038 static const char rcsid[] =
00039 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/mac/mac-csma.cc,v 1.26 1998/11/17 23:36:35 yuriy Exp $ (UCB)";
00040 #endif
00041
00042 #include "template.h"
00043 #include "random.h"
00044 #include "channel.h"
00045 #include "mac-csma.h"
00046
00047 static class MacCsmaClass : public TclClass {
00048 public:
00049 MacCsmaClass() : TclClass("Mac/Csma") {}
00050 TclObject* create(int, const char*const*) {
00051 return (new MacCsma);
00052 }
00053 } class_mac_csma;
00054
00055 static class MacCsmaCdClass : public TclClass {
00056 public:
00057 MacCsmaCdClass() : TclClass("Mac/Csma/Cd") {}
00058 TclObject* create(int, const char*const*) {
00059 return (new MacCsmaCd);
00060 }
00061 } class_mac_csma_cd;
00062
00063 static class MacCsmaCaClass : public TclClass {
00064 public:
00065 MacCsmaCaClass() : TclClass("Mac/Csma/Ca") {}
00066 TclObject* create(int, const char*const*) {
00067 return (new MacCsmaCa);
00068 }
00069 } class_mac_csma_ca;
00070
00071
00072 void
00073 MacHandlerEoc::handle(Event* e)
00074 {
00075 mac_->endofContention((Packet*)e);
00076 }
00077
00078
00079 MacCsma::MacCsma() : txstart_(0), rtx_(0), csense_(1), hEoc_(this)
00080 {
00081 bind_time("ifs_", &ifs_);
00082 bind_time("slotTime_", &slotTime_);
00083 bind("cwmin_", &cwmin_);
00084 bind("cwmax_", &cwmax_);
00085 bind("rtxLimit_", &rtxLimit_);
00086 bind("csense_", &csense_);
00087 cw_ = cwmin_;
00088 }
00089
00090
00091 void MacCsma::resume(Packet* p)
00092 {
00093 Scheduler& s = Scheduler::instance();
00094 s.schedule(callback_, &intr_, ifs_ + slotTime_ * cwmin_);
00095 if (p != 0)
00096 drop(p);
00097 callback_ = 0;
00098 state(MAC_IDLE);
00099 rtx_ = 0;
00100 cw_ = cwmin_;
00101 }
00102
00103
00104 void MacCsma::send(Packet* p)
00105 {
00106 Scheduler& s = Scheduler::instance();
00107 double delay = channel_->txstop() + ifs_ - s.clock();
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 static const double EPS= 1.0e-12;
00131 if (csense_ && delay > EPS)
00132 s.schedule(&hSend_, p, delay + 0.000001);
00133 else {
00134 txstart_ = s.clock();
00135 channel_->contention(p, &hEoc_);
00136 }
00137 }
00138
00139
00140 void MacCsma::backoff(Handler* h, Packet* p, double delay)
00141 {
00142 Scheduler& s = Scheduler::instance();
00143 double now = s.clock();
00144
00145
00146
00147 if (++rtx_ < rtxLimit_) {
00148 delay += max(channel_->txstop() + ifs_ - now, 0.0);
00149 int slot = Random::integer(cw_);
00150 s.schedule(h, p, delay + slotTime_ * slot);
00151 cw_ = min(2 * cw_, cwmax_);
00152 }
00153 else
00154 resume(p);
00155 }
00156
00157
00158 void MacCsma::endofContention(Packet* p)
00159 {
00160 Scheduler& s = Scheduler::instance();
00161 double txt = txtime(p) - (s.clock() - txstart_);
00162 hdr_mac::access(p)->txtime() = txt;
00163 channel_->send(p, txt);
00164 s.schedule(&hRes_, &eEoc_, txt);
00165 rtx_ = 0;
00166 cw_ = cwmin_;
00167 }
00168
00169
00170 void MacCsmaCd::endofContention(Packet* p)
00171 {
00172
00173 if (channel_->collision()) {
00174 channel_->jam(0);
00175 backoff(&hSend_, p);
00176 }
00177 else
00178 MacCsma::endofContention(p);
00179 }
00180
00181
00182 void MacCsmaCa::send(Packet* p)
00183 {
00184 Scheduler& s = Scheduler::instance();
00185 double delay = channel_->txstop() + ifs_ - s.clock();
00186
00187 if (csense_ && delay > 0)
00188 backoff(&hSend_, p);
00189 else {
00190 txstart_ = s.clock();
00191 channel_->contention(p, &hEoc_);
00192 }
00193 }