satlink.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:19k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1999 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *      This product includes software developed by the MASH Research
  17.  *      Group at the University of California Berkeley.
  18.  * 4. Neither the name of the University nor of the Research Group may be
  19.  *    used to endorse or promote products derived from this software without
  20.  *    specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  *
  34.  * Contributed by Tom Henderson, UCB Daedalus Research Group, June 1999
  35.  */
  36. #ifndef lint
  37. static const char rcsid[] =
  38.     "@(#) $Header: /cvsroot/nsnam/ns-2/satellite/satlink.cc,v 1.14 2005/09/21 21:45:04 haldar Exp $";
  39. #endif
  40. /*
  41.  * Contains source code for:
  42.  * SatLinkHead
  43.  *   SatLL
  44.  *  SatMac
  45.  *  SatPhy
  46.  *  SatChannel
  47.  */
  48. #include "satlink.h"
  49. #include "sattrace.h"
  50. #include "satposition.h"
  51. #include "satgeometry.h"
  52. #include "satnode.h"
  53. #include "satroute.h"
  54. #include "errmodel.h"
  55. #include "sat-hdlc.h"
  56. /*==========================================================================*/
  57. /*
  58.  * _SatLinkHead
  59.  */
  60. static class SatLinkHeadClass : public TclClass {
  61. public:
  62. SatLinkHeadClass() : TclClass("Connector/LinkHead/Sat") {}
  63. TclObject* create(int, const char*const*) {
  64. return (new SatLinkHead);
  65. }
  66. } class_sat_link_head;
  67. SatLinkHead::SatLinkHead() : linkup_(1), phy_tx_(0), phy_rx_(0), mac_(0), satll_(0), queue_(0), errmodel_(0)
  68. {
  69. }
  70. int SatLinkHead::command(int argc, const char*const* argv)
  71. {
  72. if (argc == 2) {
  73. } else if (argc == 3) {
  74. if (strcmp(argv[1], "set_type") == 0) {
  75. if (strcmp(argv[2], "geo") == 0) {
  76. type_ = LINK_GSL_GEO;
  77. return TCL_OK;
  78. } else if (strcmp(argv[2], "polar") == 0) {
  79. type_ = LINK_GSL_POLAR;
  80. return TCL_OK;
  81. } else if (strcmp(argv[2], "gsl") == 0) {
  82. type_ = LINK_GSL;
  83. return TCL_OK;
  84. } else if (strcmp(argv[2], "gsl-repeater") == 0) {
  85. type_ = LINK_GSL_REPEATER;
  86. return TCL_OK;
  87. } else if (strcmp(argv[2], "interplane") == 0) {
  88. type_ = LINK_ISL_INTERPLANE;
  89. return TCL_OK;
  90. } else if (strcmp(argv[2], "intraplane") == 0) {
  91. type_ = LINK_ISL_INTRAPLANE;
  92. return TCL_OK;
  93. } else if (strcmp(argv[2], "crossseam") == 0) {
  94. type_ = LINK_ISL_CROSSSEAM;
  95. return TCL_OK;
  96. } else {
  97. printf("Unknown link type: %sn", argv[2]);
  98. exit(1);
  99. }
  100. if (strcmp(argv[1], "setll") == 0) {
  101. satll_ = (SatLL*) TclObject::lookup(argv[2]);
  102. if (satll_ == 0)
  103. return TCL_ERROR;
  104. return TCL_OK;
  105. } else if(strcmp(argv[1], "setphytx") == 0) {
  106. phy_tx_ = (SatPhy*) TclObject::lookup(argv[2]);
  107. if (phy_tx_ == 0)
  108. return TCL_ERROR;
  109. return TCL_OK;
  110. } else if(strcmp(argv[1], "setphyrx") == 0) {
  111. phy_rx_ = (SatPhy*) TclObject::lookup(argv[2]);
  112. if (phy_rx_ == 0)
  113. return TCL_ERROR;
  114. return TCL_OK;
  115. } else if(strcmp(argv[1], "setmac") == 0) {
  116. mac_ = (SatMac*) TclObject::lookup(argv[2]);
  117. if (mac_ == 0)
  118. return TCL_ERROR;
  119. return TCL_OK;
  120. } else if(strcmp(argv[1], "setqueue") == 0) {
  121. queue_ = (Queue*) TclObject::lookup(argv[2]);
  122. if (queue_ == 0)
  123. return TCL_ERROR;
  124. return TCL_OK;
  125. } else if(strcmp(argv[1], "seterrmodel") == 0) {
  126. errmodel_ = (ErrorModel*) TclObject::lookup(argv[2]);
  127. if (errmodel_ == 0)
  128. return TCL_ERROR;
  129. return TCL_OK;
  130. }
  131. }
  132. return (LinkHead::command(argc, argv));
  133. }
  134. /*==========================================================================*/
  135. /*
  136.  * _SatLL
  137.  */
  138. static class SatLLClass : public TclClass {
  139. public:
  140. SatLLClass() : TclClass("LL/Sat") {}
  141. TclObject* create(int, const char*const*) {
  142. return (new SatLL);
  143. }
  144. } sat_class_ll;
  145. void SatLL::recv(Packet* p, Handler* /*h*/)
  146. {
  147. hdr_cmn *ch = HDR_CMN(p);
  148. /*
  149.  * Sanity Check
  150.  */
  151. assert(initialized());
  152. // If direction = UP, then pass it up the stack
  153. // Otherwise, set direction to DOWN and pass it down the stack
  154. if(ch->direction() == hdr_cmn::UP) {
  155. uptarget_ ? sendUp(p) : drop(p);
  156. return;
  157. }
  158. ch->direction() = hdr_cmn::DOWN;
  159. sendDown(p);
  160. }
  161. int SatLL::command(int argc, const char*const* argv)
  162. {
  163. if (argc == 3) {
  164. if (strcmp(argv[1], "setnode") == 0) {
  165. satnode_ = (SatNode*) TclObject::lookup(argv[2]);
  166. return (TCL_OK);
  167. }
  168. }
  169. return LL::command(argc, argv);
  170. }
  171. int SatLL::getRoute(Packet *p)
  172. {
  173. hdr_cmn *ch = HDR_CMN(p);
  174.         // wired-satellite integration
  175. if (SatRouteObject::instance().wiredRouting()) {
  176. hdr_ip *ip = HDR_IP(p);
  177. RouteLogic *routelogic_;
  178. int next_hopIP = -1; // Initialize in case route not found
  179. int myaddr_;
  180. // Wired/satellite integration
  181. // We need to make sure packet headers are set correctly
  182. // This code adapted from virtual-classifier.cc
  183. Tcl &tcl = Tcl::instance();
  184. tcl.evalc("[Simulator instance] get-routelogic");
  185. routelogic_ = (RouteLogic*) TclObject::lookup(tcl.result());
  186. char* adst = Address::instance().print_nodeaddr(ip->daddr());
  187. myaddr_ = satnode()->ragent()->myaddr();
  188. //char* asrc = Address::instance().print_nodeaddr(h->saddr());
  189. char* asrc = Address::instance().print_nodeaddr(myaddr_);
  190. routelogic_->lookup_flat(asrc, adst, next_hopIP);
  191. delete [] adst;
  192. delete [] asrc;
  193. // The following fields are usually set by routeagent
  194. // forwardPacket() in satroute.cc (when wiredRouting_ == 0)
  195. ch->next_hop_ = next_hopIP;
  196. if (satnode()) {
  197. ch->last_hop_ = satnode()->ragent()->myaddr();
  198. } else {
  199. printf("Error:  LL has no satnode_ pointer setn");
  200. exit(1);
  201. }
  202.         }
  203. // else (if no wired rtg) next-hop field is populated by rtg agent
  204. return ch->next_hop_;
  205. }
  206. // Encode link layer sequence number, type, and mac address fields
  207. void SatLL::sendDown(Packet* p)
  208. {
  209. hdr_cmn *ch = HDR_CMN(p);
  210. hdr_ll *llh = HDR_LL(p);
  211. char *mh = (char*)p->access(hdr_mac::offset_);
  212. int peer_mac_;
  213. SatChannel* satchannel_;
  214. llh->seqno_ = ++seqno_;
  215. llh->lltype() = LL_DATA;
  216. getRoute(p);
  217. // Set mac src, type, and dst
  218. mac_->hdr_src(mh, mac_->addr());
  219. mac_->hdr_type(mh, ETHERTYPE_IP); // We'll just use ETHERTYPE_IP
  220. nsaddr_t dst = ch->next_hop();
  221. // a value of -1 is IP_BROADCAST
  222. if (dst < -1) {
  223. printf("Error:  next_hop_ field not set by routing agentn");
  224. exit(1);
  225. }
  226. switch(ch->addr_type()) {
  227. case NS_AF_INET:
  228. case NS_AF_NONE:
  229. if (IP_BROADCAST == (u_int32_t) dst)
  230. {
  231. mac_->hdr_dst((char*) HDR_MAC(p), MAC_BROADCAST);
  232. break;
  233. }
  234. /* 
  235.  * Here is where arp would normally occur.  In the satellite
  236.  * case, we don't arp (for now).  Instead, use destination
  237.  * address to find the mac address corresponding to the
  238.  * peer connected to this channel.  If someone wants to
  239.  * add arp, look at how the wireless code does it.
  240.  */ 
  241. // Cache latest value used
  242. if (dst == arpcachedst_) {
  243. mac_->hdr_dst((char*) HDR_MAC(p), arpcache_);
  244. break;
  245. }
  246. // Search for peer's mac address (this is the pseudo-ARP)
  247. satchannel_ = (SatChannel*) channel();
  248. peer_mac_ = satchannel_->find_peer_mac_addr(dst);
  249. if (peer_mac_ < 0 ) {
  250. printf("Error:  couldn't find dest mac on channel ");
  251. printf("for src/dst %d %d at NOW %fn", 
  252.     ch->last_hop_, dst, NOW); 
  253. exit(1);
  254. } else {
  255. mac_->hdr_dst((char*) HDR_MAC(p), peer_mac_);
  256. arpcachedst_ = dst;
  257. arpcache_ = peer_mac_;
  258. break;
  259. default:
  260. printf("Error:  addr_type not set to NS_AF_INET or NS_AF_NONEn");
  261. exit(1);
  262. }
  263. // let mac decide when to take a new packet from the queue.
  264. Scheduler& s = Scheduler::instance();
  265. s.schedule(downtarget_, p, delay_);
  266. }
  267. void SatLL::sendUp(Packet* p)
  268. {
  269. Scheduler& s = Scheduler::instance();
  270. if (hdr_cmn::access(p)->error() > 0)
  271. drop(p);
  272. else
  273. s.schedule(uptarget_, p, delay_);
  274. }
  275. // Helper function 
  276. Channel* SatLL::channel()
  277. {
  278. Phy* phy_ = (Phy*) mac_->downtarget();
  279. return phy_->channel();
  280. }
  281. /*==========================================================================*/
  282. /*
  283.  * _SatMac
  284.  */
  285. static class SatMacClass : public TclClass {
  286. public:
  287. SatMacClass() : TclClass("Mac/Sat") {}
  288. TclObject* create(int, const char*const*) {
  289. return (new SatMac);
  290. }
  291. } sat_class_mac;
  292. void MacSendTimer::expire(Event*)
  293. {
  294.         a_->send_timer();
  295. }
  296. void MacRecvTimer::expire(Event*)
  297. {
  298.         a_->recv_timer();
  299. }
  300. SatMac::SatMac() : Mac(), send_timer_(this), recv_timer_(this)
  301. {
  302. bind_bool("trace_collisions_", &trace_collisions_);
  303. bind_bool("trace_drops_", &trace_drops_);
  304. }
  305. int SatMac::command(int argc, const char*const* argv)
  306. {
  307. Tcl& tcl = Tcl::instance();
  308. if(argc == 2) {
  309. }
  310. else if (argc == 3) {
  311. TclObject *obj;
  312. if( (obj = TclObject::lookup(argv[2])) == 0) {
  313. fprintf(stderr, "%s lookup failedn", argv[1]);
  314. return TCL_ERROR;                
  315. }
  316. if (strcmp(argv[1], "channel") == 0) {
  317. //channel_ = (Channel*) obj;
  318. return (TCL_OK);
  319. }
  320. if (strcmp(argv[1], "set_drop_trace") == 0) {
  321. drop_trace_ = (SatTrace *) TclObject::lookup(argv[2]);
  322. if (drop_trace_ == 0) {
  323. tcl.resultf("no such object %s", argv[2]);
  324. return (TCL_ERROR);
  325. }
  326. return (TCL_OK);
  327. }
  328. if (strcmp(argv[1], "set_coll_trace") == 0) {
  329. coll_trace_ = (SatTrace *) TclObject::lookup(argv[2]);
  330. if (coll_trace_ == 0) {
  331. tcl.resultf("no such object %s", argv[2]);
  332. return (TCL_ERROR);
  333. }
  334. return (TCL_OK);
  335. }
  336. }
  337. return Mac::command(argc, argv);
  338. }
  339. void SatMac::sendUp(Packet* p) 
  340. {
  341. hdr_mac* mh = HDR_MAC(p);
  342. int dst = this->hdr_dst((char*)mh); // mac destination address
  343. if (((u_int32_t)dst != MAC_BROADCAST) && (dst != index_)) {
  344. drop(p);
  345. return;
  346. }
  347. // First bit of packet has arrived-- wait for 
  348. // (txtime + delay_) before sending up
  349. Scheduler::instance().schedule(uptarget_, p, delay_ + mh->txtime());
  350. }
  351. void SatMac::sendDown(Packet* p)
  352. {
  353. Scheduler& s = Scheduler::instance();
  354. double txt;
  355. // LINK_HDRSIZE is defined in satlink.h.  This is the size of header
  356. // information for all layers below IP.  Alternatively, one could
  357. // derive this information dynamically from packet headers. 
  358. int packetsize_ = HDR_CMN(p)->size() + LINK_HDRSIZE;
  359. assert (bandwidth_ != 0);
  360. txt = txtime(packetsize_);
  361. // For convenience, we encode the transmit time in the Mac header
  362. // The packet will be held (for collision detection) for txtime 
  363. // at the receiving mac.
  364.         HDR_MAC(p)->txtime() = txt;
  365. downtarget_->recv(p, this);
  366. // Callback for when this packet's transmission will be done
  367. s.schedule(&hRes_, &intr_, txt);
  368. }
  369. static class UnslottedAlohaMacClass : public TclClass {
  370. public:
  371. UnslottedAlohaMacClass() : TclClass("Mac/Sat/UnslottedAloha") {}
  372. TclObject* create(int, const char*const*) {
  373. return (new UnslottedAlohaMac());
  374. }
  375. } sat_class_unslottedalohamac;
  376. /*==========================================================================*/
  377. /*
  378.  * _UnslottedAlohaMac
  379.  */
  380. UnslottedAlohaMac::UnslottedAlohaMac() : SatMac(), tx_state_(MAC_IDLE), 
  381.     rx_state_(MAC_IDLE), rtx_(0), end_of_contention_(0) 
  382. {
  383. bind_time("mean_backoff_", &mean_backoff_);
  384. bind("rtx_limit_", &rtx_limit_);
  385. bind_time("send_timeout_", &send_timeout_);
  386. }
  387. void UnslottedAlohaMac::send_timer() 
  388. {
  389. switch (tx_state_) {
  390. case MAC_SEND:
  391. // We've timed out on send-- back off
  392. backoff();
  393. break;
  394. case MAC_COLL:
  395. // Our backoff timer has expired-- resend
  396. sendDown(snd_pkt_);
  397. break;
  398. default:
  399. printf("Error: wrong tx_state in unslotted aloha: %dn",
  400.     tx_state_);
  401. break;
  402. }
  403. }
  404. void UnslottedAlohaMac::recv_timer() 
  405. {
  406. switch (rx_state_) {
  407. case MAC_RECV:
  408. // We've successfully waited out the reception
  409. end_of_contention(rcv_pkt_);
  410. break;
  411. default:
  412. printf("Error: wrong rx_state in unslotted aloha: %dn",
  413.     rx_state_);
  414. break;
  415. }
  416. }
  417. void UnslottedAlohaMac::sendUp(Packet* p) 
  418. {
  419. hdr_mac* mh = HDR_MAC(p);
  420. int dst;
  421. if (rx_state_ == MAC_IDLE) {
  422. // First bit of packet has arrived-- wait for 
  423. // txtime to make sure no collisions occur 
  424. rcv_pkt_ = p;
  425. end_of_contention_ = NOW + mh->txtime();
  426. rx_state_ = MAC_RECV;
  427. recv_timer_.resched(mh->txtime());
  428. } else {
  429. // Collision: figure out if contention phase must be lengthened
  430. if ( (NOW + mh->txtime()) > end_of_contention_ ) {
  431. recv_timer_.resched(mh->txtime());
  432. }
  433. // If this is the first collision, we will also have a
  434. // rcv_pkt_ pending
  435. if (rcv_pkt_) {
  436. // Before dropping rcv_pkt_, trace the collision
  437. // if it was intended for us
  438. mh = HDR_MAC(rcv_pkt_);
  439. dst = this->hdr_dst((char*)mh); // mac dest. address
  440. if (((u_int32_t)dst == MAC_BROADCAST)||(dst == index_))
  441. if (coll_trace_ && trace_collisions_)
  442. coll_trace_->traceonly(rcv_pkt_);
  443. drop(rcv_pkt_);
  444. }
  445. rcv_pkt_ = 0;
  446. // Again, before we drop this packet, log a collision if
  447. // it was intended for us
  448. mh = HDR_MAC(p);
  449. dst = this->hdr_dst((char*)mh); // mac destination address
  450. if (((u_int32_t)dst == MAC_BROADCAST) || (dst == index_))
  451. if (coll_trace_ && trace_collisions_)
  452. coll_trace_->traceonly(p);
  453. drop(p);
  454. }
  455. }
  456. void UnslottedAlohaMac::sendDown(Packet* p)
  457. {
  458. double txt;
  459. // compute transmission delay:
  460. int packetsize_ = HDR_CMN(p)->size() + LINK_HDRSIZE;
  461. assert (bandwidth_ != 0);
  462. txt = txtime(packetsize_);
  463.         HDR_MAC(p)->txtime() = txt;
  464. // Send the packet down 
  465. tx_state_ = MAC_SEND;
  466. snd_pkt_ = p->copy();  // save a copy in case it gets retransmitted
  467. downtarget_->recv(p, this);
  468. // Set a timer-- if we do not hear our own transmission within this
  469. // interval (and cancel the timer), the send_timer will expire and
  470. // we will backoff and retransmit.
  471. send_timer_.resched(send_timeout_ + txt);
  472. }
  473. // Called when contention period ends
  474. void UnslottedAlohaMac::end_of_contention(Packet* p) 
  475. {
  476. rx_state_ = MAC_IDLE;
  477. if (!p)  
  478. return; // No packet to free or send up.
  479. hdr_mac* mh = HDR_MAC(p);
  480. int dst = this->hdr_dst((char*)mh); // mac destination address
  481. int src = this->hdr_src((char*)mh); // mac source address
  482. if (((u_int32_t)dst != MAC_BROADCAST) && (dst != index_) && 
  483.          (src != index_)) {
  484. drop(p); // Packet not intended for our station
  485. return;
  486. if (src == index_) {
  487. // received our own packet: free up transmit side, drop this
  488. // packet, and perform callback to queue which is blocked
  489. if (!callback_) {
  490. printf("Error, queue callback_ is not validn");
  491. exit(1);
  492. }
  493. send_timer_.force_cancel();
  494. tx_state_ = MAC_IDLE;
  495. rtx_ = 0;
  496. drop(snd_pkt_); // Free the packet cached for retransmission
  497. resume(p);
  498. } else {
  499. // wait for processing delay (delay_) to send packet upwards 
  500. Scheduler::instance().schedule(uptarget_, p, delay_);
  501. }
  502. }
  503. void UnslottedAlohaMac::backoff(double delay)
  504. {
  505. double backoff_ = Random::exponential(mean_backoff_);
  506. // if number of retransmissions is within limit, do exponential backoff
  507. // else drop the packet and resume
  508. if (++rtx_ <= rtx_limit_) {
  509. tx_state_ = MAC_COLL;
  510. delay += backoff_;
  511. send_timer_.resched(delay);
  512. } else {
  513. tx_state_ = MAC_IDLE;
  514. rtx_ = 0;
  515. // trace the dropped packet
  516. if (drop_trace_ && trace_drops_)
  517. drop_trace_->traceonly(snd_pkt_);
  518. resume(snd_pkt_);
  519. }
  520. }
  521. /*==========================================================================*/
  522. /*
  523.  * _SatPhy
  524.  */
  525. static class SatPhyClass: public TclClass {
  526. public:
  527. SatPhyClass() : TclClass("Phy/Sat") {}
  528. TclObject* create(int, const char*const*) {
  529. return (new SatPhy);
  530. }
  531. } class_SatPhy;
  532. void SatPhy::sendDown(Packet *p)
  533. {
  534. if (channel_)
  535. channel_->recv(p, this);
  536. else {
  537. // it is possible for routing to change (and a channel to
  538. // be disconnected) while a packet
  539. // is moving down the stack.  Therefore, just log a drop
  540. // if there is no channel
  541. if ( ((SatNode*) head()->node())->trace() )
  542. ((SatNode*) head()->node())->trace()->traceonly(p);
  543. Packet::free(p);
  544. }
  545. }
  546. // Note that this doesn't do that much right now.  If you want to incorporate
  547. // an error model, you could insert a "propagation" object like in the
  548. // wireless case.
  549. int SatPhy::sendUp(Packet * /* pkt */)
  550. {
  551. return TRUE;
  552. }
  553. int
  554. SatPhy::command(int argc, const char*const* argv) {
  555. if (argc == 2) {
  556. } else if (argc == 3) {
  557. TclObject *obj;
  558. if( (obj = TclObject::lookup(argv[2])) == 0) {
  559. fprintf(stderr, "%s lookup failedn", argv[1]);
  560. return TCL_ERROR;
  561. }
  562. }
  563. return Phy::command(argc, argv);
  564. }
  565. static class RepeaterPhyClass: public TclClass {
  566. public:
  567. RepeaterPhyClass() : TclClass("Phy/Repeater") {}
  568. TclObject* create(int, const char*const*) {
  569. return (new RepeaterPhy);
  570. }
  571. } class_RepeaterPhy;
  572. void RepeaterPhy::recv(Packet* p, Handler*)
  573. {
  574. struct hdr_cmn *hdr = HDR_CMN(p);
  575. if (hdr->direction() == hdr_cmn::UP) {
  576. // change direction and send to uptarget (which is
  577. // really a Phy_tx that is also a RepeaterPhy)
  578. hdr->direction() = hdr_cmn::DOWN;
  579. uptarget_->recv(p, (Handler*) 0);
  580. } else {
  581. sendDown(p);
  582. }
  583. }
  584. void RepeaterPhy::sendDown(Packet *p)
  585. {
  586. struct hdr_cmn *hdr = HDR_CMN(p);
  587. hdr->direction() =  hdr_cmn::DOWN;
  588. if (channel_)
  589. channel_->recv(p, this);
  590. else {
  591. printf("Error, no channel on repeatern");
  592. exit(1);
  593. }
  594. }
  595. /*==========================================================================*/
  596. /*
  597.  * _SatChannel
  598.  */
  599. static class SatChannelClass : public TclClass {
  600. public:
  601. SatChannelClass() : TclClass("Channel/Sat") {}
  602. TclObject* create(int, const char*const*) {
  603. return (new SatChannel);
  604. }
  605. } class_Sat_channel;
  606. SatChannel::SatChannel(void) : Channel() {
  607. }
  608. double
  609. SatChannel::get_pdelay(Node* tnode, Node* rnode)
  610. {
  611. coordinate a = ((SatNode*)tnode)->position()->coord();
  612. coordinate b = ((SatNode*)rnode)->position()->coord();
  613. return (SatGeometry::propdelay(a, b));
  614. }
  615. // This is a helper function that attaches a SatChannel to a Phy
  616. void SatChannel::add_interface(Phy* phy_)
  617. {
  618. phy_->setchnl(this); // Attach phy to this channel
  619. phy_->insertchnl(&ifhead_); // Add phy_ to list of phys on the channel
  620. }
  621. // Remove a phy from a channel
  622. void SatChannel::remove_interface(Phy* phy_)
  623. {
  624. phy_->setchnl(NULL); // Set phy_'s channel pointer to NULL
  625. phy_->removechnl(); // Remove phy_ to list of phys on the channel
  626. }
  627. // Search for destination mac address on this channel.  Look through list
  628. // of phys on the channel.  If the channel connects to a geo repeater, look
  629. // for the destination on the corresponding downlink channel.  
  630. int SatChannel::find_peer_mac_addr(int dst)
  631. {
  632. Phy *n;
  633. Channel* chan_;
  634. chan_ = this;
  635. n = ifhead_.lh_first; 
  636. if (n->head()->type() == LINK_GSL_REPEATER) {
  637. SatLinkHead* slh = (SatLinkHead*) n->head();
  638. chan_ = slh->phy_tx()->channel();
  639. }
  640. for(n = chan_->ifhead_.lh_first; n; n = n->nextchnl() ) {
  641. if (n->node()->address() == dst) {
  642. return (((SatMac*) n->uptarget())->addr());
  643. }
  644. }
  645. return -1;
  646. }