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/satellite/satlink.cc,v 1.11 2002/03/21 01:41:06 johnh Exp $";
00040 #endif
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #include "satlink.h"
00052 #include "sattrace.h"
00053 #include "satposition.h"
00054 #include "satgeometry.h"
00055 #include "satnode.h"
00056 #include "satroute.h"
00057 #include "errmodel.h"
00058
00059
00060
00061
00062
00063
00064 static class SatLinkHeadClass : public TclClass {
00065 public:
00066 SatLinkHeadClass() : TclClass("Connector/LinkHead/Sat") {}
00067 TclObject* create(int, const char*const*) {
00068 return (new SatLinkHead);
00069 }
00070 } class_sat_link_head;
00071
00072 SatLinkHead::SatLinkHead() : linkup_(1), phy_tx_(0), phy_rx_(0), mac_(0), satll_(0), queue_(0), errmodel_(0)
00073 {
00074 }
00075
00076 int SatLinkHead::command(int argc, const char*const* argv)
00077 {
00078 if (argc == 2) {
00079 } else if (argc == 3) {
00080 if (strcmp(argv[1], "set_type") == 0) {
00081 if (strcmp(argv[2], "geo") == 0) {
00082 type_ = LINK_GSL_GEO;
00083 return TCL_OK;
00084 } else if (strcmp(argv[2], "polar") == 0) {
00085 type_ = LINK_GSL_POLAR;
00086 return TCL_OK;
00087 } else if (strcmp(argv[2], "gsl") == 0) {
00088 type_ = LINK_GSL;
00089 return TCL_OK;
00090 } else if (strcmp(argv[2], "gsl-repeater") == 0) {
00091 type_ = LINK_GSL_REPEATER;
00092 return TCL_OK;
00093 } else if (strcmp(argv[2], "interplane") == 0) {
00094 type_ = LINK_ISL_INTERPLANE;
00095 return TCL_OK;
00096 } else if (strcmp(argv[2], "intraplane") == 0) {
00097 type_ = LINK_ISL_INTRAPLANE;
00098 return TCL_OK;
00099 } else if (strcmp(argv[2], "crossseam") == 0) {
00100 type_ = LINK_ISL_CROSSSEAM;
00101 return TCL_OK;
00102 } else {
00103 printf("Unknown link type: %s\n", argv[2]);
00104 exit(1);
00105 }
00106 }
00107 if (strcmp(argv[1], "setll") == 0) {
00108 satll_ = (SatLL*) TclObject::lookup(argv[2]);
00109 if (satll_ == 0)
00110 return TCL_ERROR;
00111 return TCL_OK;
00112 } else if(strcmp(argv[1], "setphytx") == 0) {
00113 phy_tx_ = (SatPhy*) TclObject::lookup(argv[2]);
00114 if (phy_tx_ == 0)
00115 return TCL_ERROR;
00116 return TCL_OK;
00117 } else if(strcmp(argv[1], "setphyrx") == 0) {
00118 phy_rx_ = (SatPhy*) TclObject::lookup(argv[2]);
00119 if (phy_rx_ == 0)
00120 return TCL_ERROR;
00121 return TCL_OK;
00122 } else if(strcmp(argv[1], "setmac") == 0) {
00123 mac_ = (SatMac*) TclObject::lookup(argv[2]);
00124 if (mac_ == 0)
00125 return TCL_ERROR;
00126 return TCL_OK;
00127 } else if(strcmp(argv[1], "setqueue") == 0) {
00128 queue_ = (Queue*) TclObject::lookup(argv[2]);
00129 if (queue_ == 0)
00130 return TCL_ERROR;
00131 return TCL_OK;
00132 } else if(strcmp(argv[1], "seterrmodel") == 0) {
00133 errmodel_ = (ErrorModel*) TclObject::lookup(argv[2]);
00134 if (errmodel_ == 0)
00135 return TCL_ERROR;
00136 return TCL_OK;
00137 }
00138 }
00139 return (LinkHead::command(argc, argv));
00140 }
00141
00142
00143
00144
00145
00146
00147 static class SatLLClass : public TclClass {
00148 public:
00149 SatLLClass() : TclClass("LL/Sat") {}
00150 TclObject* create(int, const char*const*) {
00151 return (new SatLL);
00152 }
00153 } sat_class_ll;
00154
00155
00156 void SatLL::recv(Packet* p, Handler* )
00157 {
00158 hdr_cmn *ch = HDR_CMN(p);
00159
00160
00161
00162
00163 assert(initialized());
00164
00165
00166
00167 if(ch->direction() == hdr_cmn::UP) {
00168 uptarget_ ? sendUp(p) : drop(p);
00169 return;
00170 }
00171
00172 ch->direction() = hdr_cmn::DOWN;
00173 sendDown(p);
00174 }
00175 int SatLL::command(int argc, const char*const* argv)
00176 {
00177 if (argc == 3) {
00178 if (strcmp(argv[1], "setnode") == 0) {
00179 satnode_ = (SatNode*) TclObject::lookup(argv[2]);
00180 return (TCL_OK);
00181 }
00182 }
00183 return LL::command(argc, argv);
00184 }
00185
00186
00187 void SatLL::sendDown(Packet* p)
00188 {
00189 hdr_cmn *ch = HDR_CMN(p);
00190 hdr_ll *llh = HDR_LL(p);
00191 char *mh = (char*)p->access(hdr_mac::offset_);
00192 int peer_mac_;
00193 SatChannel* satchannel_;
00194
00195 llh->seqno_ = ++seqno_;
00196 llh->lltype() = LL_DATA;
00197
00198
00199 if (SatRouteObject::instance().wiredRouting()) {
00200
00201
00202
00203 RouteLogic *routelogic_;
00204 hdr_ip* h = hdr_ip::access(p);
00205 int next_hopIP = -1;
00206 int myaddr_;
00207 Tcl &tcl = Tcl::instance();
00208 tcl.evalc("[Simulator instance] get-routelogic");
00209 routelogic_ = (RouteLogic*) TclObject::lookup(tcl.result());
00210 char* adst = Address::instance().print_nodeaddr(h->daddr());
00211 myaddr_ = satnode()->ragent()->myaddr();
00212
00213 char* asrc = Address::instance().print_nodeaddr(myaddr_);
00214 routelogic_->lookup_flat(asrc, adst, next_hopIP);
00215 delete [] adst;
00216 delete [] asrc;
00217
00218
00219 ch->next_hop_ = next_hopIP;
00220 if (satnode()) {
00221 ch->last_hop_ = satnode()->ragent()->myaddr();
00222 } else {
00223 printf("Error: LL has no satnode_ pointer set\n");
00224 exit(1);
00225 }
00226 }
00227
00228 mac_->hdr_src(mh, mac_->addr());
00229 mac_->hdr_type(mh, ETHERTYPE_IP);
00230
00231 nsaddr_t dst = ch->next_hop();
00232
00233 if (dst < -1) {
00234 printf("Error: next_hop_ field not set by routing agent\n");
00235 exit(1);
00236 }
00237
00238 switch(ch->addr_type()) {
00239
00240 case NS_AF_INET:
00241 case NS_AF_NONE:
00242 if (IP_BROADCAST == (u_int32_t) dst)
00243 {
00244 mac_->hdr_dst((char*) HDR_MAC(p), MAC_BROADCAST);
00245 break;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255 if (dst == arpcachedst_) {
00256 mac_->hdr_dst((char*) HDR_MAC(p), arpcache_);
00257 break;
00258 }
00259
00260 satchannel_ = (SatChannel*) channel();
00261 peer_mac_ = satchannel_->find_peer_mac_addr(dst);
00262 if (peer_mac_ < 0 ) {
00263 printf("Error: couldn't find dest mac on channel ");
00264 printf("for src/dst %d %d at NOW %f\n",
00265 ch->last_hop_, dst, NOW);
00266 exit(1);
00267 } else {
00268 mac_->hdr_dst((char*) HDR_MAC(p), peer_mac_);
00269 arpcachedst_ = dst;
00270 arpcache_ = peer_mac_;
00271 break;
00272 }
00273
00274 default:
00275 printf("Error: addr_type not set to NS_AF_INET or NS_AF_NONE\n");
00276 exit(1);
00277 }
00278
00279
00280 Scheduler& s = Scheduler::instance();
00281 s.schedule(downtarget_, p, delay_);
00282 }
00283
00284 void SatLL::sendUp(Packet* p)
00285 {
00286 Scheduler& s = Scheduler::instance();
00287 if (hdr_cmn::access(p)->error() > 0)
00288 drop(p);
00289 else
00290 s.schedule(uptarget_, p, delay_);
00291 }
00292
00293
00294 Channel* SatLL::channel()
00295 {
00296 Phy* phy_ = (Phy*) mac_->downtarget();
00297 return phy_->channel();
00298 }
00299
00300
00301
00302
00303
00304
00305 static class SatMacClass : public TclClass {
00306 public:
00307 SatMacClass() : TclClass("Mac/Sat") {}
00308 TclObject* create(int, const char*const*) {
00309 return (new SatMac);
00310 }
00311 } sat_class_mac;
00312
00313 void MacSendTimer::expire(Event*)
00314 {
00315 a_->send_timer();
00316 }
00317
00318 void MacRecvTimer::expire(Event*)
00319 {
00320 a_->recv_timer();
00321 }
00322
00323 SatMac::SatMac() : Mac(), send_timer_(this), recv_timer_(this)
00324 {
00325 bind_bool("trace_collisions_", &trace_collisions_);
00326 bind_bool("trace_drops_", &trace_drops_);
00327 }
00328
00329 int SatMac::command(int argc, const char*const* argv)
00330 {
00331 Tcl& tcl = Tcl::instance();
00332 if(argc == 2) {
00333 }
00334 else if (argc == 3) {
00335 TclObject *obj;
00336 if( (obj = TclObject::lookup(argv[2])) == 0) {
00337 fprintf(stderr, "%s lookup failed\n", argv[1]);
00338 return TCL_ERROR;
00339 }
00340 if (strcmp(argv[1], "channel") == 0) {
00341
00342 return (TCL_OK);
00343 }
00344 if (strcmp(argv[1], "set_drop_trace") == 0) {
00345 drop_trace_ = (SatTrace *) TclObject::lookup(argv[2]);
00346 if (drop_trace_ == 0) {
00347 tcl.resultf("no such object %s", argv[2]);
00348 return (TCL_ERROR);
00349 }
00350 return (TCL_OK);
00351 }
00352 if (strcmp(argv[1], "set_coll_trace") == 0) {
00353 coll_trace_ = (SatTrace *) TclObject::lookup(argv[2]);
00354 if (coll_trace_ == 0) {
00355 tcl.resultf("no such object %s", argv[2]);
00356 return (TCL_ERROR);
00357 }
00358 return (TCL_OK);
00359 }
00360 }
00361 return Mac::command(argc, argv);
00362 }
00363
00364 void SatMac::sendUp(Packet* p)
00365 {
00366 hdr_mac* mh = HDR_MAC(p);
00367 int dst = this->hdr_dst((char*)mh);
00368
00369 if (((u_int32_t)dst != MAC_BROADCAST) && (dst != index_)) {
00370 drop(p);
00371 return;
00372 }
00373
00374
00375 Scheduler::instance().schedule(uptarget_, p, delay_ + mh->txtime());
00376 }
00377
00378
00379
00380 void SatMac::sendDown(Packet* p)
00381 {
00382 Scheduler& s = Scheduler::instance();
00383 double txt;
00384
00385
00386
00387 int packetsize_ = HDR_CMN(p)->size() + LINK_HDRSIZE;
00388 if (bandwidth_ != 0)
00389 txt = txtime(packetsize_);
00390
00391
00392
00393 HDR_MAC(p)->txtime() = txt;
00394 downtarget_->recv(p, this);
00395
00396 s.schedule(&hRes_, &intr_, txt);
00397 }
00398
00399 static class UnslottedAlohaMacClass : public TclClass {
00400 public:
00401 UnslottedAlohaMacClass() : TclClass("Mac/Sat/UnslottedAloha") {}
00402 TclObject* create(int, const char*const*) {
00403 return (new UnslottedAlohaMac());
00404 }
00405 } sat_class_unslottedalohamac;
00406
00407
00408
00409
00410
00411
00412 UnslottedAlohaMac::UnslottedAlohaMac() : SatMac(), tx_state_(MAC_IDLE),
00413 rx_state_(MAC_IDLE), rtx_(0), end_of_contention_(0)
00414 {
00415 bind_time("mean_backoff_", &mean_backoff_);
00416 bind("rtx_limit_", &rtx_limit_);
00417 bind_time("send_timeout_", &send_timeout_);
00418 }
00419
00420 void UnslottedAlohaMac::send_timer()
00421 {
00422 switch (tx_state_) {
00423
00424 case MAC_SEND:
00425
00426 backoff();
00427 break;
00428 case MAC_COLL:
00429
00430 sendDown(snd_pkt_);
00431 break;
00432 default:
00433 printf("Error: wrong tx_state in unslotted aloha: %d\n",
00434 tx_state_);
00435 break;
00436 }
00437 }
00438
00439 void UnslottedAlohaMac::recv_timer()
00440 {
00441 switch (rx_state_) {
00442
00443 case MAC_RECV:
00444
00445 end_of_contention(rcv_pkt_);
00446 break;
00447 default:
00448 printf("Error: wrong rx_state in unslotted aloha: %d\n",
00449 rx_state_);
00450 break;
00451 }
00452
00453 }
00454
00455 void UnslottedAlohaMac::sendUp(Packet* p)
00456 {
00457 hdr_mac* mh = HDR_MAC(p);
00458 int dst;
00459
00460 if (rx_state_ == MAC_IDLE) {
00461
00462
00463 rcv_pkt_ = p;
00464 end_of_contention_ = NOW + mh->txtime();
00465 rx_state_ = MAC_RECV;
00466 recv_timer_.resched(mh->txtime());
00467 } else {
00468
00469 if ( (NOW + mh->txtime()) > end_of_contention_ ) {
00470 recv_timer_.resched(mh->txtime());
00471 }
00472
00473
00474 if (rcv_pkt_) {
00475
00476
00477 mh = HDR_MAC(rcv_pkt_);
00478 dst = this->hdr_dst((char*)mh);
00479 if (((u_int32_t)dst == MAC_BROADCAST)||(dst == index_))
00480 if (coll_trace_ && trace_collisions_)
00481 coll_trace_->traceonly(rcv_pkt_);
00482 drop(rcv_pkt_);
00483 }
00484 rcv_pkt_ = 0;
00485
00486
00487 mh = HDR_MAC(p);
00488 dst = this->hdr_dst((char*)mh);
00489 if (((u_int32_t)dst == MAC_BROADCAST) || (dst == index_))
00490 if (coll_trace_ && trace_collisions_)
00491 coll_trace_->traceonly(p);
00492 drop(p);
00493 }
00494 }
00495
00496 void UnslottedAlohaMac::sendDown(Packet* p)
00497 {
00498 double txt;
00499
00500
00501 int packetsize_ = HDR_CMN(p)->size() + LINK_HDRSIZE;
00502 if (bandwidth_ != 0)
00503 txt = txtime(packetsize_);
00504 HDR_MAC(p)->txtime() = txt;
00505
00506
00507 tx_state_ = MAC_SEND;
00508 snd_pkt_ = p->copy();
00509 downtarget_->recv(p, this);
00510
00511
00512
00513
00514 send_timer_.resched(send_timeout_ + txt);
00515 }
00516
00517
00518 void UnslottedAlohaMac::end_of_contention(Packet* p)
00519 {
00520 rx_state_ = MAC_IDLE;
00521 if (!p)
00522 return;
00523
00524 hdr_mac* mh = HDR_MAC(p);
00525 int dst = this->hdr_dst((char*)mh);
00526 int src = this->hdr_src((char*)mh);
00527
00528 if (((u_int32_t)dst != MAC_BROADCAST) && (dst != index_) &&
00529 (src != index_)) {
00530 drop(p);
00531 return;
00532 }
00533 if (src == index_) {
00534
00535
00536 if (!callback_) {
00537 printf("Error, queue callback_ is not valid\n");
00538 exit(1);
00539 }
00540 send_timer_.force_cancel();
00541 tx_state_ = MAC_IDLE;
00542 rtx_ = 0;
00543 drop(snd_pkt_);
00544 resume(p);
00545 } else {
00546
00547 Scheduler::instance().schedule(uptarget_, p, delay_);
00548 }
00549 }
00550
00551 void UnslottedAlohaMac::backoff(double delay)
00552 {
00553 double backoff_ = Random::exponential(mean_backoff_);
00554
00555
00556
00557 if (++rtx_ <= rtx_limit_) {
00558 tx_state_ = MAC_COLL;
00559 delay += backoff_;
00560 send_timer_.resched(delay);
00561 } else {
00562 tx_state_ = MAC_IDLE;
00563 rtx_ = 0;
00564
00565 if (drop_trace_ && trace_drops_)
00566 drop_trace_->traceonly(snd_pkt_);
00567 resume(snd_pkt_);
00568 }
00569 }
00570
00571
00572
00573
00574
00575
00576
00577 static class SatPhyClass: public TclClass {
00578 public:
00579 SatPhyClass() : TclClass("Phy/Sat") {}
00580 TclObject* create(int, const char*const*) {
00581 return (new SatPhy);
00582 }
00583 } class_SatPhy;
00584
00585 void SatPhy::sendDown(Packet *p)
00586 {
00587 if (channel_)
00588 channel_->recv(p, this);
00589 else {
00590
00591
00592
00593
00594 if ( ((SatNode*) head()->node())->trace() )
00595 ((SatNode*) head()->node())->trace()->traceonly(p);
00596 Packet::free(p);
00597 }
00598 }
00599
00600
00601
00602
00603 int SatPhy::sendUp(Packet * )
00604 {
00605 return TRUE;
00606 }
00607
00608 int
00609 SatPhy::command(int argc, const char*const* argv) {
00610 if (argc == 2) {
00611 } else if (argc == 3) {
00612 TclObject *obj;
00613
00614 if( (obj = TclObject::lookup(argv[2])) == 0) {
00615 fprintf(stderr, "%s lookup failed\n", argv[1]);
00616 return TCL_ERROR;
00617 }
00618 }
00619 return Phy::command(argc, argv);
00620 }
00621
00622 static class RepeaterPhyClass: public TclClass {
00623 public:
00624 RepeaterPhyClass() : TclClass("Phy/Repeater") {}
00625 TclObject* create(int, const char*const*) {
00626 return (new RepeaterPhy);
00627 }
00628 } class_RepeaterPhy;
00629
00630 void RepeaterPhy::recv(Packet* p, Handler*)
00631 {
00632 struct hdr_cmn *hdr = HDR_CMN(p);
00633 if (hdr->direction() == hdr_cmn::UP) {
00634
00635
00636 hdr->direction() = hdr_cmn::DOWN;
00637 uptarget_->recv(p, (Handler*) 0);
00638 } else {
00639 sendDown(p);
00640 }
00641 }
00642
00643 void RepeaterPhy::sendDown(Packet *p)
00644 {
00645 struct hdr_cmn *hdr = HDR_CMN(p);
00646 hdr->direction() = hdr_cmn::DOWN;
00647
00648 if (channel_)
00649 channel_->recv(p, this);
00650 else {
00651 printf("Error, no channel on repeater\n");
00652 exit(1);
00653 }
00654 }
00655
00656
00657
00658
00659
00660
00661 static class SatChannelClass : public TclClass {
00662 public:
00663 SatChannelClass() : TclClass("Channel/Sat") {}
00664 TclObject* create(int, const char*const*) {
00665 return (new SatChannel);
00666 }
00667 } class_Sat_channel;
00668
00669 SatChannel::SatChannel(void) : Channel() {
00670 }
00671
00672 double
00673 SatChannel::get_pdelay(Node* tnode, Node* rnode)
00674 {
00675 coordinate a = ((SatNode*)tnode)->position()->coord();
00676 coordinate b = ((SatNode*)rnode)->position()->coord();
00677 return (SatGeometry::propdelay(a, b));
00678 }
00679
00680
00681 void SatChannel::add_interface(Phy* phy_)
00682 {
00683 phy_->setchnl(this);
00684 phy_->insertchnl(&ifhead_);
00685 }
00686
00687
00688 void SatChannel::remove_interface(Phy* phy_)
00689 {
00690 phy_->setchnl(NULL);
00691 phy_->removechnl();
00692 }
00693
00694
00695
00696
00697 int SatChannel::find_peer_mac_addr(int dst)
00698 {
00699 Phy *n;
00700 Channel* chan_;
00701 chan_ = this;
00702 n = ifhead_.lh_first;
00703 if (n->head()->type() == LINK_GSL_REPEATER) {
00704 SatLinkHead* slh = (SatLinkHead*) n->head();
00705 chan_ = slh->phy_tx()->channel();
00706 }
00707 for(n = chan_->ifhead_.lh_first; n; n = n->nextchnl() ) {
00708 if (n->node()->address() == dst) {
00709 return (((SatMac*) n->uptarget())->addr());
00710 }
00711 }
00712 return -1;
00713 }
00714
00715