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
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include <um.h>
00047 #include <mac.h>
00048 #include <flags.h>
00049 #include <random.h>
00050 #include <address.h>
00051 #include <iostream>
00052
00053
00054 static class UMRlcClass:public TclClass
00055 {
00056 public:
00057 UMRlcClass():TclClass("UMTS/RLC/UM") { }
00058 TclObject *create(int, const char *const *) {
00059 return (new UM());
00060 }
00061 } class_um;
00062
00063
00064
00065 UM::UM():RLC(), temporaryPacket_(this), nextExpectedSDU_(0), nextExpectedSeqno_(0),
00066 nextExpectedSegment_(0), errorInSDU_(0), seqno_(0), send_status_(0),
00067 SDU_size_(0), maxseq_(-1), highest_ack_(0), maxseen_(0), next_(0),
00068 d_address_(0), macDA_(0), tti_timer_(this, RLC_TIMER_TTI)
00069 {
00070 bind("win_", &win_);
00071 bind_time("temp_pdu_timeout_time_", &tempPDUTimeOutTime_);
00072 bind("buffer_level_max_", &bufferLevelMax_);
00073 bind("payload_", &payloadSize_);
00074 bind_time("TTI_", &TTI_);
00075 bind("TTI_PDUs_", &TTI_PDUs_);
00076 bind("length_indicator_", &length_indicator_);
00077 bind("min_concat_data_", &min_concat_data_);
00078 bind("bandwidth_", &bandwidth_);
00079 bind("macDA_", &macDA_);
00080
00081
00082
00083
00084
00085
00086 lengthIndicatorSize_ = ((length_indicator_ + 1) / 8);
00087 temporaryPacket_.p = NULL;
00088
00089 tti_timer_.sched(TTI_ - 0.001);
00090
00091 }
00092
00093
00094 int UM::command(int argc, const char *const *argv)
00095 {
00096 if (argc == 2) {
00097 Tcl & tcl = Tcl::instance();
00098 if (strcmp(argv[1], "TTI") == 0) {
00099 tcl.resultf("%f", TTI_);
00100 return TCL_OK;
00101 } else if (strcmp(argv[1], "BW") == 0) {
00102 tcl.resultf("%f", bandwidth_);
00103 return TCL_OK;
00104 }
00105
00106
00107
00108
00109 } else if (argc == 3) {
00110 if (strcmp(argv[1], "macDA") == 0) {
00111 int nodeID = Address::instance().str2addr(argv[2]);
00112
00113 macDA_ = nodeID;
00114 return (TCL_OK);
00115 } else if (strcmp(argv[1], "addr") == 0) {
00116 address_ = Address::instance().str2addr(argv[2]);
00117 return (TCL_OK);
00118 } else if (strcmp(argv[1], "daddr") == 0) {
00119 int nodeID = Address::instance().str2addr(argv[2]);
00120
00121 d_address_ = nodeID;
00122 return (TCL_OK);
00123 }
00124 }
00125 int returnvalue = LL::command(argc, argv);
00126
00127
00128 return returnvalue;
00129 }
00130
00131 void UM::recv(Packet * p, Handler * h)
00132 {
00133 if (debug_)
00134 std::cerr << "entering UM::recv()" << std::endl;
00135
00136 hdr_cmn *ch = HDR_CMN(p);
00137
00138
00139
00140 if (ch->direction() == hdr_cmn::UP) {
00141 hdr_rlc *llh = hdr_rlc::access(p);
00142
00143 if (debug_)
00144 std::cerr << NOW << " UM::recv() packet going UP" << std::endl;
00145
00146 if (llh->dst() != address_ || ch->error() > 0) {
00147
00148
00149 if (debug_)
00150 std::cerr << NOW << " UM::recv() dropping packet"
00151 << " llh->dst()=" << llh->dst()
00152 << " address_=" << address_
00153 << " ch->error()=" << ch->error()
00154 << std::endl;
00155 Packet::free(p);
00156 return;
00157 }
00158
00159 if (llh->lltype() == RLC_DATA) {
00160
00161
00162
00163 hdr_tcp *tcph = hdr_tcp::access(p);
00164 hdr_rlc *llh = hdr_rlc::access(p);
00165 int temp_sdu = tcph->seqno();
00166 int temp_seqno = llh->seqno();
00167 int temp_segment = llh->segment();
00168
00169
00170 if (temp_seqno == llh->eopno()) {
00171
00172
00173
00174
00175 if (nextExpectedSeqno_ == temp_seqno && nextExpectedSDU_ == temp_sdu
00176 && errorInSDU_ == 0) {
00177 makeSDU(p);
00178 } else {
00179 Packet::free(p);
00180 }
00181 errorInSDU_ = 0;
00182 nextExpectedSDU_ = temp_sdu + 1;
00183 nextExpectedSeqno_ = temp_seqno + 1;
00184 } else {
00185
00186
00187
00188
00189
00190
00191 if (nextExpectedSeqno_ == temp_seqno) {
00192 nextExpectedSeqno_++;
00193 } else {
00194 nextExpectedSDU_ = temp_sdu;
00195 nextExpectedSeqno_ = temp_seqno + 1;
00196 if (temp_segment != 0) {
00197 errorInSDU_++;
00198 }
00199 }
00200 Packet::free(p);
00201 }
00202
00203 } else {
00204 if (debug_)
00205 std::cerr << "UM::recv() dropping packet"
00206 << " llh->type=" << llh->lltype()
00207 << " ch->error()=" << ch->error()
00208 << std::endl;
00209
00210
00211
00212 drop(p);
00213 }
00214 return;
00215 } else {
00216
00217
00218
00219 assert(ch->direction() == hdr_cmn::DOWN);
00220 sendDown(p);
00221 }
00222
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232 int UM::enquePacket(Packet * p)
00233 {
00234
00235 int r_value = 0;
00236
00237
00238 r_value = enqueInBackOfTransmissionBuffer(p);
00239
00240
00241 return r_value;
00242 }
00243
00244 int UM::enqueInBackOfTransmissionBuffer(Packet * p)
00245 {
00246
00247
00248 int r_value = 0;
00249
00250
00251 if (transmissionBuffer_.length() >= bufferLevelMax_) {
00252 drop(p);
00253 } else {
00254 transmissionBuffer_.enque(p);
00255 r_value = 1;
00256 }
00257
00258
00259 return r_value;
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269 void UM::sendDown(Packet * p)
00270 {
00271
00272
00273
00274 int numPDUs =
00275 (int) ceil((double) hdr_cmn::access(p)->size() /
00276 (double) payloadSize_);
00277
00278 if (numPDUs + transmissionBuffer_.length() >= bufferLevelMax_) {
00279 Packet::free(p);
00280 return;
00281 }
00282
00283 int segment = 0;
00284
00285
00286
00287 handleTemporaryPacket(p);
00288
00289 if (hdr_rlc::access(p)->segment() == 0) {
00290
00291
00292 segment++;
00293 }
00294
00295 while (p != NULL) {
00296
00297
00298
00299
00300
00301 int concat_data = 0;
00302 bool close_PDU = false;
00303 int padding = 0;
00304 bool force_length_indicator = false;
00305 Packet *c;
00306
00307 int p_size = hdr_cmn::access(p)->size();
00308
00309 close_PDU = p_size <= payloadSize_;
00310 force_length_indicator = p_size < payloadSize_;
00311
00312 if (p_size <= (payloadSize_ - lengthIndicatorSize_)) {
00313
00314
00315 concat_data = payloadSize_ - p_size - 2 * lengthIndicatorSize_;
00316 if (concat_data < min_concat_data_) {
00317 concat_data = 0;
00318 padding = payloadSize_ - p_size - lengthIndicatorSize_;
00319 } else {
00320 padding = 0;
00321 }
00322 }
00323
00324 if (close_PDU) {
00325
00326 c = p;
00327 p = NULL;
00328 } else {
00329
00330 concat_data = 0;
00331 padding = 0;
00332 c = p->copy();
00333 }
00334
00335
00336
00337 hdr_cmn *c_ch = HDR_CMN(c);
00338 hdr_rlc *c_llh = hdr_rlc::access(c);
00339 hdr_cmn *p_ch = NULL;
00340 hdr_ip *p_iph = NULL;
00341
00342 if (p != NULL) {
00343 p_ch = HDR_CMN(p);
00344 p_iph = hdr_ip::access(p);
00345 }
00346
00347 c_llh->lptype() = c_ch->ptype();
00348 c_llh->lerror_ = c_ch->error();
00349 c_llh->lts_ = c_ch->timestamp();
00350 c_llh->segment() = segment;
00351 segment++;
00352
00353 if (close_PDU) {
00354
00355 if (SDU_size_ > 0) {
00356 c_llh->lsize_ = SDU_size_;
00357 } else {
00358 c_llh->lsize_ = c_ch->size();
00359 }
00360
00361 SDU_size_ = -1;
00362
00363 } else if (SDU_size_ < 0) {
00364 assert(p != NULL);
00365 SDU_size_ = hdr_cmn::access(p)->size();
00366 }
00367
00368 c_llh->lltype() = RLC_DATA;
00369 c_llh->seqno() = seqno_;
00370 seqno_++;
00371 c_llh->dst() = d_address_;
00372 c_llh->src() = address_;
00373 c_llh->lengthInd_ = 0;
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 if (close_PDU) {
00389 c_llh->eopno_ = c_llh->seqno();
00390 } else {
00391 c_llh->eopno_ = EOPNO_NOT_EOP;
00392 }
00393 if (concat_data || padding || force_length_indicator) {
00394 c_llh->lengthInd_++;
00395 }
00396
00397 if (close_PDU) {
00398 c_llh->payload_[PAYLOAD_FLD1] = c_ch->size();
00399 } else {
00400 if (force_length_indicator) {
00401 c_llh->payload_[PAYLOAD_FLD1] = payloadSize_ - lengthIndicatorSize_;
00402 } else {
00403 c_llh->payload_[PAYLOAD_FLD1] = payloadSize_;
00404 }
00405 }
00406 c_llh->payload_[PAYLOAD_FLD2] = 0;
00407 c_llh->payload_[PAYLOAD_FLD3] = 0;
00408
00409 c_llh->padding_ = padding;
00410
00411
00412 char *mh = (char *) c->access(hdr_mac::offset_);
00413 struct hdr_mac *c_dh = (struct hdr_mac *) mh;
00414
00415 c_ch->ptype() = PT_UM;
00416 c_dh->macDA_ = macDA_;
00417 c_dh->macSA_ = -1;
00418 c_dh->hdr_type() = ETHERTYPE_RLC;
00419 c_ch->timestamp() = Scheduler::instance().clock();
00420 c_ch->direction() = hdr_cmn::DOWN;
00421
00422
00423 if (close_PDU) {
00424 if (concat_data) {
00425
00426
00427
00428 c_llh->lengthInd_++;
00429
00430 StoreTemporaryPacket(c, concat_data);
00431 break;
00432 }
00433 } else {
00434
00435
00436 p_ch->size() = p_ch->size() - c_llh->payload_[PAYLOAD_FLD1];
00437 }
00438
00439 assert(c_ch->error() == 0);
00440
00441 c_ch->size() = payloadSize_;
00442
00443
00444
00445 if (enquePacket(c) == 0) {
00446 } else {
00447 }
00448
00449 }
00450
00451
00452 }
00453
00454
00455
00456
00457 void UM::StoreTemporaryPacket(Packet * p, int concat_data)
00458 {
00459
00460 temporaryPacket_.p = p;
00461 temporaryPacket_.concat_data = concat_data;
00462
00463
00464
00465
00466 temporaryPacket_.tempPDUTimer.sched(tempPDUTimeOutTime_);
00467 }
00468
00469
00470 void UM::handleTemporaryPacket(Packet * p)
00471 {
00472
00473
00474 if (p == NULL) {
00475 return;
00476 }
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 if (temporaryPacket_.p != NULL) {
00487
00488 if (hdr_cmn::access(p)->size() > payloadSize_) {
00489
00490
00491
00492 hdr_rlc::access(temporaryPacket_.p)->payload_[1] =
00493 temporaryPacket_.concat_data;
00494
00495 SDU_size_ = hdr_cmn::access(p)->size();
00496 hdr_cmn::access(p)->size() =
00497 hdr_cmn::access(p)->size() - temporaryPacket_.concat_data;
00498
00499
00500
00501 hdr_rlc::access(p)->segment() = 0;
00502
00503 } else {
00504
00505 hdr_rlc::access(temporaryPacket_.p)->lengthInd_--;
00506 hdr_rlc::access(temporaryPacket_.p)->padding_ =
00507 temporaryPacket_.concat_data + lengthIndicatorSize_;
00508 }
00509 enquePacket(temporaryPacket_.p);
00510
00511
00512
00513 temporaryPacket_.tempPDUTimer.cancel();
00514 temporaryPacket_.p = NULL;
00515 }
00516 }
00517
00518
00519 void UM::timeout(int tno, int flowID)
00520 {
00521 vector < int >temp_vect;
00522 double TTI_time_;
00523
00524 switch (tno) {
00525 case RLC_TIMER_TEMP_PDU:
00526
00527
00528
00529
00530
00531
00532
00533 hdr_rlc::access(temporaryPacket_.p)->lengthInd_--;
00534 hdr_rlc::access(temporaryPacket_.p)->padding_ =
00535 temporaryPacket_.concat_data + lengthIndicatorSize_;
00536 enquePacket(temporaryPacket_.p);
00537
00538 break;
00539 case RLC_TIMER_TTI:
00540 TTI_time_ = Scheduler::instance().clock();
00541
00542
00543
00544
00545 tti_timer_.resched(TTI_);
00546 for (int i = 0; i < TTI_PDUs_; i++) {
00547
00548 Packet *p = transmissionBuffer_.deque();
00549
00550 if (p != NULL) {
00551 hdr_cmn *ch = HDR_CMN(p);
00552 hdr_rlc *llh = hdr_rlc::access(p);
00553 if (debug_)
00554 {
00555
00556 std::cerr << "UM::timeout() sending packet"
00557 << " seqno=" << llh->seqno()
00558 << " eopno=" << llh->eopno()
00559 << std::endl;
00560
00561 }
00562
00563 ch->direction() = hdr_cmn::DOWN;
00564 downtarget_->recv(p);
00565 }
00566 }
00567 break;
00568 default:
00569 break;
00570 }
00571
00572 }
00573
00574 void UM::completePDU(Packet * p)
00575 {
00576
00577
00578 hdr_rlc *llh = hdr_rlc::access(p);
00579
00580
00581
00582 if (llh->seqno() == -1) {
00583 llh->seqno() = seqno_;
00584 seqno_++;
00585 if (llh->eopno() == EOPNO_TO_SEQNO) {
00586 llh->eopno() = llh->seqno();
00587 }
00588 }
00589 return;
00590 }
00591
00592 void UM::makeSDU(Packet * p)
00593 {
00594 hdr_cmn *ch;
00595 hdr_rlc *llh;
00596
00597 assert(p);
00598 ch = HDR_CMN(p);
00599 llh = hdr_rlc::access(p);
00600
00601 ch->ptype() = llh->lptype();
00602 ch->error() = llh->lerror();
00603 ch->timestamp() = llh->lts();
00604 ch->size() = llh->lsize();
00605
00606 assert(ch->direction() == hdr_cmn::UP);
00607
00608 uptarget_ ? sendUp(p) : Packet::free(p);
00609 }
00610
00611 int UM::buff_size()
00612 {
00613 return(transmissionBuffer_.size());
00614 }
00615
00616 void UM::CSwitch(double bandwidth, double TTI)
00617 {
00618 bandwidth_ = bandwidth;
00619 TTI_ = TTI;
00620 }
00621