Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

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.11 2002/03/21 01:41:06 johnh 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 
00059 /*==========================================================================*/
00060 /*
00061  * _SatLinkHead
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  * _SatLL
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* /*h*/)
00157 {
00158         hdr_cmn *ch = HDR_CMN(p);
00159         
00160         /*
00161          * Sanity Check
00162          */
00163         assert(initialized());
00164         
00165         // If direction = UP, then pass it up the stack
00166         // Otherwise, set direction to DOWN and pass it down the stack
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 // Encode link layer sequence number, type, and mac address fields
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         // wired-satellite integration
00199         if (SatRouteObject::instance().wiredRouting()) {
00200                 // Wired/satellite integration
00201                 // We need to make sure packet headers are set correctly
00202                 // This code adapted from virtual-classifier.cc
00203                 RouteLogic *routelogic_;
00204                 hdr_ip* h = hdr_ip::access(p);
00205                 int next_hopIP = -1; // Initialize in case route not found
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                 //char* asrc = Address::instance().print_nodeaddr(h->saddr());
00213                 char* asrc = Address::instance().print_nodeaddr(myaddr_);
00214                 routelogic_->lookup_flat(asrc, adst, next_hopIP);
00215                 delete [] adst;
00216                 delete [] asrc;
00217                 // The following fields are usually set by routeagent
00218                 // forwardPacket() in satroute.cc (when wiredRouting_ == 0)
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         // Set mac src, type, and dst
00228         mac_->hdr_src(mh, mac_->addr());
00229         mac_->hdr_type(mh, ETHERTYPE_IP); // We'll just use ETHERTYPE_IP
00230         
00231         nsaddr_t dst = ch->next_hop();
00232         // a value of -1 is IP_BROADCAST
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                  * Here is where arp would normally occur.  In the satellite
00249                  * case, we don't arp (for now).  Instead, use destination
00250                  * address to find the mac address corresponding to the
00251                  * peer connected to this channel.  If someone wants to
00252                  * add arp, look at how the wireless code does it.
00253                  */ 
00254                 // Cache latest value used
00255                 if (dst == arpcachedst_) {
00256                         mac_->hdr_dst((char*) HDR_MAC(p), arpcache_);
00257                         break;
00258                 }
00259                 // Search for peer's mac address (this is the pseudo-ARP)
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         // let mac decide when to take a new packet from the queue.
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 // Helper function 
00294 Channel* SatLL::channel()
00295 {
00296         Phy* phy_ = (Phy*) mac_->downtarget();
00297         return phy_->channel();
00298 }
00299 
00300 /*==========================================================================*/
00301 /*
00302  * _SatMac
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                         //channel_ = (Channel*) obj;
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); // mac destination address
00368         
00369         if (((u_int32_t)dst != MAC_BROADCAST) && (dst != index_)) {
00370                 drop(p);
00371                 return;
00372         }
00373         // First bit of packet has arrived-- wait for 
00374         // (txtime + delay_) before sending up
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         // LINK_HDRSIZE is defined in satlink.h.  This is the size of header
00385         // information for all layers below IP.  Alternatively, one could
00386         // derive this information dynamically from packet headers. 
00387         int packetsize_ = HDR_CMN(p)->size() + LINK_HDRSIZE;
00388         if (bandwidth_ != 0)
00389                 txt = txtime(packetsize_);
00390         // For convenience, we encode the transmit time in the Mac header
00391         // The packet will be held (for collision detection) for txtime 
00392         // at the receiving mac.
00393         HDR_MAC(p)->txtime() = txt;
00394         downtarget_->recv(p, this);
00395         // Callback for when this packet's transmission will be done
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  * _UnslottedAlohaMac
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                 // We've timed out on send-- back off
00426                 backoff();
00427                 break;
00428         case MAC_COLL:
00429                 // Our backoff timer has expired-- resend
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                 // We've successfully waited out the reception
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                 // First bit of packet has arrived-- wait for 
00462                 // txtime to make sure no collisions occur 
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                 // Collision: figure out if contention phase must be lengthened
00469                 if ( (NOW + mh->txtime()) > end_of_contention_ ) {
00470                         recv_timer_.resched(mh->txtime());
00471                 }
00472                 // If this is the first collision, we will also have a
00473                 // rcv_pkt_ pending
00474                 if (rcv_pkt_) {
00475                         // Before dropping rcv_pkt_, trace the collision
00476                         // if it was intended for us
00477                         mh = HDR_MAC(rcv_pkt_);
00478                         dst = this->hdr_dst((char*)mh); // mac dest. address
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                 // Again, before we drop this packet, log a collision if
00486                 // it was intended for us
00487                 mh = HDR_MAC(p);
00488                 dst = this->hdr_dst((char*)mh); // mac destination address
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         // compute transmission delay:
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         // Send the packet down 
00507         tx_state_ = MAC_SEND;
00508         snd_pkt_ = p->copy();  // save a copy in case it gets retransmitted
00509         downtarget_->recv(p, this);
00510 
00511         // Set a timer-- if we do not hear our own transmission within this
00512         // interval (and cancel the timer), the send_timer will expire and
00513         // we will backoff and retransmit.
00514         send_timer_.resched(send_timeout_ + txt);
00515 }
00516 
00517 // Called when contention period ends
00518 void UnslottedAlohaMac::end_of_contention(Packet* p) 
00519 {
00520         rx_state_ = MAC_IDLE;
00521         if (!p)  
00522                 return; // No packet to free or send up.
00523 
00524         hdr_mac* mh = HDR_MAC(p);
00525         int dst = this->hdr_dst((char*)mh); // mac destination address
00526         int src = this->hdr_src((char*)mh); // mac source address
00527         
00528         if (((u_int32_t)dst != MAC_BROADCAST) && (dst != index_) && 
00529             (src != index_)) {
00530                 drop(p); // Packet not intended for our station
00531                 return;
00532         } 
00533         if (src == index_) {
00534                 // received our own packet: free up transmit side, drop this
00535                 // packet, and perform callback to queue which is blocked
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_); // Free the packet cached for retransmission
00544                 resume(p);
00545         } else {
00546                 // wait for processing delay (delay_) to send packet upwards 
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         // if number of retransmissions is within limit, do exponential backoff
00556         // else drop the packet and resume
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                 // trace the dropped packet
00565                 if (drop_trace_ && trace_drops_)
00566                         drop_trace_->traceonly(snd_pkt_);
00567                 resume(snd_pkt_);
00568         }
00569 }
00570 
00571 
00572 /*==========================================================================*/
00573 /*
00574  * _SatPhy
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                 // it is possible for routing to change (and a channel to
00591                 // be disconnected) while a packet
00592                 // is moving down the stack.  Therefore, just log a drop
00593                 // if there is no channel
00594                 if ( ((SatNode*) head()->node())->trace() )
00595                         ((SatNode*) head()->node())->trace()->traceonly(p);
00596                 Packet::free(p);
00597         }
00598 }
00599 
00600 // Note that this doesn't do that much right now.  If you want to incorporate
00601 // an error model, you could insert a "propagation" object like in the
00602 // wireless case.
00603 int SatPhy::sendUp(Packet * /* pkt */)
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                 // change direction and send to uptarget (which is
00635                 // really a Phy_tx that is also a RepeaterPhy)
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  * _SatChannel
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 // This is a helper function that attaches a SatChannel to a Phy
00681 void SatChannel::add_interface(Phy* phy_)
00682 {
00683         phy_->setchnl(this); // Attach phy to this channel
00684         phy_->insertchnl(&ifhead_); // Add phy_ to list of phys on the channel
00685 }
00686 
00687 // Remove a phy from a channel
00688 void SatChannel::remove_interface(Phy* phy_)
00689 {
00690         phy_->setchnl(NULL); // Set phy_'s channel pointer to NULL
00691         phy_->removechnl(); // Remove phy_ to list of phys on the channel
00692 }
00693 
00694 // Search for destination mac address on this channel.  Look through list
00695 // of phys on the channel.  If the channel connects to a geo repeater, look
00696 // for the destination on the corresponding downlink channel.  
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 

Generated on Tue Apr 20 12:14:31 2004 for NS2.26SourcesOriginal by doxygen 1.3.3