satlink.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) 1999 Regents of the University of California.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *      This product includes software developed by the MASH Research
00017  *      Group at the University of California Berkeley.
00018  * 4. Neither the name of the University nor of the Research Group may be
00019  *    used to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  * Contributed by Tom Henderson, UCB Daedalus Research Group, June 1999
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  * Contains source code for:
00044  *  SatLinkHead
00045  *      SatLL
00046  *  SatMac
00047  *  SatPhy
00048  *  SatChannel
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  * _SatLinkHead
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  * _SatLL
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* /*h*/)
00158 {
00159     hdr_cmn *ch = HDR_CMN(p);
00160     
00161     /*
00162      * Sanity Check
00163      */
00164     assert(initialized());
00165     
00166     // If direction = UP, then pass it up the stack
00167     // Otherwise, set direction to DOWN and pass it down the stack
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         // wired-satellite integration
00191     if (SatRouteObject::instance().wiredRouting()) {
00192         
00193         hdr_ip *ip = HDR_IP(p);
00194         RouteLogic *routelogic_;
00195         int next_hopIP = -1; // Initialize in case route not found
00196         int myaddr_;
00197         // Wired/satellite integration
00198         // We need to make sure packet headers are set correctly
00199         // This code adapted from virtual-classifier.cc
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         //char* asrc = Address::instance().print_nodeaddr(h->saddr());
00207         char* asrc = Address::instance().print_nodeaddr(myaddr_);
00208         routelogic_->lookup_flat(asrc, adst, next_hopIP);
00209         delete [] adst;
00210         delete [] asrc;
00211         // The following fields are usually set by routeagent
00212         // forwardPacket() in satroute.cc (when wiredRouting_ == 0)
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     // else (if no wired rtg) next-hop field is populated by rtg agent
00222     
00223     return ch->next_hop_;
00224     
00225 }
00226 
00227 
00228 // Encode link layer sequence number, type, and mac address fields
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     // Set mac src, type, and dst
00244     mac_->hdr_src(mh, mac_->addr());
00245     mac_->hdr_type(mh, ETHERTYPE_IP); // We'll just use ETHERTYPE_IP
00246     
00247     nsaddr_t dst = ch->next_hop();
00248     // a value of -1 is IP_BROADCAST
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          * Here is where arp would normally occur.  In the satellite
00265          * case, we don't arp (for now).  Instead, use destination
00266          * address to find the mac address corresponding to the
00267          * peer connected to this channel.  If someone wants to
00268          * add arp, look at how the wireless code does it.
00269          */ 
00270         // Cache latest value used
00271         if (dst == arpcachedst_) {
00272             mac_->hdr_dst((char*) HDR_MAC(p), arpcache_);
00273             break;
00274         }
00275         // Search for peer's mac address (this is the pseudo-ARP)
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     // let mac decide when to take a new packet from the queue.
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 // Helper function 
00310 Channel* SatLL::channel()
00311 {
00312     Phy* phy_ = (Phy*) mac_->downtarget();
00313     return phy_->channel();
00314 }
00315 
00316 /*==========================================================================*/
00317 /*
00318  * _SatMac
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             //channel_ = (Channel*) obj;
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); // mac destination address
00384     
00385     if (((u_int32_t)dst != MAC_BROADCAST) && (dst != index_)) {
00386         drop(p);
00387         return;
00388     }
00389     // First bit of packet has arrived-- wait for 
00390     // (txtime + delay_) before sending up
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     // LINK_HDRSIZE is defined in satlink.h.  This is the size of header
00401     // information for all layers below IP.  Alternatively, one could
00402     // derive this information dynamically from packet headers. 
00403     int packetsize_ = HDR_CMN(p)->size() + LINK_HDRSIZE;
00404     assert (bandwidth_ != 0);
00405     txt = txtime(packetsize_);
00406     // For convenience, we encode the transmit time in the Mac header
00407     // The packet will be held (for collision detection) for txtime 
00408     // at the receiving mac.
00409         HDR_MAC(p)->txtime() = txt;
00410     downtarget_->recv(p, this);
00411     // Callback for when this packet's transmission will be done
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  * _UnslottedAlohaMac
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         // We've timed out on send-- back off
00442         backoff();
00443         break;
00444     case MAC_COLL:
00445         // Our backoff timer has expired-- resend
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         // We've successfully waited out the reception
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         // First bit of packet has arrived-- wait for 
00478         // txtime to make sure no collisions occur 
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         // Collision: figure out if contention phase must be lengthened
00485         if ( (NOW + mh->txtime()) > end_of_contention_ ) {
00486             recv_timer_.resched(mh->txtime());
00487         }
00488         // If this is the first collision, we will also have a
00489         // rcv_pkt_ pending
00490         if (rcv_pkt_) {
00491             // Before dropping rcv_pkt_, trace the collision
00492             // if it was intended for us
00493             mh = HDR_MAC(rcv_pkt_);
00494             dst = this->hdr_dst((char*)mh); // mac dest. address
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         // Again, before we drop this packet, log a collision if
00502         // it was intended for us
00503         mh = HDR_MAC(p);
00504         dst = this->hdr_dst((char*)mh); // mac destination address
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     // compute transmission delay:
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     // Send the packet down 
00523     tx_state_ = MAC_SEND;
00524     snd_pkt_ = p->copy();  // save a copy in case it gets retransmitted
00525     downtarget_->recv(p, this);
00526 
00527     // Set a timer-- if we do not hear our own transmission within this
00528     // interval (and cancel the timer), the send_timer will expire and
00529     // we will backoff and retransmit.
00530     send_timer_.resched(send_timeout_ + txt);
00531 }
00532 
00533 // Called when contention period ends
00534 void UnslottedAlohaMac::end_of_contention(Packet* p) 
00535 {
00536     rx_state_ = MAC_IDLE;
00537     if (!p)  
00538         return; // No packet to free or send up.
00539 
00540     hdr_mac* mh = HDR_MAC(p);
00541     int dst = this->hdr_dst((char*)mh); // mac destination address
00542     int src = this->hdr_src((char*)mh); // mac source address
00543     
00544     if (((u_int32_t)dst != MAC_BROADCAST) && (dst != index_) && 
00545             (src != index_)) {
00546         drop(p); // Packet not intended for our station
00547         return;
00548     } 
00549     if (src == index_) {
00550         // received our own packet: free up transmit side, drop this
00551         // packet, and perform callback to queue which is blocked
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_); // Free the packet cached for retransmission
00560         resume(p);
00561     } else {
00562         // wait for processing delay (delay_) to send packet upwards 
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     // if number of retransmissions is within limit, do exponential backoff
00572     // else drop the packet and resume
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         // trace the dropped packet
00581         if (drop_trace_ && trace_drops_)
00582             drop_trace_->traceonly(snd_pkt_);
00583         resume(snd_pkt_);
00584     }
00585 }
00586 
00587 
00588 /*==========================================================================*/
00589 /*
00590  * _SatPhy
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         // it is possible for routing to change (and a channel to
00607         // be disconnected) while a packet
00608         // is moving down the stack.  Therefore, just log a drop
00609         // if there is no channel
00610         if ( ((SatNode*) head()->node())->trace() )
00611             ((SatNode*) head()->node())->trace()->traceonly(p);
00612         Packet::free(p);
00613     }
00614 }
00615 
00616 // Note that this doesn't do that much right now.  If you want to incorporate
00617 // an error model, you could insert a "propagation" object like in the
00618 // wireless case.
00619 int SatPhy::sendUp(Packet * /* pkt */)
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         // change direction and send to uptarget (which is
00651         // really a Phy_tx that is also a RepeaterPhy)
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  * _SatChannel
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 // This is a helper function that attaches a SatChannel to a Phy
00697 void SatChannel::add_interface(Phy* phy_)
00698 {
00699     phy_->setchnl(this); // Attach phy to this channel
00700     phy_->insertchnl(&ifhead_); // Add phy_ to list of phys on the channel
00701 }
00702 
00703 // Remove a phy from a channel
00704 void SatChannel::remove_interface(Phy* phy_)
00705 {
00706     phy_->setchnl(NULL); // Set phy_'s channel pointer to NULL
00707     phy_->removechnl(); // Remove phy_ to list of phys on the channel
00708 }
00709 
00710 // Search for destination mac address on this channel.  Look through list
00711 // of phys on the channel.  If the channel connects to a geo repeater, look
00712 // for the destination on the corresponding downlink channel.  
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 

Generated on Tue Mar 6 16:47:50 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6