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

sathandoff.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/sathandoff.cc,v 1.10 2001/11/06 06:21:47 tomh Exp $";
00040 #endif
00041 
00042 #include "random.h"
00043 #include "sathandoff.h"
00044 #include "satlink.h"
00045 #include "satroute.h"
00046 #include "satposition.h"
00047 #include "satnode.h"
00048 #include "satgeometry.h"
00049 #include <math.h>
00050 
00051 
00052 static class LinkHandoffMgrClass : public TclClass {
00053 public:
00054         LinkHandoffMgrClass() : TclClass("HandoffManager") {}
00055         TclObject* create(int, const char*const*) {
00056                 return (new LinkHandoffMgr());
00057         }
00058 } class_link_handoff_manager;
00059 
00060 static class SatLinkHandoffMgrClass : public TclClass {
00061 public:
00062         SatLinkHandoffMgrClass() : TclClass("HandoffManager/Sat") {}
00063         TclObject* create(int, const char*const*) {
00064                 return (new SatLinkHandoffMgr());
00065         }
00066 } class_sat_link_handoff_manager;
00067 
00068 static class TermLinkHandoffMgrClass : public TclClass {
00069 public:
00070         TermLinkHandoffMgrClass() : TclClass("HandoffManager/Term") {}
00071         TclObject* create(int, const char*const*) {
00072                 return (new TermLinkHandoffMgr());
00073         }
00074 } class_term_link_handoff_manager;
00075 
00076 void SatHandoffTimer::expire(Event*)
00077 {                           
00078         a_->handoff();  
00079 }                               
00080 
00081 void TermHandoffTimer::expire(Event*)
00082 {                           
00083         a_->handoff();  
00084 }                               
00085 
00087 // class LinkHandoffMgr
00089 
00090 RNG LinkHandoffMgr::handoff_rng_;
00091 int LinkHandoffMgr::handoff_randomization_ = 0;
00092 
00093 LinkHandoffMgr::LinkHandoffMgr()
00094 {
00095         bind_bool("handoff_randomization_", &handoff_randomization_);
00096 }
00097 
00098 int LinkHandoffMgr::command(int argc, const char*const* argv)
00099 {
00100         if (argc == 2) {
00101         } else if (argc == 3) {
00102                 if(strcmp(argv[1], "setnode") == 0) {
00103                         node_ = (Node*) TclObject::lookup(argv[2]);
00104                         if (node_ == 0)
00105                                 return TCL_ERROR;
00106                         return TCL_OK;
00107                 }
00108         }
00109         return (TclObject::command(argc, argv));
00110 }
00111 
00112 // Each crossseam satellite will have two net stacks-- at most one will
00113 // be occupied.  This procedure finds an unoccupied stack on the node.
00114 SatLinkHead* LinkHandoffMgr::get_peer_next_linkhead(SatNode* np)
00115 {
00116         LinkHead* lhp;
00117         SatLinkHead* slhp;
00118         for (lhp = np->linklisthead().lh_first; lhp; 
00119             lhp = lhp->nextlinkhead() ) {
00120                 slhp = (SatLinkHead*) lhp;
00121                 if (slhp->type() == LINK_ISL_CROSSSEAM) {
00122                         if (!slhp->phy_tx()->channel() && 
00123                             !slhp->phy_rx()->channel() ) 
00124                                 return slhp;
00125                 }
00126         }
00127         printf("Error, couldn't find an empty crossseam stack for handoff\n");
00128         return 0;
00129 }
00130 
00131 // This helper function assumes that the channel to which the link interface
00132 // is attached has one peer node (i.e., no other receive infs on channel)
00133 SatLinkHead* LinkHandoffMgr::get_peer_linkhead(SatLinkHead* slhp)
00134 {
00135         SatChannel *schan_;
00136         Phy *remote_phy_;
00137         Node *remote_node_;
00138 
00139         schan_ = (SatChannel*) slhp->phy_tx()->channel();
00140         if (schan_ == 0) {
00141                 printf("Error:  get_peer_linkhead called for a non-");
00142                 printf("connected link on node %d\n", slhp->node()->address());
00143                 return 0; // Link is not currently connected
00144         }
00145         remote_phy_ = schan_->ifhead_.lh_first; 
00146         if (remote_phy_ == 0) {
00147                 printf("Error:  node %d's tx phy ", slhp->node()->address());
00148                 printf("connected to channel with no receivers\n");
00149                 return 0;
00150         }
00151         remote_node_ = remote_phy_->head()->node();
00152         if (remote_phy_->nextchnl()) {
00153                 printf("Error:  This ISL channel has more than one target\n");
00154                 return 0;
00155         }
00156         return ( (SatLinkHead*) remote_phy_->head());
00157 }
00158 
00159 // This helper function assumes that the channel to which the link interface
00160 // is attached has one peer node (i.e., no other receive infs on channel)
00161 SatNode* LinkHandoffMgr::get_peer(SatLinkHead* slhp)
00162 {
00163         SatChannel *schan_;
00164         Phy *remote_phy_;
00165 
00166         schan_ = (SatChannel*) slhp->phy_tx()->channel();
00167         if (schan_ == 0)
00168                 return 0; // Link is not currently connected
00169         remote_phy_ = schan_->ifhead_.lh_first; 
00170         if (remote_phy_ == 0) {
00171                 // this is not an error as far as satellite GSL endpoints
00172                 // appear to be concerned.
00173                 // Commented out for drawing GSL links in dumpSats()
00174                 // in satnode.cc
00175                 // printf("Error:  node %d's tx phy ", slhp->node()->address());
00176                 // printf("connected to channel with no receivers\n");
00177                 return 0;
00178         }
00179         if (remote_phy_->nextchnl()) {
00180                 printf("Error:  This ISL channel has more than one target\n");
00181                 return 0;
00182         }
00183         
00184         return ( (SatNode*) remote_phy_->head()->node());
00185 }
00186 
00188 // class TermLinkHandoffMgr
00190 
00191 double TermLinkHandoffMgr::elevation_mask_ = 0;
00192 int TermLinkHandoffMgr::term_handoff_int_ = 10;
00193 
00194 TermLinkHandoffMgr::TermLinkHandoffMgr() : timer_(this)
00195 {
00196         bind("elevation_mask_", &elevation_mask_);
00197         bind("term_handoff_int_", &term_handoff_int_);
00198 }
00199 
00200 // 
00201 // This is called each time the node checks to see if its link to a
00202 // polar satellite needs to be handed off.  
00203 // There are two cases:
00204 //     i) current link is up; check to see if it stays up or is handed off
00205 //     ii) current link is down; check to see if it can go up
00206 // If there are any changes, call for rerouting.  Finally, restart the timer. 
00207 //
00208 int TermLinkHandoffMgr::handoff()
00209 {
00210         coordinate sat_coord, earth_coord;
00211         SatLinkHead* slhp;
00212         SatNode *peer_; // Polar satellite at opposite end of the GSL
00213         SatNode *best_peer_; // Best found peer for handoff
00214         Node *nodep;  // Pointer used in searching the list of nodes
00215         PolarSatPosition *nextpos_;
00216         int link_changes_flag_ = FALSE; // Flag indicating change took place 
00217         int restart_timer_flag_ = FALSE; // Restart timer only if polar links
00218         double found_elev_ = 0;  //``Flag'' indicates whether handoff can occur 
00219         double best_found_elev_ = 0; 
00220         double mask_ = DEG_TO_RAD(TermLinkHandoffMgr::elevation_mask_);
00221 
00222         earth_coord = ((SatNode *)node_)->position()->coord();
00223         // Traverse the linked list of link interfaces
00224         for (slhp = (SatLinkHead*) node_->linklisthead().lh_first; slhp; 
00225             slhp = (SatLinkHead*) slhp->nextlinkhead() ) {
00226                 if (slhp->type() == LINK_GSL_GEO || 
00227                     slhp->type() == LINK_GENERIC)
00228                         continue;
00229                 if (slhp->type() != LINK_GSL_POLAR) {
00230                         printf("Error: Terminal link type ");
00231                         printf("not valid %d NOW %f\n", slhp->type(), NOW);
00232                         exit(1);
00233                 }
00234                 // The link is a GSL_POLAR link-- should be one receive 
00235                 // interface on it
00236                 restart_timer_flag_ = TRUE;
00237                 peer_ = get_peer(slhp);
00238                 if (peer_) {
00239                         sat_coord = peer_->position()->coord();
00240                         if (!SatGeometry::check_elevation(sat_coord, 
00241                             earth_coord, mask_) && slhp->linkup_) {
00242                                 slhp->linkup_ = FALSE;
00243                                 link_changes_flag_ = TRUE;
00244                                 // Detach receive link interface from channel
00245                                 // Next line removes phy from linked list
00246                                 //   of interfaces attached to channel
00247                                 slhp->phy_rx()->removechnl();
00248                                 // Set our channel pointers to NULL
00249                                 slhp->phy_tx()->setchnl(0);
00250                                 slhp->phy_rx()->setchnl(0);
00251                                 // wired-satellite integration
00252                                 if (SatRouteObject::instance().wiredRouting()) {
00253                                         Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", slhp->phy_tx()->node()->address(), peer_->address());
00254                                         // Must do this bidirectionally
00255                                         Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", peer_->address(), slhp->phy_tx()->node()->address());
00256                                 }
00257                         }
00258                 }
00259                 if (!slhp->linkup_) {
00260                         // If link is down, see if we can use another satellite
00261                         // 
00262                         // As an optimization, first check the next satellite 
00263                         // coming over the horizon.  Next, consider all 
00264                         // remaining satellites.
00265                         // 
00266                         if (peer_) {
00267                                 // Next satellite
00268                                 nextpos_ = ((PolarSatPosition*) 
00269                                     peer_->position())->next();
00270                                 if (nextpos_) {
00271                                         sat_coord = nextpos_->coord();
00272                                         found_elev_ = SatGeometry::check_elevation(sat_coord, earth_coord, mask_);
00273                                         if (found_elev_)
00274                                                 peer_ = (SatNode*) nextpos_->node();
00275                                 }
00276                         }
00277                         // Next, check all remaining satellites if not found
00278                         if (!found_elev_) {
00279                                 for (nodep=Node::nodehead_.lh_first; nodep;
00280                                     nodep = nodep->nextnode()) {
00281                                         if (!SatNode::IsASatNode(nodep->address()))
00282                                                 continue;
00283                                         peer_ = (SatNode*) nodep;
00284                                         if (peer_->position() && 
00285                                             (peer_->position()->type() != 
00286                                             POSITION_SAT_POLAR))
00287                                                     continue;
00288                                         sat_coord = 
00289                                             peer_->position()->coord();
00290                                         found_elev_ = SatGeometry::check_elevation(sat_coord, earth_coord, mask_);
00291                                         if (found_elev_ > best_found_elev_) {
00292                                             best_peer_ = peer_;
00293                                             best_found_elev_ = found_elev_;
00294                                         }
00295                                 }
00296                                 if (best_found_elev_) {
00297                                         peer_ = best_peer_;
00298                                         found_elev_ = best_found_elev_;
00299                                 }
00300                         }
00301                         if (found_elev_) {
00302                                 slhp->linkup_ = TRUE;
00303                                 link_changes_flag_ = TRUE;
00304                                 // Point slhp->phy_tx to peer_'s inlink
00305                                 slhp->phy_tx()->setchnl(peer_->uplink());
00306                                 // Point slhp->phy_rx to peer_'s outlink and
00307                                 // add phy_rx to the channels list of phy's
00308                                 slhp->phy_rx()->setchnl(peer_->downlink());
00309                                 // Add phy to channel's linked list of i/fces
00310                                 slhp->phy_rx()->insertchnl(&(peer_->downlink()->ifhead_));
00311                         }
00312                 }
00313         }
00314         if (link_changes_flag_) { 
00315                 SatRouteObject::instance().recompute();
00316         }
00317         if (restart_timer_flag_) {
00318                 // If we don't have polar GSLs, don't reset the timer
00319                 if (handoff_randomization_) {
00320                         timer_.resched(term_handoff_int_ + 
00321                             handoff_rng_.uniform(-1 * term_handoff_int_/2, 
00322                             term_handoff_int_/2));
00323                 } else
00324                         timer_.resched(term_handoff_int_);
00325         }
00326         return link_changes_flag_;
00327 }
00328 
00330 // class SatLinkHandoffMgr
00332 
00333 double SatLinkHandoffMgr::latitude_threshold_ = 0;
00334 double SatLinkHandoffMgr::longitude_threshold_ = 0;
00335 int SatLinkHandoffMgr::sat_handoff_int_ = 10;
00336 
00337 SatLinkHandoffMgr::SatLinkHandoffMgr() : timer_(this)
00338 {
00339         bind("sat_handoff_int_", &sat_handoff_int_);
00340         bind("latitude_threshold_", &latitude_threshold_);
00341         bind("longitude_threshold_", &longitude_threshold_);
00342 }
00343 
00344 //
00345 // This function is responsible for activating, deactivating, and handing off
00346 // satellite ISLs.  If the ISL is an intraplane link, 
00347 // do nothing.  If the ISL is an interplane link, it will be taken down
00348 // when _either_ of the connected satellites are above lat_threshold_ 
00349 // degrees, and brought back up when _both_ satellites move below 
00350 // lat_threshold_ again.  If an ISL is a cross-seam link, it must also be 
00351 // handed off periodically while the satellite is below lat_threshold_.  
00352 // 
00353 // Finally, optimizations that avoid going through the linked lists unless 
00354 // the satellite is ``close'' to lat_threshold_ are employed.
00355 //
00356 int SatLinkHandoffMgr::handoff()
00357 {
00358         SatLinkHead *slhp, *peer_slhp, *peer_next_slhp;
00359         SatNode *local_, *peer_, *peer_next_; 
00360         PolarSatPosition *pos_, *peer_pos_, *peer_next_pos_;
00361         double dist_to_peer, dist_to_next;
00362         Channel *tx_channel_, *rx_channel_;
00363         double sat_latitude_, sat_longitude_, peer_latitude_, peer_longitude_;  
00364         int link_down_flag_;
00365         double lat_threshold_ = DEG_TO_RAD(latitude_threshold_);
00366         double cross_long_threshold_ = DEG_TO_RAD(longitude_threshold_);        
00367         int link_changes_flag_ = FALSE; // Flag indicating change took place 
00368         coordinate local_coord_, peer_coord_;
00369 
00370         local_ = (SatNode*) node_;
00371         local_coord_ = local_->position()->coord();
00372         sat_latitude_ = SatGeometry::get_latitude(local_->position()->coord());
00373         sat_longitude_= SatGeometry::get_longitude(local_->position()->coord());
00374 
00375         // First go through crossseam ISLs to search for handoffs
00376         for (slhp = (SatLinkHead*) local_->linklisthead().lh_first; slhp; 
00377             slhp = (SatLinkHead*) slhp->nextlinkhead() ) {
00378                 if (slhp->type() != LINK_ISL_CROSSSEAM)  
00379                         continue;
00380                 peer_ = get_peer(slhp);
00381                 if (peer_ == 0)
00382                         continue; // this link interface is not attached
00383                 // If this is a crossseam link, first see if the link must 
00384                 // be physically handed off to the next satellite.
00385                 // Handoff is needed if the satellite at the other end of
00386                 // the link is further away than the ``next'' satellite
00387                 // in the peer's orbital plane.
00388                 pos_ = (PolarSatPosition*)slhp->node()->position(); 
00389                 peer_slhp = get_peer_linkhead(slhp);
00390                 peer_pos_ = (PolarSatPosition*) peer_->position();
00391                 peer_coord_ = peer_pos_->coord();
00392                 if (fabs(sat_latitude_) > lat_threshold_)
00393                         link_down_flag_ = TRUE;
00394                 else
00395                         link_down_flag_ = FALSE;
00396                 if (peer_pos_->plane() < pos_->plane()) {
00397                         // Crossseam handoff is controlled by satellites
00398                         // in the plane with a lower index
00399                         break;  
00400                 }
00401                 peer_next_pos_ = peer_pos_->next();
00402                 if (!peer_next_pos_) {
00403                         printf("Error:  crossseam handoffs require ");
00404                         printf("setting the ``next'' field\n");
00405                         exit(1);
00406                 }
00407                 peer_next_ = (SatNode*) peer_next_pos_->node();
00408                 dist_to_peer = SatGeometry::distance(peer_coord_, local_coord_);
00409                 dist_to_next = SatGeometry::distance(peer_next_pos_->coord(), 
00410                     local_coord_); 
00411                 if (dist_to_next < dist_to_peer) {
00412                         // Handoff -- the "next" satellite should have a 
00413                         // currently unused network stack.  Find this 
00414                         // unused stack and handoff the channels to it.
00415                         // 
00416                         // Remove peer's tx/rx interface from channel
00417                         peer_slhp->phy_rx()->removechnl();
00418                         peer_slhp->phy_tx()->setchnl(0);
00419                         peer_slhp->phy_rx()->setchnl(0);
00420                         // Add peer_next's tx/rx interfaces to our channels
00421                         peer_next_slhp = get_peer_next_linkhead(peer_next_);
00422                         tx_channel_ = slhp->phy_tx()->channel();
00423                         rx_channel_ = slhp->phy_rx()->channel();
00424                         peer_next_slhp->phy_tx()->setchnl(rx_channel_);
00425                         peer_next_slhp->phy_rx()->setchnl(tx_channel_);
00426                         peer_next_slhp->phy_rx()->insertchnl(&(tx_channel_->ifhead_));
00427                         link_changes_flag_ = TRUE; 
00428                         // wired-satellite integration
00429                         if (SatRouteObject::instance().wiredRouting()) {
00430                                 // Check if link is up first before deleting
00431                                 if (slhp->linkup_) { 
00432                                         Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", slhp->phy_tx()->node()->address(), peer_->address());
00433                                 }
00434                                 if (peer_slhp->linkup_) { 
00435                                         Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", peer_->address(), slhp->phy_tx()->node()->address());
00436                                 }
00437                         }
00438                         // Now reset the peer_ variables to point to next
00439                         peer_ = peer_next_;
00440                         peer_slhp = peer_next_slhp;
00441                         peer_coord_ = peer_->position()->coord();
00442                 }
00443                 // Next, see if the link needs to be taken down.
00444                 peer_latitude_ = 
00445                     SatGeometry::get_latitude(peer_coord_);
00446                 peer_longitude_ = SatGeometry::get_longitude(peer_coord_);
00447                 if (fabs(peer_latitude_) > lat_threshold_)
00448                         link_down_flag_ = TRUE;
00449                 // If the two satellites are too close to each other in
00450                 // longitude, the link should be down
00451                 if ((fabs(peer_longitude_ - sat_longitude_) <
00452                     cross_long_threshold_) ||
00453                     fabs(peer_longitude_ - sat_longitude_) >
00454                     (2 * PI - cross_long_threshold_))
00455                         link_down_flag_ = TRUE;
00456                 // Check to see if link grazes atmosphere at an altitude
00457                 // below the atmospheric margin
00458                 link_down_flag_ |= !(SatGeometry::are_satellites_mutually_visible(peer_coord_, local_coord_));
00459                 // Evaluate whether a change in link status is needed
00460                 if ((slhp->linkup_ || peer_slhp->linkup_) && link_down_flag_) {
00461                         slhp->linkup_ = FALSE;
00462                         peer_slhp->linkup_ = FALSE;
00463                         link_changes_flag_ = TRUE;
00464                         // wired-satellite integration
00465                         if (SatRouteObject::instance().wiredRouting()) {
00466                             Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", slhp->phy_tx()->node()->address(), peer_->address());
00467                             Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", peer_->address(), slhp->phy_tx()->node()->address());
00468                         }
00469                 } else if ((!slhp->linkup_  || !peer_slhp->linkup_) && 
00470                     !link_down_flag_) {
00471                         slhp->linkup_ = TRUE;
00472                         peer_slhp->linkup_ = TRUE;
00473                         link_changes_flag_ = TRUE;
00474                 }
00475         }
00476 
00477         // Now, work on interplane ISLs (intraplane ISLs are not handed off)
00478         
00479         // Now search for interplane ISLs
00480         for (slhp = (SatLinkHead*) local_->linklisthead().lh_first; slhp; 
00481             slhp = (SatLinkHead*) slhp->nextlinkhead() ) {
00482                 if (slhp->type() != LINK_ISL_INTERPLANE)  
00483                         continue;
00484                 if (fabs(sat_latitude_) > lat_threshold_)
00485                         link_down_flag_ = TRUE;
00486                 else
00487                         link_down_flag_ = FALSE;
00488                 peer_ = get_peer(slhp);
00489                 peer_slhp = get_peer_linkhead(slhp);
00490                 peer_coord_ = peer_->position()->coord();
00491                 peer_latitude_ = SatGeometry::get_latitude(peer_coord_);
00492                 if (fabs(peer_latitude_) > lat_threshold_)
00493                         link_down_flag_ = TRUE;
00494                 link_down_flag_ |= !(SatGeometry::are_satellites_mutually_visible(peer_coord_, local_coord_));
00495                 if (slhp->linkup_ && link_down_flag_) {
00496                         // Take links down if either satellite at high latitude
00497                         slhp->linkup_ = FALSE;
00498                         peer_slhp->linkup_ = FALSE;
00499                         link_changes_flag_ = TRUE;
00500                         // wired-satellite integration
00501                         if (SatRouteObject::instance().wiredRouting()) {
00502                             Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", slhp->phy_tx()->node()->address(), peer_->address());
00503                             Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", peer_->address(), slhp->phy_tx()->node()->address());
00504                         }                                                       
00505                 } else if (!slhp->linkup_ && !link_down_flag_) {
00506                         slhp->linkup_ = TRUE;
00507                         peer_slhp->linkup_ = TRUE;
00508                         link_changes_flag_ = TRUE;
00509                 }
00510         }
00511         if (link_changes_flag_)  {
00512                 SatRouteObject::instance().recompute();
00513         }
00514         if (handoff_randomization_) {
00515                 timer_.resched(sat_handoff_int_ + 
00516                     handoff_rng_.uniform(-1 * sat_handoff_int_/2, 
00517                     sat_handoff_int_/2));
00518         } else
00519                 timer_.resched(sat_handoff_int_);
00520         return link_changes_flag_;
00521 }

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