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.11 2005/08/22 05:08:34 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_ = 0;
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_ > 0.0) {
00297 assert (best_peer_ != 0);
00298 peer_ = best_peer_;
00299 found_elev_ = best_found_elev_;
00300 }
00301 }
00302 if (found_elev_) {
00303 slhp->linkup_ = TRUE;
00304 link_changes_flag_ = TRUE;
00305
00306 slhp->phy_tx()->setchnl(peer_->uplink());
00307
00308
00309 slhp->phy_rx()->setchnl(peer_->downlink());
00310
00311 slhp->phy_rx()->insertchnl(&(peer_->downlink()->ifhead_));
00312 }
00313 }
00314 }
00315 if (link_changes_flag_) {
00316 SatRouteObject::instance().recompute();
00317 }
00318 if (restart_timer_flag_) {
00319
00320 if (handoff_randomization_) {
00321 timer_.resched(term_handoff_int_ +
00322 handoff_rng_.uniform(-1 * term_handoff_int_/2,
00323 term_handoff_int_/2));
00324 } else
00325 timer_.resched(term_handoff_int_);
00326 }
00327 return link_changes_flag_;
00328 }
00329
00331
00333
00334 double SatLinkHandoffMgr::latitude_threshold_ = 0;
00335 double SatLinkHandoffMgr::longitude_threshold_ = 0;
00336 int SatLinkHandoffMgr::sat_handoff_int_ = 10;
00337
00338 SatLinkHandoffMgr::SatLinkHandoffMgr() : timer_(this)
00339 {
00340 bind("sat_handoff_int_", &sat_handoff_int_);
00341 bind("latitude_threshold_", &latitude_threshold_);
00342 bind("longitude_threshold_", &longitude_threshold_);
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 int SatLinkHandoffMgr::handoff()
00358 {
00359 SatLinkHead *slhp, *peer_slhp, *peer_next_slhp;
00360 SatNode *local_, *peer_, *peer_next_;
00361 PolarSatPosition *pos_, *peer_pos_, *peer_next_pos_;
00362 double dist_to_peer, dist_to_next;
00363 Channel *tx_channel_, *rx_channel_;
00364 double sat_latitude_, sat_longitude_, peer_latitude_, peer_longitude_;
00365 int link_down_flag_;
00366 double lat_threshold_ = DEG_TO_RAD(latitude_threshold_);
00367 double cross_long_threshold_ = DEG_TO_RAD(longitude_threshold_);
00368 int link_changes_flag_ = FALSE;
00369 coordinate local_coord_, peer_coord_;
00370
00371 local_ = (SatNode*) node_;
00372 local_coord_ = local_->position()->coord();
00373 sat_latitude_ = SatGeometry::get_latitude(local_->position()->coord());
00374 sat_longitude_= SatGeometry::get_longitude(local_->position()->coord());
00375
00376
00377 for (slhp = (SatLinkHead*) local_->linklisthead().lh_first; slhp;
00378 slhp = (SatLinkHead*) slhp->nextlinkhead() ) {
00379 if (slhp->type() != LINK_ISL_CROSSSEAM)
00380 continue;
00381 peer_ = get_peer(slhp);
00382 if (peer_ == 0)
00383 continue;
00384
00385
00386
00387
00388
00389 pos_ = (PolarSatPosition*)slhp->node()->position();
00390 peer_slhp = get_peer_linkhead(slhp);
00391 peer_pos_ = (PolarSatPosition*) peer_->position();
00392 peer_coord_ = peer_pos_->coord();
00393 if (fabs(sat_latitude_) > lat_threshold_)
00394 link_down_flag_ = TRUE;
00395 else
00396 link_down_flag_ = FALSE;
00397 if (peer_pos_->plane() < pos_->plane()) {
00398
00399
00400 break;
00401 }
00402 peer_next_pos_ = peer_pos_->next();
00403 if (!peer_next_pos_) {
00404 printf("Error: crossseam handoffs require ");
00405 printf("setting the ``next'' field\n");
00406 exit(1);
00407 }
00408 peer_next_ = (SatNode*) peer_next_pos_->node();
00409 dist_to_peer = SatGeometry::distance(peer_coord_, local_coord_);
00410 dist_to_next = SatGeometry::distance(peer_next_pos_->coord(),
00411 local_coord_);
00412 if (dist_to_next < dist_to_peer) {
00413
00414
00415
00416
00417
00418 peer_slhp->phy_rx()->removechnl();
00419 peer_slhp->phy_tx()->setchnl(0);
00420 peer_slhp->phy_rx()->setchnl(0);
00421
00422 peer_next_slhp = get_peer_next_linkhead(peer_next_);
00423 tx_channel_ = slhp->phy_tx()->channel();
00424 rx_channel_ = slhp->phy_rx()->channel();
00425 peer_next_slhp->phy_tx()->setchnl(rx_channel_);
00426 peer_next_slhp->phy_rx()->setchnl(tx_channel_);
00427 peer_next_slhp->phy_rx()->insertchnl(&(tx_channel_->ifhead_));
00428 link_changes_flag_ = TRUE;
00429
00430 if (SatRouteObject::instance().wiredRouting()) {
00431
00432 if (slhp->linkup_) {
00433 Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", slhp->phy_tx()->node()->address(), peer_->address());
00434 }
00435 if (peer_slhp->linkup_) {
00436 Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", peer_->address(), slhp->phy_tx()->node()->address());
00437 }
00438 }
00439
00440 peer_ = peer_next_;
00441 peer_slhp = peer_next_slhp;
00442 peer_coord_ = peer_->position()->coord();
00443 }
00444
00445 peer_latitude_ =
00446 SatGeometry::get_latitude(peer_coord_);
00447 peer_longitude_ = SatGeometry::get_longitude(peer_coord_);
00448 if (fabs(peer_latitude_) > lat_threshold_)
00449 link_down_flag_ = TRUE;
00450
00451
00452 if ((fabs(peer_longitude_ - sat_longitude_) <
00453 cross_long_threshold_) ||
00454 fabs(peer_longitude_ - sat_longitude_) >
00455 (2 * PI - cross_long_threshold_))
00456 link_down_flag_ = TRUE;
00457
00458
00459 link_down_flag_ |= !(SatGeometry::are_satellites_mutually_visible(peer_coord_, local_coord_));
00460
00461 if ((slhp->linkup_ || peer_slhp->linkup_) && link_down_flag_) {
00462 slhp->linkup_ = FALSE;
00463 peer_slhp->linkup_ = FALSE;
00464 link_changes_flag_ = TRUE;
00465
00466 if (SatRouteObject::instance().wiredRouting()) {
00467 Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", slhp->phy_tx()->node()->address(), peer_->address());
00468 Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", peer_->address(), slhp->phy_tx()->node()->address());
00469 }
00470 } else if ((!slhp->linkup_ || !peer_slhp->linkup_) &&
00471 !link_down_flag_) {
00472 slhp->linkup_ = TRUE;
00473 peer_slhp->linkup_ = TRUE;
00474 link_changes_flag_ = TRUE;
00475 }
00476 }
00477
00478
00479
00480
00481 for (slhp = (SatLinkHead*) local_->linklisthead().lh_first; slhp;
00482 slhp = (SatLinkHead*) slhp->nextlinkhead() ) {
00483 if (slhp->type() != LINK_ISL_INTERPLANE)
00484 continue;
00485 if (fabs(sat_latitude_) > lat_threshold_)
00486 link_down_flag_ = TRUE;
00487 else
00488 link_down_flag_ = FALSE;
00489 peer_ = get_peer(slhp);
00490 peer_slhp = get_peer_linkhead(slhp);
00491 peer_coord_ = peer_->position()->coord();
00492 peer_latitude_ = SatGeometry::get_latitude(peer_coord_);
00493 if (fabs(peer_latitude_) > lat_threshold_)
00494 link_down_flag_ = TRUE;
00495 link_down_flag_ |= !(SatGeometry::are_satellites_mutually_visible(peer_coord_, local_coord_));
00496 if (slhp->linkup_ && link_down_flag_) {
00497
00498 slhp->linkup_ = FALSE;
00499 peer_slhp->linkup_ = FALSE;
00500 link_changes_flag_ = TRUE;
00501
00502 if (SatRouteObject::instance().wiredRouting()) {
00503 Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", slhp->phy_tx()->node()->address(), peer_->address());
00504 Tcl::instance().evalf("[Simulator instance] sat_link_destroy %d %d", peer_->address(), slhp->phy_tx()->node()->address());
00505 }
00506 } else if (!slhp->linkup_ && !link_down_flag_) {
00507 slhp->linkup_ = TRUE;
00508 peer_slhp->linkup_ = TRUE;
00509 link_changes_flag_ = TRUE;
00510 }
00511 }
00512 if (link_changes_flag_) {
00513 SatRouteObject::instance().recompute();
00514 }
00515 if (handoff_randomization_) {
00516 timer_.resched(sat_handoff_int_ +
00517 handoff_rng_.uniform(-1 * sat_handoff_int_/2,
00518 sat_handoff_int_/2));
00519 } else
00520 timer_.resched(sat_handoff_int_);
00521 return link_changes_flag_;
00522 }