00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef lint
00038 static const char rcsid[] =
00039 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/satellite/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
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
00113
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
00132
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;
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
00160
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;
00169 remote_phy_ = schan_->ifhead_.lh_first;
00170 if (remote_phy_ == 0) {
00171
00172
00173
00174
00175
00176
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
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
00202
00203
00204
00205
00206
00207
00208 int TermLinkHandoffMgr::handoff()
00209 {
00210 coordinate sat_coord, earth_coord;
00211 SatLinkHead* slhp;
00212 SatNode *peer_;
00213 SatNode *best_peer_;
00214 Node *nodep;
00215 PolarSatPosition *nextpos_;
00216 int link_changes_flag_ = FALSE;
00217 int restart_timer_flag_ = FALSE;
00218 double found_elev_ = 0;
00219 double best_found_elev_ = 0;
00220 double mask_ = DEG_TO_RAD(TermLinkHandoffMgr::elevation_mask_);
00221
00222 earth_coord = ((SatNode *)node_)->position()->coord();
00223
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
00235
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
00245
00246
00247 slhp->phy_rx()->removechnl();
00248
00249 slhp->phy_tx()->setchnl(0);
00250 slhp->phy_rx()->setchnl(0);
00251
00252 if (SatRouteObject::instance().wiredRouting()) {
00253 Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", slhp->phy_tx()->node()->address(), peer_->address());
00254
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
00261
00262
00263
00264
00265
00266 if (peer_) {
00267
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
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
00305 slhp->phy_tx()->setchnl(peer_->uplink());
00306
00307
00308 slhp->phy_rx()->setchnl(peer_->downlink());
00309
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
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
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
00346
00347
00348
00349
00350
00351
00352
00353
00354
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;
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
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;
00383
00384
00385
00386
00387
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
00398
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
00413
00414
00415
00416
00417 peer_slhp->phy_rx()->removechnl();
00418 peer_slhp->phy_tx()->setchnl(0);
00419 peer_slhp->phy_rx()->setchnl(0);
00420
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
00429 if (SatRouteObject::instance().wiredRouting()) {
00430
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
00439 peer_ = peer_next_;
00440 peer_slhp = peer_next_slhp;
00441 peer_coord_ = peer_->position()->coord();
00442 }
00443
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
00450
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
00457
00458 link_down_flag_ |= !(SatGeometry::are_satellites_mutually_visible(peer_coord_, local_coord_));
00459
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
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
00478
00479
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
00497 slhp->linkup_ = FALSE;
00498 peer_slhp->linkup_ = FALSE;
00499 link_changes_flag_ = TRUE;
00500
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 }