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