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 #include <stdarg.h>
00030 #include <float.h>
00031
00032 #include "landmark.h"
00033 #include <random.h>
00034 #include <cmu-trace.h>
00035 #include <address.h>
00036
00037 static int lm_index = 0;
00038
00039
00040 void
00041 LMNode::copy_tag_list(compr_taglist *taglist)
00042 {
00043 compr_taglist *tags = NULL;
00044 compr_taglist *tag_ptr1, *tag_ptr2;
00045
00046
00047 if(tag_list_) {
00048 tag_ptr1 = tag_list_;
00049 while(tag_ptr1) {
00050 tag_ptr2 = tag_ptr1;
00051 tag_ptr1 = tag_ptr1->next_;
00052 delete tag_ptr2;
00053 }
00054 tag_list_ = NULL;
00055 }
00056
00057
00058 tag_ptr1 = taglist;
00059 while(tag_ptr1) {
00060 if(!tag_list_) {
00061 tag_list_ = new compr_taglist;
00062 tag_ptr2 = tag_list_;
00063 }
00064 else {
00065 tag_ptr2->next_ = new compr_taglist;
00066 tag_ptr2 = tag_ptr2->next_;
00067 }
00068 tag_ptr2->obj_name_ = tag_ptr1->obj_name_;
00069 tag_ptr1 = tag_ptr1->next_;
00070 }
00071 }
00072
00073
00074
00075
00076
00077
00078 inline double
00079 LandmarkAgent::jitter(double max, int be_random_)
00080 {
00081 return (be_random_ ? Random::uniform(max) : 0);
00082 }
00083
00084
00085
00086
00087 inline double
00088 LandmarkAgent::random_timer(double max, int be_random_)
00089 {
00090 return (be_random_ ? rn_->uniform(max) : 0);
00091 }
00092
00093
00094
00095 void
00096 LandmarkAgent::stop()
00097 {
00098 ParentChildrenList *pcl = parent_children_list_, *tmp_pcl;
00099
00100 trace("Node %d: LM Agent going down at time %f",myaddr_,NOW);
00101
00102
00103 if(promo_timer_running_) {
00104 promo_timer_running_ = 0;
00105 promo_timer_->cancel();
00106 }
00107 num_resched_ = 0;
00108 wait_state_ = 0;
00109 total_wait_time_ = 0;
00110
00111
00112 highest_level_ = 0;
00113
00114
00115 while(pcl) {
00116 tmp_pcl = pcl;
00117 pcl = pcl->next_;
00118 delete tmp_pcl;
00119 }
00120 parent_children_list_ = NULL;
00121
00122
00123 node_dead_ = 1;
00124
00125 global_lm_id_ = NO_GLOBAL_LM;
00126 global_lm_level_ = -1;
00127
00128
00129 if(tag_advt_event_->uid_ > 0) {
00130 Scheduler &s = Scheduler::instance();
00131 s.cancel(tag_advt_event_);
00132 }
00133 }
00134
00135
00136
00137
00138
00139 void LandmarkAgent::
00140 trace (char *fmt,...)
00141 {
00142 va_list ap;
00143
00144 if (!tracetarget_)
00145 return;
00146
00147
00148 va_start (ap, fmt);
00149
00150 vsprintf (tracetarget_->buffer (), fmt, ap);
00151 tracetarget_->dump ();
00152
00153 va_end (ap);
00154 }
00155
00156
00157
00158 static class LandmarkClass:public TclClass
00159 {
00160 public:
00161 LandmarkClass ():TclClass ("Agent/landmark")
00162 {
00163 }
00164 TclObject *create (int, const char *const *)
00165 {
00166 return (new LandmarkAgent ());
00167 }
00168 } class_landmark;
00169
00170
00171
00172
00173 LandmarkAgent::LandmarkAgent (): Agent(PT_MESSAGE), promo_start_time_(0), promo_timeout_(50), promo_timeout_decr_(1), promo_timer_running_(0), seqno_(0), highest_level_(0), parent_children_list_(NULL), ll_queue(0), be_random_(1), wait_state_(0), total_wait_time_(0), debug_(1) ,qry_debug_(0)
00174 {
00175
00176 promo_timer_ = new PromotionTimer(this);
00177
00178
00179 num_resched_ = 0;
00180 tag_dbase_ = NULL;
00181 node_ = NULL;
00182
00183 cache_ = 0;
00184 tag_cache_ = new TagCache[MAX_CACHE_ITEMS];
00185 num_cached_items_ = 0;
00186
00187 recent_demotion_msgs_ = new RecentMsgRecord[MAX_DEMOTION_RECORDS];
00188 num_demotion_msgs_ = 0;
00189
00190
00191 update_period_ = 400;
00192 update_timeout_ = update_period_ + 4 * LM_STARTUP_JITTER;
00193
00194 adverts_type_ = FLOOD;
00195 global_lm_ = 0;
00196 global_lm_id_ = NO_GLOBAL_LM;
00197 global_lm_level_ = -1;
00198
00199
00200 rn_ = new RNG(RNG::RAW_SEED_SOURCE,lm_index++);;
00201
00202 for(int i = 0; i < 128; ++i) {
00203 rn_->uniform(200);
00204 }
00205
00206 node_dead_ = 0;
00207
00208 bind ("be_random_", &be_random_);
00209
00210 bind ("debug_", &debug_);
00211
00212 num_nbrs_ = 0;
00213 nbrs_ = NULL;
00214
00215 tag_mobility_ = new TagMobilityHandler(this);
00216 tag_mobility_event_ = new Event;
00217
00218
00219 tag_rng_ = new RNG(RNG::RAW_SEED_SOURCE,lm_index++);;
00220
00221 for(int i = 0; i < 128; ++i) {
00222 tag_rng_->uniform(200);
00223 }
00224
00225 mobility_period_ = 60;
00226 mobile_tags_ = NULL;
00227
00228 tag_advt_handler_ = new TagAdvtHandler(this);
00229 tag_advt_event_ = new Event;
00230 }
00231
00232
00233
00234
00235 int
00236 LandmarkAgent::CheckDemotionMsg(nsaddr_t id, int level, int origin_time)
00237 {
00238 int i = 0;
00239
00240
00241 for(i = 0; i < num_demotion_msgs_; ++i) {
00242 if(recent_demotion_msgs_[i].id_ == id && recent_demotion_msgs_[i].level_ == level) {
00243 if(recent_demotion_msgs_[i].origin_time_ >= origin_time) {
00244 return(OLD_MESSAGE);
00245 }
00246 else {
00247 recent_demotion_msgs_[i].origin_time_ = origin_time;
00248 return(NEW_ENTRY);
00249 }
00250 }
00251 }
00252
00253 if(num_demotion_msgs_ < MAX_DEMOTION_RECORDS) {
00254 i = num_demotion_msgs_;
00255 ++num_demotion_msgs_;
00256 recent_demotion_msgs_[i].id_ = id;
00257 recent_demotion_msgs_[i].level_ = level;
00258 recent_demotion_msgs_[i].origin_time_ = origin_time;
00259 }
00260 else {
00261
00262 int replace_index = 0;
00263 int least_time = recent_demotion_msgs_[replace_index].origin_time_;
00264 for(i = 0; i < MAX_DEMOTION_RECORDS; ++i) {
00265 if(recent_demotion_msgs_[i].origin_time_ < least_time)
00266 replace_index = i;
00267 }
00268 recent_demotion_msgs_[replace_index].id_ = id;
00269 recent_demotion_msgs_[replace_index].level_ = level;
00270 recent_demotion_msgs_[replace_index].origin_time_ = origin_time;
00271 }
00272 return(NEW_ENTRY);
00273 }
00274
00275
00276
00277
00278 void
00279 ParentChildrenList::UpdateChildLMAddr(nsaddr_t id, int num_lm_addrs, int64_t *lm_addrs)
00280 {
00281 LMNode *potl_ch = NULL;
00282
00283 potl_ch = pchildren_;
00284 while(potl_ch) {
00285 if(potl_ch->id_ == id)
00286 break;
00287 potl_ch = potl_ch->next_;
00288 }
00289
00290 assert(potl_ch);
00291 (potl_ch->lmaddr_)->delete_lm_addrs();
00292 for(int i = 0; i < num_lm_addrs; ++i)
00293 (potl_ch->lmaddr_)->add_lm_addr(lm_addrs[i]);
00294 }
00295
00296
00297
00298
00299 int
00300 ParentChildrenList::UpdatePotlParent(nsaddr_t id, nsaddr_t next_hop, int num_hops, int level, int num_children, int energy, int origin_time, int delete_flag)
00301 {
00302 LMNode *potl_parent, *list_ptr;
00303 double now = Scheduler::instance().clock();
00304
00305 int seqnum = origin_time & 0xFFFF;
00306 origin_time = origin_time >> 16;
00307
00308 assert(num_pparent_ >= 0);
00309
00310
00311 if(delete_flag && !pparent_)
00312 return(ENTRY_NOT_FOUND);
00313
00314
00315
00316
00317
00318 if(pparent_ == NULL) {
00319 pparent_ = new LMNode(id, next_hop, num_hops, level, num_children, energy, origin_time, now);
00320 pparent_->last_upd_seqnum_ = seqnum;
00321 parent_ = pparent_;
00322 ++num_pparent_;
00323 return(NEW_ENTRY);
00324 }
00325
00326 list_ptr = pparent_;
00327 potl_parent = list_ptr;
00328 while(list_ptr != NULL) {
00329 if(list_ptr->id_ == id) {
00330
00331 if(list_ptr->last_upd_origin_time_ > origin_time || (list_ptr->last_upd_origin_time_ == origin_time && list_ptr->last_upd_seqnum_ >= seqnum)) {
00332
00333 if(list_ptr->num_hops_ > num_hops) {
00334 list_ptr->next_hop_ = next_hop;
00335 list_ptr->num_hops_ = num_hops;
00336 return(OLD_ENTRY);
00337 }
00338 return(OLD_MESSAGE);
00339 }
00340 if(!delete_flag) {
00341
00342 if(parent_->num_hops_ > num_hops + 10 || num_hops == 0) {
00343 parent_ = list_ptr;
00344 }
00345 list_ptr->next_hop_ = next_hop;
00346 list_ptr->num_hops_ = num_hops;
00347 list_ptr->level_ = level;
00348 list_ptr->num_children_ = num_children;
00349 list_ptr->energy_ = energy;
00350 list_ptr->last_upd_origin_time_ = origin_time;
00351 list_ptr->last_upd_seqnum_ = seqnum;
00352 list_ptr->last_update_rcvd_ = Scheduler::instance().clock();
00353 }
00354 else {
00355 if(num_pparent_)
00356 --(num_pparent_);
00357
00358 if(pparent_ == list_ptr)
00359 pparent_ = list_ptr->next_;
00360 else
00361 potl_parent->next_ = list_ptr->next_;
00362
00363 if(parent_->id_ == list_ptr->id_)
00364 assert(parent_ == list_ptr);
00365
00366
00367 if(pparent_ == NULL) {
00368 parent_ = NULL;
00369 }
00370 else if(parent_ == list_ptr) {
00371
00372
00373 LMNode *tmp = pparent_;
00374 int best_num_hops = pparent_->num_hops_;
00375 LMNode *best_parent = pparent_;
00376 while(tmp != NULL) {
00377 if(tmp->num_hops_ < best_num_hops) {
00378 best_num_hops = tmp->num_hops_;
00379 best_parent = tmp;
00380 }
00381 tmp = tmp->next_;
00382 }
00383 parent_ = best_parent;
00384 }
00385 delete list_ptr;
00386 }
00387 return(OLD_ENTRY);
00388 }
00389 potl_parent = list_ptr;
00390 list_ptr = list_ptr->next_;
00391 }
00392
00393 if(delete_flag)
00394 return(ENTRY_NOT_FOUND);
00395
00396 potl_parent->next_ = new LMNode(id, next_hop, num_hops, level, num_children, energy, origin_time, now);
00397 (potl_parent->next_)->last_upd_seqnum_ = seqnum;
00398 ++num_pparent_;
00399
00400 if(parent_->num_hops_ > num_hops) {
00401 parent_ = potl_parent->next_;
00402 }
00403 return(NEW_ENTRY);
00404 }
00405
00406
00407
00408
00409 int
00410 ParentChildrenList::UpdatePotlChild(nsaddr_t id, nsaddr_t next_hop, int num_hops, int level, int num_children, int energy, int origin_time, int child_flag, int delete_flag, compr_taglist *taglist)
00411 {
00412 LMNode *potl_child, *list_ptr;
00413 double now = Scheduler::instance().clock();
00414 int new_child = 0;
00415 int tags_changed = 0;
00416 int seqnum = origin_time & 0xFFFF;
00417 origin_time = origin_time >> 16;
00418
00419
00420
00421
00422 if(delete_flag && !pchildren_) {
00423 return(ENTRY_NOT_FOUND);
00424 }
00425
00426 assert(num_potl_children_ >= 0);
00427 assert(num_children_ >= 0);
00428
00429 if(pchildren_ == NULL) {
00430 pchildren_ = new LMNode(id, next_hop, num_hops, level, num_children, energy, origin_time, now);
00431 pchildren_->child_flag_ = child_flag;
00432 pchildren_->last_upd_seqnum_ = seqnum;
00433 if(child_flag == IS_CHILD) ++(num_children_);
00434 if(child_flag != NOT_POTL_CHILD) ++(num_potl_children_);
00435 ++(num_heard_);
00436 pchildren_->copy_tag_list(taglist);
00437 if(child_flag == IS_CHILD)
00438 return(NEW_CHILD);
00439 else
00440 return(NEW_ENTRY);
00441 }
00442
00443 list_ptr = pchildren_;
00444 potl_child = list_ptr;
00445 while(list_ptr != NULL) {
00446 if(list_ptr->id_ == id) {
00447
00448 if(list_ptr->last_upd_origin_time_ > origin_time || (list_ptr->last_upd_origin_time_ == origin_time && list_ptr->last_upd_seqnum_ >= seqnum)) {
00449
00450
00451
00452
00453 if(list_ptr->num_hops_ > num_hops) {
00454 list_ptr->next_hop_ = next_hop;
00455 list_ptr->num_hops_ = num_hops;
00456 return(OLD_ENTRY);
00457 }
00458
00459 return(OLD_MESSAGE);
00460 }
00461 if(!delete_flag) {
00462
00463
00464 if((list_ptr->child_flag_ == NOT_CHILD || list_ptr->child_flag_ == NOT_POTL_CHILD) && (child_flag == IS_CHILD)) {
00465 list_ptr->child_flag_ = child_flag;
00466 ++(num_children_);
00467 new_child = 1;
00468 }
00469 else if((list_ptr->child_flag_ == IS_CHILD) && (child_flag == NOT_CHILD || child_flag == NOT_POTL_CHILD)) {
00470 list_ptr->child_flag_ = child_flag;
00471 --(num_children_);
00472 }
00473 list_ptr->next_hop_ = next_hop;
00474 list_ptr->num_hops_ = num_hops;
00475 list_ptr->level_ = level;
00476 list_ptr->num_children_ = num_children;
00477 list_ptr->energy_ = energy;
00478 list_ptr->last_upd_origin_time_ = origin_time;
00479 list_ptr->last_upd_seqnum_ = seqnum;
00480 list_ptr->last_update_rcvd_ = Scheduler::instance().clock();
00481 if(!a_->compare_tag_lists(list_ptr->tag_list_,-1,taglist,-1)) {
00482 tags_changed = 1;
00483
00484 list_ptr->copy_tag_list(taglist);
00485 }
00486 }
00487 else {
00488 if(pchildren_ == list_ptr)
00489 pchildren_ = list_ptr->next_;
00490 else
00491 potl_child->next_ = list_ptr->next_;
00492
00493 if(list_ptr->child_flag_ == IS_CHILD) --num_children_;
00494 if(list_ptr->child_flag_ != NOT_POTL_CHILD) --num_potl_children_;
00495 --num_heard_;
00496 delete list_ptr;
00497 }
00498 if(new_child)
00499 return(NEW_CHILD);
00500 else if(tags_changed && child_flag == IS_CHILD)
00501 return(OLD_CHILD_TAGS_CHANGED);
00502 else
00503 return(OLD_ENTRY);
00504 }
00505 potl_child = list_ptr;
00506 list_ptr = list_ptr->next_;
00507 }
00508
00509
00510
00511 if(delete_flag) {
00512 return(ENTRY_NOT_FOUND);
00513 }
00514
00515 potl_child->next_ = new LMNode(id, next_hop, num_hops, level, num_children, energy, origin_time, now);
00516 (potl_child->next_)->copy_tag_list(taglist);
00517 (potl_child->next_)->child_flag_ = child_flag;
00518 (potl_child->next_)->last_upd_seqnum_ = seqnum;
00519 if(child_flag == IS_CHILD) ++(num_children_);
00520 if(child_flag != NOT_POTL_CHILD) ++(num_potl_children_);
00521 ++(num_heard_);
00522 if(child_flag == IS_CHILD)
00523 return(NEW_CHILD);
00524 else
00525 return(NEW_ENTRY);
00526 }
00527
00528
00529
00530
00531
00532 void
00533 LandmarkAgent::ProcessHierUpdate(Packet *p)
00534 {
00535 hdr_ip *iph = HDR_IP(p);
00536 hdr_cmn *hdrc = HDR_CMN(p);
00537 Scheduler &s = Scheduler::instance();
00538 double now = s.clock();
00539 int origin_time = 0;
00540 unsigned char *walk;
00541 nsaddr_t origin_id, parent, next_hop;
00542 int i, level, vicinity_radius, num_hops, potl_parent_flag = FALSE;
00543 int action, energy = 0;
00544 nsaddr_t *potl_children;
00545 int num_children = 0;
00546 int num_potl_children = 0;
00547 int num_lm_addrs = 0;
00548 int num_advert_lm_addrs = 0;
00549 int64_t *advert_lm_addrs = NULL;
00550 int64_t *lm_addrs = NULL;
00551
00552
00553 int num_tags = 0;
00554 compr_taglist *adv_tags = NULL, *tag_ptr;
00555 compr_taglist *tag_ptr1, *tag_ptr2;
00556 Packet *newp;
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 walk = p->accessdata();
00568
00569
00570 origin_id = iph->saddr();
00571
00572
00573 if(origin_id == myaddr_) {
00574 Packet::free(p);
00575 return;
00576 }
00577
00578
00579 action = *walk++;
00580
00581 num_advert_lm_addrs = *walk++;
00582 if(num_advert_lm_addrs)
00583 advert_lm_addrs = new int64_t[num_advert_lm_addrs];
00584 for(int j = 0; j < num_advert_lm_addrs; ++j) {
00585 advert_lm_addrs[j] = *walk++;
00586 advert_lm_addrs[j] = (advert_lm_addrs[j] << 8) | *walk++;
00587 advert_lm_addrs[j] = (advert_lm_addrs[j] << 8) | *walk++;
00588 advert_lm_addrs[j] = (advert_lm_addrs[j] << 8) | *walk++;
00589 advert_lm_addrs[j] = (advert_lm_addrs[j] << 8) | *walk++;
00590 advert_lm_addrs[j] = (advert_lm_addrs[j] << 8) | *walk++;
00591 advert_lm_addrs[j] = (advert_lm_addrs[j] << 8) | *walk++;
00592 advert_lm_addrs[j] = (advert_lm_addrs[j] << 8) | *walk++;
00593 }
00594
00595
00596 level = *walk++;
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 energy = *walk++;
00609 energy = (energy << 8) | *walk++;
00610 energy = (energy << 8) | *walk++;
00611 energy = (energy << 8) | *walk++;
00612
00613
00614 next_hop = *walk++;
00615 next_hop = (next_hop << 8) | *walk;
00616
00617
00618 --walk;
00619 (*walk++) = (myaddr_ >> 8) & 0xFF;
00620 (*walk++) = (myaddr_) & 0xFF;
00621
00622
00623 vicinity_radius = *walk++;
00624 vicinity_radius = (vicinity_radius << 8) | *walk++;
00625
00626 num_hops = vicinity_radius - (iph->ttl_ - 1);
00627
00628
00629
00630
00631
00632 origin_time = *walk++;
00633 origin_time = (origin_time << 8) | *walk++;
00634 origin_time = (origin_time << 8) | *walk++;
00635 origin_time = (origin_time << 8) | *walk++;
00636
00637
00638
00639
00640
00641
00642 parent = *walk++;
00643 parent = parent << 8 | *walk++;
00644
00645
00646
00647 if(level > 0 && (action == PERIODIC_ADVERTS || action == GLOBAL_ADVERT || action == UNICAST_ADVERT_CHILD || action == UNICAST_ADVERT_PARENT)) {
00648
00649 num_children = *walk++;
00650 num_children = num_children << 8 | *walk++;
00651
00652
00653 num_potl_children = *walk++;
00654 num_potl_children = num_potl_children << 8 | *walk++;
00655
00656
00657
00658 if(num_potl_children) {
00659 potl_children = new nsaddr_t[num_potl_children];
00660 for(i = 0; i < num_potl_children; ++i) {
00661 potl_children[i] = *walk++;
00662 potl_children[i] = potl_children[i] << 8 | *walk++;
00663 int tmp_num_addrs = *walk++;
00664 if(potl_children[i] == myaddr_) {
00665 potl_parent_flag = TRUE;
00666 num_lm_addrs = tmp_num_addrs;
00667 if(num_lm_addrs) {
00668 lm_addrs = new int64_t[num_lm_addrs];
00669 for(int j = 0; j < num_lm_addrs; ++j) {
00670 lm_addrs[j] = *walk++;
00671 lm_addrs[j] = (lm_addrs[j] << 8) | *walk++;
00672 lm_addrs[j] = (lm_addrs[j] << 8) | *walk++;
00673 lm_addrs[j] = (lm_addrs[j] << 8) | *walk++;
00674 lm_addrs[j] = (lm_addrs[j] << 8) | *walk++;
00675 lm_addrs[j] = (lm_addrs[j] << 8) | *walk++;
00676 lm_addrs[j] = (lm_addrs[j] << 8) | *walk++;
00677 lm_addrs[j] = (lm_addrs[j] << 8) | *walk++;
00678 }
00679 }
00680 }
00681 else
00682 walk = walk + tmp_num_addrs*8;
00683 }
00684 }
00685 }
00686
00687 num_tags = 0;
00688 if(action == PERIODIC_ADVERTS || action == GLOBAL_ADVERT || action == UNICAST_ADVERT_CHILD || action == UNICAST_ADVERT_PARENT) {
00689 num_tags = *walk++;
00690 num_tags = (num_tags << 8) | *walk++;
00691 }
00692
00693
00694 adv_tags = NULL;
00695
00696
00697 if(num_tags && level < highest_level_) {
00698 adv_tags = new compr_taglist;
00699 tag_ptr = adv_tags;
00700 i = 0;
00701 while(i < num_tags) {
00702 if(i) {
00703 tag_ptr->next_ = new compr_taglist;
00704 tag_ptr = tag_ptr->next_;
00705 }
00706 tag_ptr->obj_name_ = *walk++;
00707 tag_ptr->obj_name_ = (tag_ptr->obj_name_ << 8) | *walk++;
00708 tag_ptr->obj_name_ = (tag_ptr->obj_name_ << 8) | *walk++;
00709 tag_ptr->obj_name_ = (tag_ptr->obj_name_ << 8) | *walk++;
00710 ++i;
00711
00712 }
00713 }
00714
00715
00716
00717
00718 ParentChildrenList **pcl1 = NULL;
00719 ParentChildrenList **pcl2 = NULL;
00720 int found1 = FALSE;
00721 int found2 = FALSE;
00722 ParentChildrenList **pcl = &parent_children_list_;
00723
00724
00725 while((*pcl) != NULL) {
00726 if((*pcl)->level_ == (level-1)) {
00727 found1 = TRUE;
00728 pcl1 = pcl;
00729 }
00730 if((*pcl)->level_ == (level+1)) {
00731 found2 = TRUE;
00732 pcl2 = pcl;
00733 }
00734 pcl = &((*pcl)->next_);
00735 }
00736
00737
00738
00739 if(!found1 && level) {
00740 *pcl = new ParentChildrenList(level-1, this);
00741 pcl1 = pcl;
00742 pcl = &((*pcl)->next_);
00743 }
00744
00745 if(!found2) {
00746 *pcl = new ParentChildrenList(level+1, this);
00747 pcl2 = pcl;
00748 pcl = &((*pcl)->next_);
00749 }
00750
00751
00752
00753
00754
00755 int delete_flag = FALSE;
00756 if(action == DEMOTION) delete_flag = TRUE;
00757 int child_flag = NOT_CHILD;
00758 if(parent == myaddr_)
00759 child_flag = IS_CHILD;
00760 else if(action == GLOBAL_ADVERT && num_hops > vicinity_radius)
00761
00762
00763 child_flag = NOT_POTL_CHILD;
00764
00765 int ret_value = (*pcl2)->UpdatePotlChild(origin_id, next_hop, num_hops, level, num_children, energy, origin_time, child_flag, delete_flag,adv_tags);
00766
00767
00768
00769 if(ret_value == OLD_MESSAGE && action != UNICAST_ADVERT_CHILD && action != UNICAST_ADVERT_PARENT) {
00770 if(num_potl_children) delete[] potl_children;
00771 if(num_lm_addrs) delete[] lm_addrs;
00772 if(num_advert_lm_addrs) delete[] advert_lm_addrs;
00773
00774 tag_ptr1 = adv_tags;
00775 while(tag_ptr1) {
00776 tag_ptr2 = tag_ptr1;
00777 tag_ptr1 = tag_ptr1->next_;
00778 delete tag_ptr2;
00779 }
00780 Packet::free(p);
00781 return;
00782 }
00783
00784
00785
00786 if(ret_value == NEW_CHILD || ret_value == OLD_CHILD_TAGS_CHANGED)
00787 SendChangedTagListUpdate(0,level);
00788
00789
00790
00791
00792
00793
00794 if((ret_value == NEW_ENTRY) && (level == highest_level_) && (action == PERIODIC_ADVERTS || action == UNICAST_ADVERT_CHILD || action == UNICAST_ADVERT_PARENT) && (num_hops < radius(level))) {
00795
00796 if(promo_timer_running_ && !wait_state_) {
00797 double resched_time = promo_timeout_ - (now - promo_start_time_) - promo_timeout_decr_;
00798 if(resched_time < 0) resched_time = 0;
00799
00800 promo_timer_->resched(resched_time);
00801 }
00802 }
00803
00804
00805
00806 if(action == DEMOTION) {
00807 (*pcl1)->UpdatePotlParent(origin_id, next_hop, num_hops, level, num_children, energy, origin_time, TRUE);
00808 if(((*pcl1)->parent_ == NULL) && (!promo_timer_running_ || (promo_timer_running_ && wait_state_)) && (highest_level_ == level-1)) {
00809
00810 ParentChildrenList *tmp_pcl = parent_children_list_;
00811 while(tmp_pcl) {
00812 if(tmp_pcl->level_ == level) break;
00813 tmp_pcl = tmp_pcl->next_;
00814 }
00815 assert(tmp_pcl);
00816
00817 num_resched_ = tmp_pcl->num_heard_ - 1;
00818 if(num_resched_) {
00819
00820 if(promo_timer_running_)
00821 promo_timer_->cancel();
00822 promo_timer_running_ = 1;
00823 wait_state_ = 0;
00824 total_wait_time_ = 0;
00825 promo_timeout_ = random_timer(double(CONST_TIMEOUT + PROMO_TIMEOUT_MULTIPLES * radius(level) + MAX_TIMEOUT/((num_resched_+1) * pow(2,highest_level_+1))), be_random_);
00826 trace("Node %d: Promotion timeout after wait period in ProcessHierUpdate: %f", myaddr_,promo_timeout_);
00827 num_resched_ = 0;
00828 promo_start_time_ = s.clock();
00829 promo_timer_->resched(promo_timeout_);
00830 }
00831 else if(!promo_timer_running_) {
00832 double wait_time = PERIODIC_WAIT_TIME;
00833 promo_timer_running_ = 1;
00834 wait_state_ = 1;
00835 total_wait_time_ += wait_time;
00836 trace("Node %d: Entering wait state in ProcessHierUpdate because of no parent: %f", myaddr_,now);
00837 promo_timer_->resched(wait_time);
00838 }
00839 }
00840 }
00841
00842
00843 else if(potl_parent_flag) {
00844 LMNode *old_parent = (*pcl1)->parent_;
00845 (*pcl1)->UpdatePotlParent(origin_id, next_hop, num_hops, level, num_children, energy, origin_time, FALSE);
00846
00847
00848
00849 if((((*pcl1)->parent_)->id_ == origin_id) && (level-1 == highest_level_)) {
00850
00851
00852
00853
00854 ((*pcl1)->mylmaddrs_)->delete_lm_addrs();
00855 assign_lmaddress(lm_addrs, num_lm_addrs, (*pcl1)->level_);
00856 }
00857
00858
00859 int new_advert = 0;
00860
00861 if((*pcl1)->parent_ == old_parent && old_parent) {
00862 if(((*pcl1)->parent_)->id_ != old_parent->id_)
00863 new_advert = 1;
00864 }
00865 else if((*pcl1)->parent_ != old_parent && (*pcl1)->parent_ && old_parent) {
00866 if(((*pcl1)->parent_)->id_ != old_parent->id_)
00867 new_advert = 1;
00868 }
00869 else if((*pcl1)->parent_ != old_parent)
00870 new_advert = 1;
00871
00872
00873 if(new_advert && (level-1 <= highest_level_)) {
00874 newp = makeUpdate((*pcl1), HIER_ADVS, PERIODIC_ADVERTS);
00875 s.schedule(target_,newp,0);
00876 (*pcl1)->last_update_sent_ = now;
00877 }
00878
00879
00880
00881 if((level == (highest_level_ + 1)) && ((*pcl1)->parent_ != NULL)) {
00882 if(promo_timer_running_ && !wait_state_) {
00883 trace("Node %d: Promotion timer cancelled at time %f in ProcessHierUpdate\n",myaddr_,s.clock());
00884 promo_timer_->cancel();
00885 total_wait_time_ = 0;
00886 wait_state_ = 1;
00887 double wait_time = PERIODIC_WAIT_TIME;
00888 total_wait_time_ += wait_time;
00889 promo_timer_->sched(wait_time);
00890 }
00891 }
00892 else if(level > 0 && level == highest_level_) {
00893
00894
00895
00896 pcl = &parent_children_list_;
00897 while((*pcl) != NULL) {
00898 if((*pcl)->level_ == level) {
00899 break;
00900 }
00901 pcl = &((*pcl)->next_);
00902 }
00903 assert(*pcl);
00904
00905 LMNode *lm = (*pcl)->pchildren_;
00906 int is_subset = TRUE;
00907 if((*pcl)->num_potl_children_ > num_potl_children) {
00908 is_subset = FALSE;
00909 lm = NULL;
00910 }
00911
00912 int is_element = FALSE;
00913 while(lm) {
00914 is_element = FALSE;
00915 for(i = 0; i < num_potl_children; ++i)
00916 if(lm->id_ == potl_children[i] && lm->child_flag_ != NOT_POTL_CHILD) {
00917 is_element = TRUE;
00918 break;
00919 }
00920 if(is_element == FALSE && lm->child_flag_ != NOT_POTL_CHILD) {
00921 is_subset = FALSE;
00922 break;
00923 }
00924 lm = lm->next_;
00925 }
00926
00927 if(is_subset == TRUE) {
00928 --(highest_level_);
00929 delete_flag = TRUE;
00930 if((*pcl1)->parent_)
00931 trace("Node %d: Num potl ch %d, Node %d: Num potl ch %d, time %d",myaddr_, (*pcl)->num_potl_children_,origin_id,num_potl_children,(int)now);
00932 trace("Node %d: Parent before demotion: %d, msg from %d at time %f",myaddr_, ((*pcl1)->parent_)->id_,origin_id,now);
00933
00934 int upd_time = (int)now;
00935 upd_time = (upd_time << 16) | ((*pcl1)->seqnum_ & 0xFFFF);
00936 ++((*pcl1)->seqnum_);
00937 (*pcl1)->UpdatePotlParent(myaddr_, 0, 0, 0, 0, 0, upd_time, delete_flag);
00938
00939 if((*pcl1)->parent_)
00940 trace("Node %d: Parent after demotion: %d",myaddr_, ((*pcl1)->parent_)->id_);
00941
00942 upd_time = (int) now;
00943 upd_time = (upd_time << 16) | ((*pcl2)->seqnum_ & 0xFFFF);
00944 ++((*pcl2)->seqnum_);
00945 (*pcl2)->UpdatePotlChild(myaddr_, 0, 0, 0, 0, 0, upd_time, IS_CHILD, delete_flag,NULL);
00946
00947
00948 newp = makeUpdate(*pcl, HIER_ADVS, DEMOTION);
00949 s.schedule(target_, newp, 0);
00950
00951 if(promo_timer_running_ && !wait_state_) {
00952 trace("Node %d: Promotion timer cancelled due to demotion at time %d\n",myaddr_,(int)now);
00953 promo_timer_->cancel();
00954 total_wait_time_ = 0;
00955 wait_state_ = 1;
00956 double wait_time = PERIODIC_WAIT_TIME;
00957 total_wait_time_ += wait_time;
00958 promo_timer_->sched(wait_time);
00959 }
00960 }
00961 }
00962 }
00963
00964
00965
00966 if(ret_value == NEW_ENTRY) {
00967 ParentChildrenList *tmp_pcl = parent_children_list_;
00968 while(tmp_pcl) {
00969
00970 if(tmp_pcl->level_ <= highest_level_ && tmp_pcl->level_ >= level && (now - tmp_pcl->last_update_sent_) > 0.1) {
00971 newp = makeUpdate(tmp_pcl, HIER_ADVS, PERIODIC_ADVERTS);
00972 s.schedule(target_,newp,0);
00973 tmp_pcl->last_update_sent_ = now;
00974 }
00975 tmp_pcl = tmp_pcl->next_;
00976 }
00977 }
00978
00979 if(num_potl_children) delete[] potl_children;
00980 if(num_lm_addrs) delete[] lm_addrs;
00981 if(num_advert_lm_addrs) delete[] advert_lm_addrs;
00982
00983 tag_ptr1 = adv_tags;
00984 while(tag_ptr1) {
00985 tag_ptr2 = tag_ptr1;
00986 tag_ptr1 = tag_ptr1->next_;
00987 delete tag_ptr2;
00988 }
00989
00990
00991 if(action == DEMOTION) {
00992
00993
00994 if(CheckDemotionMsg(origin_id, level, (int)origin_time) == OLD_MESSAGE) {
00995 Packet::free(p);
00996 return;
00997 }
00998 }
00999
01000
01001
01002 if(--iph->ttl_ == 0 && action != GLOBAL_ADVERT) {
01003
01004 Packet::free(p);
01005 return;
01006 }
01007
01008
01009 if((iph->daddr() >> 8) == myaddr_) {
01010
01011 Packet::free(p);
01012 return;
01013 }
01014
01015 if(action == UNICAST_ADVERT_CHILD) {
01016 hdrc->next_hop() = get_next_hop(iph->daddr(),level);
01017
01018
01019 }
01020 else if(action == UNICAST_ADVERT_PARENT) {
01021
01022 hdrc->next_hop() = get_next_hop(iph->daddr(),level+2);
01023 }
01024
01025 assert(hdrc->next_hop() != NO_NEXT_HOP);
01026
01027
01028
01029
01030
01031
01032
01033 hdrc->direction() = hdr_cmn::DOWN;
01034
01035
01036 s.schedule(target_, p, 0);
01037 }
01038
01039
01040
01041
01042 void
01043 LandmarkAgent::assign_lmaddress(int64_t *lmaddr, int num_lm_addrs, int root_level)
01044 {
01045 ParentChildrenList *tmp_pcl, *cur_pcl = NULL, *child_pcl = NULL;
01046 ParentChildrenList *parent_pcl = NULL;
01047 LMNode *pchild;
01048 int i;
01049 int level = root_level;
01050
01051
01052
01053 while(level >= 0) {
01054 tmp_pcl = parent_children_list_;
01055 while(tmp_pcl) {
01056 if(tmp_pcl->level_ == level)
01057 cur_pcl = tmp_pcl;
01058 if(tmp_pcl->level_ == (level-1))
01059 child_pcl = tmp_pcl;
01060 if(tmp_pcl->level_ == (level+1))
01061 parent_pcl = tmp_pcl;
01062 tmp_pcl = tmp_pcl->next_;
01063 }
01064
01065 assert(cur_pcl);
01066 if(level) assert(child_pcl);
01067 assert(parent_pcl);
01068
01069
01070 if(level == root_level) {
01071 (cur_pcl->mylmaddrs_)->delete_lm_addrs();
01072 if(num_lm_addrs) {
01073 for(i = 0; i < num_lm_addrs; ++i) {
01074 (cur_pcl->mylmaddrs_)->add_lm_addr(lmaddr[i]);
01075 }
01076 parent_pcl->UpdateChildLMAddr(myaddr_,num_lm_addrs,lmaddr);
01077 }
01078 }
01079
01080 int num_addrs = 0;
01081 int64_t *assigned_addrs = NULL;
01082 (cur_pcl->mylmaddrs_)->get_lm_addrs(&num_addrs,&assigned_addrs);
01083
01084 if(num_addrs == 0) {
01085 pchild = cur_pcl->pchildren_;
01086 while(pchild) {
01087 if(pchild->child_flag_ == IS_CHILD) {
01088 (pchild->lmaddr_)->delete_lm_addrs();
01089 if(pchild->id_ == myaddr_ && level)
01090 (child_pcl->mylmaddrs_)->delete_lm_addrs();
01091 }
01092 pchild = pchild->next_;
01093 }
01094 }
01095 else if(cur_pcl->num_children_) {
01096
01097 for(i = 0; i < num_addrs; ++i) {
01098 int64_t j = 1;
01099 int64_t addr = assigned_addrs[i] + (j << ((cur_pcl->level_-1)*8));
01100
01101
01102
01103 pchild = cur_pcl->pchildren_;
01104 assert(cur_pcl->num_children_ <= MAX_CHILDREN);
01105
01106 while(pchild) {
01107 if(pchild->child_flag_ == IS_CHILD) {
01108 (pchild->lmaddr_)->delete_lm_addrs();
01109 (pchild->lmaddr_)->add_lm_addr(addr);
01110 if(pchild->id_ == myaddr_ && level) {
01111 (child_pcl->mylmaddrs_)->delete_lm_addrs();
01112 (child_pcl->mylmaddrs_)->add_lm_addr(addr);
01113 }
01114 ++j;
01115 addr = assigned_addrs[i] + (j << ((cur_pcl->level_-1)*8));
01116
01117 assert(j <= MAX_CHILDREN);
01118 }
01119 pchild = pchild->next_;
01120
01121 }
01122 }
01123 }
01124 if(num_addrs) delete[] assigned_addrs;
01125 --level;
01126 }
01127 }
01128
01129
01130
01131
01132 void
01133 LandmarkAgent::periodic_callback(Event *e, int level)
01134 {
01135
01136 Scheduler &s = Scheduler::instance();
01137 double now = Scheduler::instance().clock(), next_update_delay;
01138 int energy = (int)(node_->energy());
01139 int unicast_flag = FALSE, suppress_flag = FALSE;
01140 Packet *newp;
01141 hdr_ip *iph, *new_iph;
01142 hdr_cmn *cmh, *new_cmh;
01143 int action = PERIODIC_ADVERTS, parent_changed = 0, child_changed = 0;
01144 int upd_time = (int) now;
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155 assert(parent_children_list_ != NULL);
01156 ParentChildrenList *pcl = parent_children_list_;
01157 ParentChildrenList *cur_pcl = NULL;
01158 ParentChildrenList *new_pcl = NULL;
01159 ParentChildrenList *pcl1 = NULL;
01160 ParentChildrenList *pcl2 = NULL;
01161
01162
01163 if(highest_level_ < level)
01164 return;
01165
01166 while(pcl != NULL) {
01167 new_pcl = pcl;
01168 if(pcl->level_ == level){
01169 cur_pcl = pcl;
01170 }
01171 if(pcl->level_ == (level - 1)){
01172 pcl1 = pcl;
01173 }
01174 if(pcl->level_ == (level + 1)){
01175 pcl2 = pcl;
01176 }
01177 pcl = pcl->next_;
01178 }
01179
01180 assert(cur_pcl);
01181 if(level)
01182 assert(pcl1);
01183
01184
01185 if(!pcl2) {
01186 new_pcl->next_ = new ParentChildrenList(level+1, this);
01187 pcl2 = new_pcl->next_;
01188 }
01189
01190 assert(pcl2);
01191
01192
01193 LMNode *lmnode = cur_pcl->pparent_;
01194 LMNode *tmp_lmnode;
01195 int delete_flag = TRUE;
01196 LMNode *old_parent = cur_pcl->parent_;
01197 while(lmnode) {
01198
01199 tmp_lmnode = lmnode->next_;
01200 if(((now - lmnode->last_update_rcvd_) > cur_pcl->update_timeout_)) {
01201
01202 upd_time = (int) now;
01203 upd_time = (upd_time << 16) | ((lmnode->last_upd_seqnum_ + 1) & 0xFFFF);
01204 cur_pcl->UpdatePotlParent(lmnode->id_, 0, 0, 0, 0, 0, upd_time, delete_flag);
01205 }
01206 lmnode = tmp_lmnode;
01207 }
01208
01209
01210 if(cur_pcl->parent_ == old_parent && old_parent) {
01211 if((cur_pcl->parent_)->id_ != old_parent->id_)
01212 parent_changed = 1;
01213 }
01214 else if(cur_pcl->parent_ != old_parent && cur_pcl->parent_ && old_parent) {
01215 if((cur_pcl->parent_)->id_ != old_parent->id_)
01216 parent_changed = 1;
01217 }
01218 else if(cur_pcl->parent_ != old_parent)
01219 parent_changed = 1;
01220
01221
01222
01223 lmnode = cur_pcl->pchildren_;
01224 delete_flag = TRUE;
01225 int demotion = FALSE;
01226 while(lmnode) {
01227
01228 tmp_lmnode = lmnode->next_;
01229 if((now - lmnode->last_update_rcvd_) > cur_pcl->update_timeout_) {
01230 if(lmnode->child_flag_ == IS_CHILD)
01231 child_changed = 1;
01232 assert(level && lmnode->id_ != myaddr_);
01233 upd_time = (int) now;
01234 upd_time = (upd_time << 16) | ((lmnode->last_upd_seqnum_ + 1) & 0xFFFF);
01235 cur_pcl->UpdatePotlChild(lmnode->id_, 0, 0, 0, 0, 0, upd_time, lmnode->child_flag_, delete_flag,NULL);
01236 }
01237 lmnode = tmp_lmnode;
01238 }
01239
01240
01241 if(child_changed)
01242 SendChangedTagListUpdate(0,level-1);
01243
01244
01245 if(demotion) {
01246 trace("Node %d: Demotion due to lesser energy than child",myaddr_);
01247 highest_level_ = level - 1;
01248 Packet *p = makeUpdate(cur_pcl, HIER_ADVS, DEMOTION);
01249 s.schedule(target_, p, 0);
01250 }
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261 if(parent_changed && (cur_pcl->parent_ == NULL) && !demotion) {
01262
01263
01264
01265 if(promo_timer_running_ && level <= highest_level_) {
01266 wait_state_ = 0;
01267 total_wait_time_ = 0;
01268 promo_timer_running_ = 0;
01269 promo_timer_->cancel();
01270 }
01271
01272 num_resched_ = pcl2->num_heard_ - 1;
01273 if(num_resched_) {
01274 promo_timer_running_ = 1;
01275 wait_state_ = 0;
01276 total_wait_time_ = 0;
01277 promo_timeout_ = random_timer(double(CONST_TIMEOUT + PROMO_TIMEOUT_MULTIPLES * radius(level+1) + MAX_TIMEOUT/((num_resched_+1) * pow(2,highest_level_+1))), be_random_);
01278 trace("Node %d: Promotion timeout after wait period in periodic_callback: %f", myaddr_,promo_timeout_);
01279 num_resched_ = 0;
01280 promo_start_time_ = s.clock();
01281 promo_timer_->resched(promo_timeout_);
01282 }
01283 else {
01284 double wait_time = PERIODIC_WAIT_TIME;
01285 promo_timer_running_ = 1;
01286 wait_state_ = 1;
01287 total_wait_time_ += wait_time;
01288
01289 promo_timer_->resched(wait_time);
01290 }
01291 }
01292
01293
01294
01295 if(!demotion) {
01296 if(level) {
01297 upd_time = (int) now;
01298 upd_time = (upd_time << 16) | (pcl1->seqnum_ & 0xFFFF);
01299 ++(pcl1->seqnum_);
01300 pcl1->UpdatePotlParent(myaddr_, myaddr_, 0, level, cur_pcl->num_children_, energy, upd_time, FALSE);
01301 }
01302 upd_time = (int) now;
01303 upd_time = (upd_time << 16) | (pcl2->seqnum_ & 0xFFFF);
01304 ++(pcl2->seqnum_);
01305 pcl2->UpdatePotlChild(myaddr_, myaddr_, 0, level, cur_pcl->num_children_, energy, upd_time, IS_CHILD, FALSE,cur_pcl->tag_list_);
01306 }
01307
01308
01309
01310
01311
01312 if(!(cur_pcl->parent_) && (total_wait_time_ >= (2*PERIODIC_WAIT_TIME)) && wait_state_) {
01313 if(adverts_type_ == UNICAST) {
01314 unicast_flag = TRUE;
01315 }
01316 else if(adverts_type_ == SUPPRESS) {
01317 suppress_flag = TRUE;
01318 }
01319
01320
01321
01322 int64_t *lmaddr = new int64_t[1];
01323 lmaddr[0] = 1;
01324 lmaddr[0] = (lmaddr[0] << (cur_pcl->level_ * 8));
01325 int num_lm_addrs = 1;
01326 assign_lmaddress(lmaddr, num_lm_addrs, cur_pcl->level_);
01327
01328
01329 delete[] lmaddr;
01330 if(global_lm_)
01331 action = GLOBAL_ADVERT;
01332 }
01333 else if(cur_pcl->parent_) {
01334 if(adverts_type_ == UNICAST) {
01335 unicast_flag = TRUE;
01336 }
01337 else if(adverts_type_ == SUPPRESS) {
01338 suppress_flag = TRUE;
01339 }
01340 }
01341
01342
01343 if(!demotion && !suppress_flag) {
01344
01345 Packet *p = makeUpdate(cur_pcl, HIER_ADVS, action);
01346 unsigned char *walk;
01347 if(unicast_flag) {
01348 if(level) {
01349
01350 lmnode = cur_pcl->pchildren_;
01351 while(lmnode) {
01352 if(lmnode->id_ != myaddr_) {
01353 newp = p->copy();
01354 new_iph = HDR_IP(newp);
01355 new_cmh = HDR_CMN(newp);
01356 walk = newp->accessdata();
01357
01358
01359 new_iph->daddr() = lmnode->id_ << 8;
01360 new_iph->dport() = ROUTER_PORT;
01361 new_cmh->next_hop() = lmnode->next_hop_;
01362 new_cmh->addr_type() = NS_AF_INET;
01363 if(cur_pcl->level_)
01364 new_cmh->size() = new_cmh->size() - 4 * (cur_pcl->num_potl_children_ - 1);
01365 (*walk) = (UNICAST_ADVERT_CHILD) & 0xFF;
01366 walk++;
01367 int num_addrs = (*walk);
01368 walk += (10 + 8*num_addrs);
01369
01370
01371
01372 (*walk++) = (cur_pcl->seqnum_ >> 24) & 0xFF;
01373 (*walk++) = (cur_pcl->seqnum_ >> 16) & 0xFF;
01374 (*walk++) = (cur_pcl->seqnum_ >> 8) & 0xFF;
01375 (*walk++) = (cur_pcl->seqnum_) & 0xFF;
01376 ++(cur_pcl->seqnum_);
01377
01378 s.schedule(target_,newp,0);
01379 }
01380 lmnode = lmnode->next_;
01381 }
01382 }
01383 if(cur_pcl->parent_) {
01384 if((cur_pcl->parent_)->id_ != myaddr_) {
01385 iph = HDR_IP(p);
01386 cmh = HDR_CMN(p);
01387 walk = p->accessdata();
01388
01389
01390 iph->daddr() = (cur_pcl->parent_)->id_;
01391 iph->dport() = ROUTER_PORT;
01392 cmh->next_hop() = (cur_pcl->parent_)->next_hop_;
01393 cmh->addr_type() = NS_AF_INET;
01394 cmh->size() = cmh->size() - 4 * (cur_pcl->num_potl_children_);
01395
01396 (*walk) = (UNICAST_ADVERT_PARENT) & 0xFF;
01397 walk++;
01398 int num_addrs = (*walk);
01399 walk += (10 + 8*num_addrs);
01400
01401
01402
01403 (*walk++) = (cur_pcl->seqnum_ >> 24) & 0xFF;
01404 (*walk++) = (cur_pcl->seqnum_ >> 16) & 0xFF;
01405 (*walk++) = (cur_pcl->seqnum_ >> 8) & 0xFF;
01406 (*walk++) = (cur_pcl->seqnum_) & 0xFF;
01407 ++(cur_pcl->seqnum_);
01408
01409 s.schedule(target_,p,0);
01410 }
01411 else
01412 Packet::free(p);
01413 }
01414 else
01415 Packet::free(p);
01416 }
01417 else {
01418
01419 s.schedule(target_, p, 0);
01420 }
01421 cur_pcl->last_update_sent_ = now;
01422 }
01423
01424
01425 if(cur_pcl->last_update_sent_ == now || suppress_flag)
01426 next_update_delay = cur_pcl->update_period_ + jitter(LM_STARTUP_JITTER, be_random_);
01427 else
01428 next_update_delay = cur_pcl->update_period_ - (now - cur_pcl->last_update_sent_) + jitter(LM_STARTUP_JITTER, be_random_);
01429
01430
01431 if(!demotion)
01432 s.schedule(cur_pcl->periodic_handler_, cur_pcl->periodic_update_event_, next_update_delay);
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444 if(level == highest_level_) {
01445 cur_pcl = parent_children_list_;
01446 while(cur_pcl) {
01447 if(cur_pcl->level_ > highest_level_) {
01448 lmnode = cur_pcl->pparent_;
01449 delete_flag = TRUE;
01450 while(lmnode) {
01451
01452
01453
01454 tmp_lmnode = lmnode->next_;
01455 if(((now - lmnode->last_update_rcvd_) > cur_pcl->update_timeout_)) {
01456
01457 upd_time = (int) now;
01458 upd_time = (upd_time << 16) | ((lmnode->last_upd_seqnum_+1) & 0xFFFF);
01459 cur_pcl->UpdatePotlParent(lmnode->id_, 0, 0, 0, 0, 0, upd_time, delete_flag);
01460 }
01461 lmnode = tmp_lmnode;
01462 }
01463
01464
01465 lmnode = cur_pcl->pchildren_;
01466 while(lmnode) {
01467
01468 tmp_lmnode = lmnode->next_;
01469 if((now - lmnode->last_update_rcvd_) > cur_pcl->update_timeout_) {
01470 upd_time = (int) now;
01471 upd_time = (upd_time << 16) | ((lmnode->last_upd_seqnum_+1) & 0xFFFF);
01472
01473
01474 if(cur_pcl->level_ == global_lm_level_+1 && lmnode->id_ == global_lm_id_) {
01475 global_lm_level_ = -1;
01476 global_lm_id_ = NO_GLOBAL_LM;
01477 }
01478
01479 cur_pcl->UpdatePotlChild(lmnode->id_, 0, 0, 0, 0, 0, upd_time, lmnode->child_flag_, delete_flag,NULL);
01480 }
01481 lmnode = tmp_lmnode;
01482 }
01483 }
01484 cur_pcl = cur_pcl->next_;
01485 }
01486 }
01487 }
01488
01489
01490
01491
01492 Packet *
01493 LandmarkAgent::makeUpdate(ParentChildrenList *pcl, int pkt_type, int action)
01494 {
01495 Packet *p = allocpkt();
01496 hdr_ip *iph = HDR_IP(p);
01497 hdr_cmn *hdrc = HDR_CMN(p);
01498 unsigned char *walk;
01499 compr_taglist *adv_tags = NULL;
01500 double now = Scheduler::instance().clock();
01501 int64_t *lmaddrs;
01502 int num_lm_addrs = 0;
01503
01504 hdrc->next_hop_ = IP_BROADCAST;
01505 hdrc->addr_type_ = NS_AF_INET;
01506 iph->daddr() = IP_BROADCAST;
01507 iph->dport() = ROUTER_PORT;
01508 iph->ttl_ = radius(pcl->level_);
01509
01510 iph->saddr() = myaddr_;
01511 iph->sport() = ROUTER_PORT;
01512
01513 if(action == GLOBAL_ADVERT)
01514 trace("Node %d: Generating global LM message at time %f",myaddr_,now);
01515
01516 assert(pcl->num_tags_ >= 0);
01517
01518 if(pkt_type == HIER_ADVS) {
01519
01520 if(pcl->level_ == 0) {
01521
01522 assert(action != DEMOTION);
01523
01524
01525
01526
01527
01528 lmaddrs = NULL;
01529 num_lm_addrs = 0;
01530 (pcl->mylmaddrs_)->get_lm_addrs(&num_lm_addrs, &lmaddrs);
01531
01532 p->allocdata(12 + (4 * pcl->num_tags_) + 2 + 4 + 1 + (8*num_lm_addrs));
01533 walk = p->accessdata();
01534
01535
01536 (*walk++) = (action) & 0xFF;
01537
01538
01539 (*walk++) = (num_lm_addrs) & 0xFF;
01540
01541
01542 for(int i = 0; i < num_lm_addrs; ++i) {
01543
01544 (*walk++) = (lmaddrs[i] >> 56) & 0xFF;
01545 (*walk++) = (lmaddrs[i] >> 48) & 0xFF;
01546 (*walk++) = (lmaddrs[i] >> 40) & 0xFF;
01547 (*walk++) = (lmaddrs[i] >> 32) & 0xFF;
01548 (*walk++) = (lmaddrs[i] >> 24) & 0xFF;
01549 (*walk++) = (lmaddrs[i] >> 16) & 0xFF;
01550 (*walk++) = (lmaddrs[i] >> 8) & 0xFF;
01551 (*walk++) = (lmaddrs[i]) & 0xFF;
01552 }
01553 if(num_lm_addrs)
01554 delete[] lmaddrs;
01555
01556
01557 (*walk++) = (pcl->level_) & 0xFF;
01558
01559
01560 int energy = (int)(node_->energy());
01561 (*walk++) = (energy >> 24) & 0xFF;
01562 (*walk++) = (energy >> 16) & 0xFF;
01563 (*walk++) = (energy >> 8) & 0xFF;
01564 (*walk++) = (energy) & 0xFF;
01565
01566
01567 (*walk++) = (myaddr_ >> 8) & 0xFF;
01568 (*walk++) = (myaddr_) & 0xFF;
01569
01570
01571
01572 (*walk++) = (radius(pcl->level_) >> 8) & 0xFF;
01573 (*walk++) = (radius(pcl->level_)) & 0xFF;
01574
01575
01576
01577
01578
01579
01580 int origin_time = (int)now;
01581 (*walk++) = (origin_time >> 8) & 0xFF;
01582 (*walk++) = (origin_time) & 0xFF;
01583 (*walk++) = (pcl->seqnum_ >> 8) & 0xFF;
01584 (*walk++) = (pcl->seqnum_) & 0xFF;
01585 ++(pcl->seqnum_);
01586
01587
01588 if(pcl->parent_ == NULL) {
01589 (*walk++) = (NO_PARENT >> 8) & 0xFF;
01590 (*walk++) = (NO_PARENT) & 0xFF;
01591 }
01592 else {
01593 (*walk++) = ((pcl->parent_)->id_ >> 8) & 0xFF;
01594 (*walk++) = ((pcl->parent_)->id_) & 0xFF;
01595 }
01596
01597 (*walk++) = (pcl->num_tags_ >> 8) & 0xFF;
01598 (*walk++) = (pcl->num_tags_) & 0xFF;
01599 if(pcl->num_tags_) {
01600 adv_tags = pcl->tag_list_;
01601 while(adv_tags) {
01602 (*walk++) = (adv_tags->obj_name_ >> 24) & 0xFF;
01603 (*walk++) = (adv_tags->obj_name_ >> 16) & 0xFF;
01604 (*walk++) = (adv_tags->obj_name_ >> 8) & 0xFF;
01605 (*walk++) = (adv_tags->obj_name_) & 0xFF;
01606 adv_tags = adv_tags->next_;
01607 }
01608 }
01609
01610
01611
01612
01613 hdrc->size_ = 20 + 20 + 4 + (4 * pcl->num_tags_) + 4 + 1 + (8*num_lm_addrs);
01614 }
01615 else {
01616
01617
01618
01619
01620
01621 int pkt_size = 0;
01622 lmaddrs = NULL;
01623 num_lm_addrs = 0;
01624 if(action == PERIODIC_ADVERTS || action == GLOBAL_ADVERT) {
01625 LMNode *pch = pcl->pchildren_;
01626
01627
01628 int size = 0;
01629 while(pch) {
01630 int64_t *addrs;
01631 int num_addrs = 0;
01632 (pch->lmaddr_)->get_lm_addrs(&num_addrs,&addrs);
01633 if(num_addrs) delete[] addrs;
01634 size += (1 + num_addrs*8);
01635 pch = pch->next_;
01636 }
01637
01638
01639
01640
01641 (pcl->mylmaddrs_)->get_lm_addrs(&num_lm_addrs, &lmaddrs);
01642
01643 pkt_size = 12 + 4 + (2 * pcl->num_potl_children_) + size + (4 * pcl->num_tags_) + 2 + 4 + 1 + (8*num_lm_addrs);
01644 }
01645 else
01646 pkt_size = 17;
01647
01648 p->allocdata(pkt_size);
01649 walk = p->accessdata();
01650
01651
01652 (*walk++) = (action) & 0xFF;
01653
01654
01655
01656
01657
01658 (*walk++) = (num_lm_addrs) & 0xFF;
01659 for(int i = 0; i < num_lm_addrs; ++i) {
01660
01661 (*walk++) = (lmaddrs[i] >> 56) & 0xFF;
01662 (*walk++) = (lmaddrs[i] >> 48) & 0xFF;
01663 (*walk++) = (lmaddrs[i] >> 40) & 0xFF;
01664 (*walk++) = (lmaddrs[i] >> 32) & 0xFF;
01665 (*walk++) = (lmaddrs[i] >> 24) & 0xFF;
01666 (*walk++) = (lmaddrs[i] >> 16) & 0xFF;
01667 (*walk++) = (lmaddrs[i] >> 8) & 0xFF;
01668 (*walk++) = (lmaddrs[i]) & 0xFF;
01669 }
01670 if(num_lm_addrs)
01671 delete[] lmaddrs;
01672
01673
01674
01675 (*walk++) = (pcl->level_) & 0xFF;
01676
01677
01678 int energy = (int)(node_->energy());
01679 (*walk++) = (energy >> 24) & 0xFF;
01680 (*walk++) = (energy >> 16) & 0xFF;
01681 (*walk++) = (energy >> 8) & 0xFF;
01682 (*walk++) = (energy) & 0xFF;
01683
01684
01685 (*walk++) = (myaddr_ >> 8) & 0xFF;
01686 (*walk++) = (myaddr_) & 0xFF;
01687
01688
01689 (*walk++) = (radius(pcl->level_) >> 8) & 0xFF;
01690 (*walk++) = (radius(pcl->level_)) & 0xFF;
01691
01692
01693
01694 int origin_time = (int)now;
01695 (*walk++) = (origin_time >> 8) & 0xFF;
01696 (*walk++) = (origin_time) & 0xFF;
01697 (*walk++) = (pcl->seqnum_ >> 8) & 0xFF;
01698 (*walk++) = (pcl->seqnum_) & 0xFF;
01699 ++(pcl->seqnum_);
01700
01701 if(origin_time > now) {
01702 printf("Node %d: id %d, level %d, vicinity_radius %d",myaddr_,myaddr_,pcl->level_,radius(pcl->level_));
01703 assert(origin_time < now);
01704 }
01705
01706
01707 if(pcl->parent_ == NULL) {
01708 (*walk++) = (NO_PARENT >> 8) & 0xFF;
01709 (*walk++) = (NO_PARENT) & 0xFF;
01710 }
01711 else {
01712 (*walk++) = ((pcl->parent_)->id_ >> 8) & 0xFF;
01713 (*walk++) = ((pcl->parent_)->id_) & 0xFF;
01714 }
01715
01716 if(action == PERIODIC_ADVERTS || action == GLOBAL_ADVERT) {
01717
01718 (*walk++) = (pcl->num_children_ >> 8) & 0xFF;
01719 (*walk++) = (pcl->num_children_) & 0xFF;
01720
01721
01722 (*walk++) = (pcl->num_potl_children_ >> 8) & 0xFF;
01723 (*walk++) = (pcl->num_potl_children_) & 0xFF;
01724
01725 LMNode *potl_ch = pcl->pchildren_;
01726 while(potl_ch) {
01727 if(potl_ch->child_flag_ != NOT_POTL_CHILD) {
01728 (*walk++) = (potl_ch->id_ >> 8) & 0xFF;
01729 (*walk++) = (potl_ch->id_) & 0xFF;
01730 int64_t *addrs = NULL;
01731 int num_addrs = 0;
01732 ((potl_ch)->lmaddr_)->get_lm_addrs(&num_addrs, &addrs);
01733
01734
01735
01736
01737
01738 (*walk++) = (num_addrs) & 0xFF;
01739 for(int i = 0; i < num_addrs; ++i) {
01740
01741 (*walk++) = (addrs[i] >> 56) & 0xFF;
01742 (*walk++) = (addrs[i] >> 48) & 0xFF;
01743 (*walk++) = (addrs[i] >> 40) & 0xFF;
01744 (*walk++) = (addrs[i] >> 32) & 0xFF;
01745 (*walk++) = (addrs[i] >> 24) & 0xFF;
01746 (*walk++) = (addrs[i] >> 16) & 0xFF;
01747 (*walk++) = (addrs[i] >> 8) & 0xFF;
01748 (*walk++) = (addrs[i]) & 0xFF;
01749 }
01750 if(num_addrs)
01751 delete[] addrs;
01752 }
01753 potl_ch = potl_ch->next_;
01754 }
01755
01756 (*walk++) = (pcl->num_tags_ >> 8) & 0xFF;
01757 (*walk++) = (pcl->num_tags_) & 0xFF;
01758 if(pcl->num_tags_) {
01759 adv_tags = pcl->tag_list_;
01760 while(adv_tags) {
01761 (*walk++) = (adv_tags->obj_name_ >> 24) & 0xFF;
01762 (*walk++) = (adv_tags->obj_name_ >> 16) & 0xFF;
01763 (*walk++) = (adv_tags->obj_name_ >> 8) & 0xFF;
01764 (*walk++) = (adv_tags->obj_name_) & 0xFF;
01765 adv_tags = adv_tags->next_;
01766 }
01767 }
01768
01769
01770
01771
01772
01773
01774 hdrc->size_ = 20 + 8 + ((4+8) * pcl->num_potl_children_) + 20 + 4 + (4 * pcl->num_tags_) + 4 + 1 + (8 * num_lm_addrs);
01775
01776
01777
01778
01779 }
01780 else if(action == DEMOTION) {
01781 hdrc->size_ = 20 + 20;
01782 }
01783 }
01784 }
01785
01786
01787
01788
01789
01790
01791
01792 if(action == DEMOTION && pcl->periodic_update_event_->uid_)
01793 Scheduler::instance().cancel(pcl->periodic_update_event_);
01794
01795 hdrc->direction() = hdr_cmn::DOWN;
01796 return p;
01797 }
01798
01799
01800
01801
01802 int
01803 LandmarkAgent::radius(int level)
01804 {
01805
01806 return((int(pow(2,level+1) + pow(2,level) - 1)));
01807
01808
01809
01810 }
01811
01812
01813
01814
01815 ParentChildrenList::ParentChildrenList(int level, LandmarkAgent *a) : parent_(NULL), num_heard_(0), num_children_(0), num_potl_children_(0), num_pparent_(0), pchildren_(NULL), pparent_(NULL) , seqnum_(0) ,last_update_sent_(-(a->update_period_)), update_period_(a->update_period_), update_timeout_(a->update_timeout_), next_(NULL)
01816 {
01817 level_ = level;
01818 periodic_update_event_ = new Event;
01819 periodic_handler_ = new LMPeriodicAdvtHandler(this);
01820 a_ = a;
01821 tag_list_ = NULL;
01822 num_tags_ = 0;
01823 adverts_type_ = FLOOD;
01824 mylmaddrs_ = new LMAddrs;
01825 }
01826
01827
01828
01829
01830 void
01831 PromotionTimer::expire(Event *e) {
01832 ParentChildrenList *pcl = a_->parent_children_list_;
01833 ParentChildrenList *new_pcl, *higher_level_pcl = NULL, *lower_level_pcl;
01834 ParentChildrenList *pcl1 = NULL;
01835 ParentChildrenList *pcl2 = NULL;
01836 ParentChildrenList *cur_pcl = NULL;
01837 int found = FALSE, has_parent = FALSE;
01838 int64_t *my_lm_addrs = NULL;
01839 int num_my_lm_addrs = 0;
01840 int num_potl_ch = 0;
01841 int addr_changed = 0;
01842 Scheduler &s = Scheduler::instance();
01843 double now = s.clock();
01844 Packet *p, *newp;
01845
01846
01847
01848
01849
01850
01851 while(pcl != NULL) {
01852 if(pcl->level_ == (a_->highest_level_ + 1)) {
01853
01854 higher_level_pcl = pcl;
01855 a_->num_resched_ = pcl->num_heard_ - 1;
01856 num_potl_ch = pcl->num_potl_children_;
01857 }
01858 else if(pcl->level_ == a_->highest_level_) {
01859 cur_pcl = pcl;
01860 if(pcl->parent_) {
01861 has_parent = TRUE;
01862 }
01863 }
01864 else if(pcl->level_ == (a_->highest_level_-1)) {
01865 lower_level_pcl = pcl;
01866 }
01867 pcl = pcl->next_;
01868 }
01869
01870 assert(higher_level_pcl);
01871 if(a_->highest_level_)
01872 assert(lower_level_pcl);
01873 assert(cur_pcl);
01874
01875 if(a_->wait_state_) {
01876
01877 if(a_->num_resched_ && !has_parent) {
01878 a_->wait_state_ = 0;
01879 a_->total_wait_time_ = 0;
01880
01881
01882
01883
01884
01885 a_->promo_timeout_ = a_->random_timer(double(CONST_TIMEOUT + PROMO_TIMEOUT_MULTIPLES * a_->radius(a_->highest_level_) + MAX_TIMEOUT/((a_->num_resched_+1) * pow(2,a_->highest_level_))), a_->be_random_);
01886
01887
01888
01889 a_->trace("Node %d: Promotion timeout after wait period in expire1: %f at time %f", a_->myaddr_,a_->promo_timeout_,s.clock());
01890 a_->num_resched_ = 0;
01891 a_->promo_start_time_ = s.clock();
01892 a_->promo_timer_->resched(a_->promo_timeout_);
01893 }
01894 else {
01895 double wait_time = PERIODIC_WAIT_TIME;
01896 a_->total_wait_time_ += wait_time;
01897
01898 a_->promo_timer_->resched(wait_time);
01899
01900
01901
01902 if(a_->highest_level_ && (a_->total_wait_time_ > (a_->update_period_*1.5))) {
01903
01904
01905
01906
01907
01908
01909 if(cur_pcl->num_children_ == 1 && lower_level_pcl->num_pparent_ > 1) {
01910 a_->trace("Node %d: Demoting from level %d because of no children at time %f",a_->myaddr_,a_->highest_level_,s.clock());
01911
01912
01913 int delete_flag = TRUE;
01914 int upd_time = (int) now;
01915 upd_time = (upd_time << 16) | (lower_level_pcl->seqnum_ & 0xFFFF);
01916 ++(lower_level_pcl->seqnum_);
01917 lower_level_pcl->UpdatePotlParent(a_->myaddr_, 0, 0, 0, 0, 0, upd_time, delete_flag);
01918
01919 upd_time = (int) now;
01920 upd_time = (upd_time << 16) | (higher_level_pcl->seqnum_ & 0xFFFF);
01921 ++(higher_level_pcl->seqnum_);
01922 higher_level_pcl->UpdatePotlChild(a_->myaddr_, 0, 0, 0, 0, 0, upd_time, IS_CHILD, delete_flag,NULL);
01923
01924 --(a_->highest_level_);
01925 Packet *p = a_->makeUpdate(cur_pcl, HIER_ADVS, DEMOTION);
01926 s.schedule(a_->target_,p,0);
01927 }
01928 }
01929 else if(!(cur_pcl->parent_) && (a_->total_wait_time_ >= (2*PERIODIC_WAIT_TIME))) {
01930
01931 a_->global_lm_id_ = a_->myaddr_;
01932 a_->global_lm_level_ = a_->highest_level_;
01933
01934
01935 (cur_pcl->mylmaddrs_)->get_lm_addrs(&num_my_lm_addrs,&my_lm_addrs);
01936
01937
01938
01939 int64_t *lmaddr = new int64_t[1];
01940 lmaddr[0] = 1;
01941 lmaddr[0] = (lmaddr[0] << (cur_pcl->level_ * 8));
01942 int num_lm_addrs = 1;
01943
01944 assert(num_my_lm_addrs <= 1);
01945 if(num_my_lm_addrs == 0) {
01946 addr_changed = 1;
01947 }
01948 else {
01949 if(my_lm_addrs[0] != lmaddr[0])
01950 addr_changed = 1;
01951 }
01952
01953 if(num_my_lm_addrs) delete[] my_lm_addrs;
01954
01955 if(addr_changed) {
01956 a_->trace("Node %d: LM addrs being assigned by global LM at time %f, level %d",a_->myaddr_,now,a_->highest_level_);
01957 a_->assign_lmaddress(lmaddr, num_lm_addrs, cur_pcl->level_);
01958 if(a_->global_lm_)
01959 p = a_->makeUpdate(cur_pcl, HIER_ADVS, GLOBAL_ADVERT);
01960 else
01961 p = a_->makeUpdate(cur_pcl, HIER_ADVS, PERIODIC_ADVERTS);
01962 a_->trace("Node %d: Generating ReHash msg at time %f",a_->myaddr_,NOW);
01963 a_->GenerateReHashMsg(lmaddr[0],NOW);
01964
01965
01966 ParentChildrenList *tmp_pcl = a_->parent_children_list_;
01967 while(tmp_pcl) {
01968 if(tmp_pcl->level_ < cur_pcl->level_) {
01969 a_->trace("Node %d: Generating level %d update at time %f",a_->myaddr_,tmp_pcl->level_,now);
01970 newp = a_->makeUpdate(tmp_pcl, HIER_ADVS, PERIODIC_ADVERTS);
01971 s.schedule(a_->target_,newp,0);
01972 tmp_pcl->last_update_sent_ = now;
01973 }
01974 tmp_pcl = tmp_pcl->next_;
01975 }
01976 s.schedule(a_->target_, p, 0);
01977 cur_pcl->last_update_sent_ = now;
01978 }
01979
01980
01981
01982 if(num_lm_addrs) delete[] lmaddr;
01983 }
01984 }
01985 return;
01986 }
01987
01988
01989 a_->promo_timer_running_ = 0;
01990
01991
01992
01993
01994
01995 higher_level_pcl = NULL;
01996 pcl = a_->parent_children_list_;
01997 while(pcl != NULL) {
01998 new_pcl = pcl;
01999 if(pcl->level_ == a_->highest_level_+1){
02000 found = TRUE;
02001 higher_level_pcl = pcl;
02002 }
02003 if(pcl->level_ == (a_->highest_level_)){
02004 pcl1 = pcl;
02005 }
02006 if(pcl->level_ == (a_->highest_level_+2)){
02007 pcl2 = pcl;
02008 }
02009 pcl = pcl->next_;
02010 }
02011
02012
02013 assert(pcl1);
02014
02015 if(pcl1->parent_ != NULL) {
02016 a_->trace("Node %d: Not promoted to higher level %d\n", a_->myaddr_, a_->highest_level_+1);
02017 return;
02018 }
02019
02020 ++(a_->highest_level_);
02021 assert(a_->highest_level_ < MAX_LEVELS);
02022
02023 if(!found) {
02024 new_pcl->next_ = new ParentChildrenList(a_->highest_level_, a_);
02025 higher_level_pcl = new_pcl->next_;
02026 new_pcl = new_pcl->next_;
02027 }
02028
02029
02030 if(!pcl2) {
02031 new_pcl->next_ = new ParentChildrenList((a_->highest_level_)+1, a_);
02032 pcl2 = new_pcl->next_;
02033 }
02034
02035 assert(pcl2);
02036
02037 if(a_->debug_) {
02038 a_->trace("Node %d: Promoted to level %d, num_potl_children %d at time %f", a_->myaddr_, a_->highest_level_, num_potl_ch, now);
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053 }
02054
02055
02056
02057 a_->SendChangedTagListUpdate(0,a_->highest_level_-1);
02058
02059
02060 s.schedule(higher_level_pcl->periodic_handler_, higher_level_pcl->periodic_update_event_, 0);
02061
02062
02063
02064 int num_hops = 0;
02065 int energy = (int)((a_->node_)->energy());
02066 int child_flag = IS_CHILD;
02067 int delete_flag = FALSE;
02068
02069 int upd_time = (int) now;
02070 upd_time = (upd_time << 16) | (pcl1->seqnum_ & 0xFFFF);
02071 ++(pcl1->seqnum_);
02072 pcl1->UpdatePotlParent(a_->myaddr_, a_->myaddr_, num_hops, a_->highest_level_, higher_level_pcl->num_children_, energy, upd_time, delete_flag);
02073
02074
02075
02076
02077 upd_time = (int) now;
02078 upd_time = (upd_time << 16) | (pcl2->seqnum_ & 0xFFFF);
02079 ++(pcl2->seqnum_);
02080 pcl2->UpdatePotlChild(a_->myaddr_, a_->myaddr_, num_hops, a_->highest_level_,higher_level_pcl->num_children_, energy, upd_time, child_flag, delete_flag, higher_level_pcl->tag_list_);
02081
02082
02083
02084 a_->num_resched_ = pcl2->num_heard_ - 1;
02085 if(higher_level_pcl->parent_ == NULL && a_->num_resched_) {
02086
02087
02088
02089
02090 a_->promo_timer_running_ = 1;
02091 a_->wait_state_ = 0;
02092 a_->total_wait_time_ = 0;
02093 a_->promo_timeout_ = a_->random_timer(double(CONST_TIMEOUT + PROMO_TIMEOUT_MULTIPLES * a_->radius(a_->highest_level_+1) + MAX_TIMEOUT/((a_->num_resched_+1) * pow(2,a_->highest_level_+1))), a_->be_random_);
02094 a_->trace("Node %d: Promotion timeout after wait period in expire2: %f at time %f, num_resched_ %d, energy %f", a_->myaddr_,a_->promo_timeout_,s.clock(),a_->num_resched_,(a_->node_)->energy());
02095 a_->num_resched_ = 0;
02096 a_->promo_start_time_ = s.clock();
02097 a_->promo_timer_->resched(a_->promo_timeout_);
02098 }
02099 else {
02100 double wait_time = PERIODIC_WAIT_TIME;
02101 a_->promo_timer_running_ = 1;
02102 a_->total_wait_time_ = 0;
02103 a_->wait_state_ = 1;
02104 a_->total_wait_time_ += wait_time;
02105
02106 a_->promo_timer_->resched(wait_time);
02107 }
02108
02109
02110
02111
02112
02113
02114
02115 }
02116
02117
02118
02119
02120
02121 int
02122 LandmarkAgent::command (int argc, const char *const *argv)
02123 {
02124 if (argc == 2)
02125 {
02126 if (strcmp (argv[1], "start") == 0)
02127 {
02128 startUp();
02129 return (TCL_OK);
02130 }
02131 if (strcmp (argv[1], "stop") == 0)
02132 {
02133 stop();
02134 return (TCL_OK);
02135 }
02136
02137 if (strcmp (argv[1], "print-nbrs") == 0)
02138 {
02139 get_nbrinfo();
02140 return (TCL_OK);
02141 }
02142 if (strcmp (argv[1], "enable-caching") == 0)
02143 {
02144 cache_ = 1;
02145 return (TCL_OK);
02146 }
02147 if (strcmp (argv[1], "unicast-adverts") == 0)
02148 {
02149 adverts_type_ = UNICAST;
02150 return (TCL_OK);
02151 }
02152 if (strcmp (argv[1], "hard-state-adverts") == 0)
02153 {
02154 adverts_type_ = SUPPRESS;
02155
02156 update_timeout_ = 1000000;
02157 return (TCL_OK);
02158 }
02159 if (strcmp (argv[1], "enable-global-landmark") == 0)
02160 {
02161 global_lm_ = 1;
02162 return (TCL_OK);
02163 }
02164 else if (strcmp (argv[1], "dumprtab") == 0)
02165 {
02166 Packet *p2 = allocpkt ();
02167 hdr_ip *iph2 = HDR_IP(p2);
02168
02169
02170 trace ("Table Dump %d[%d]\n----------------------------------\n",
02171 myaddr_, iph2->sport());
02172 trace ("VTD %.5f %d:%d\n", Scheduler::instance ().clock (),
02173 myaddr_, iph2->sport());
02174 trace ("Remaining energy: %f", node_->energy());
02175
02176
02177
02178
02179
02180
02181 trace("Highest Level: %d", highest_level_);
02182 Packet::free (p2);
02183 ParentChildrenList *pcl = parent_children_list_;
02184 LMNode *pch;
02185 while(pcl) {
02186 trace("Level %d:", pcl->level_);
02187 if(pcl->parent_)
02188 trace("Parent: %d", (pcl->parent_)->id_);
02189 else
02190 trace("Parent: NULL");
02191 int num_lm_addrs = 0;
02192 int64_t *lmaddrs = NULL;
02193 (pcl->mylmaddrs_)->get_lm_addrs(&num_lm_addrs,&lmaddrs);
02194 for( int i = 0; i < num_lm_addrs; ++i) {
02195 int i1,i2,i3,i4,i5,i6,i7,i8;
02196 i1 = (lmaddrs[i] >> 56) & 0xFF;
02197 i2 = (lmaddrs[i] >> 48) & 0xFF;
02198 i3 = (lmaddrs[i] >> 40) & 0xFF;
02199 i4 = (lmaddrs[i] >> 32) & 0xFF;
02200 i5 = (lmaddrs[i] >> 24) & 0xFF;
02201 i6 = (lmaddrs[i] >> 16) & 0xFF;
02202 i7 = (lmaddrs[i] >> 8) & 0xFF;
02203 i8 = (lmaddrs[i]) & 0xFF;
02204 trace("Landmark Address: %d.%d.%d.%d.%d.%d.%d.%d",i1,i2,i3,i4,i5,i6,i7,i8);
02205 }
02206 if(num_lm_addrs) delete[] lmaddrs;
02207 if(myaddr_ == 134) {
02208 pch = pcl->pchildren_;
02209 while(pch) {
02210 int num_addrs = 0;
02211 int64_t *addrs = NULL;
02212 (pch->lmaddr_)->get_lm_addrs(&num_addrs,&addrs);
02213
02214 int j1=0,j2=0,j3=0,j4=0,j5=0,j6=0,j7=0,j8=0;
02215 if(num_addrs) {
02216 j1 = (addrs[0] >> 56) & 0xFF;
02217 j2 = (addrs[0] >> 48) & 0xFF;
02218 j3 = (addrs[0] >> 40) & 0xFF;
02219 j4 = (addrs[0] >> 32) & 0xFF;
02220 j5 = (addrs[0] >> 24) & 0xFF;
02221 j6 = (addrs[0] >> 16) & 0xFF;
02222 j7 = (addrs[0] >> 8) & 0xFF;
02223 j8 = (addrs[0]) & 0xFF;
02224 }
02225 trace("Node %d: Potl Child id %d, LM addr %d.%d.%d.%d.%d.%d.%d.%d, next_hop %d, num_children %d",myaddr_,pch->id_,j1,j2,j3,j4,j5,j6,j7,j8,pch->next_hop_,pch->num_children_);
02226 if(num_addrs) delete[] addrs;
02227 pch = pch->next_;
02228 }
02229 }
02230 trace("Number of potl children: %d\n", pcl->num_potl_children_);
02231 if(myaddr_ == 166) {
02232 trace("Number of children: %d\n", pcl->num_children_);
02233 trace("Number of level %d nodes heard: %d\n", (pcl->level_)-1, pcl->num_heard_);
02234
02235 trace("Number of potl parent: %d\n", pcl->num_pparent_);
02236 if(pcl->level_ >= 1 && highest_level_ >= 1) {
02237 pch = pcl->pchildren_;
02238 trace("Potential Children (radius %d):",radius(pcl->level_));
02239 while(pch) {
02240 if(pch->child_flag_ != NOT_POTL_CHILD)
02241 trace("Node %d (%d hops away)",pch->id_,pch->num_hops_);
02242 pch = pch->next_;
02243 }
02244
02245 pch = pcl->pparent_;
02246 trace("Potential parent:");
02247 while(pch) {
02248 trace("Node %d (%d hops away)",pch->id_,pch->num_hops_);
02249 pch = pch->next_;
02250 }
02251 }
02252 }
02253 pcl = pcl->next_;
02254 }
02255
02256 Packet::free(p2);
02257 return (TCL_OK);
02258 }
02259 }
02260 else if (argc == 3)
02261 {
02262 if (strcasecmp (argv[1], "tracetarget") == 0)
02263 {
02264 TclObject *obj;
02265 if ((obj = TclObject::lookup (argv[2])) == 0)
02266 {
02267 fprintf (stderr, "%s: %s lookup of %s failed\n", __FILE__, argv[1],
02268 argv[2]);
02269 return TCL_ERROR;
02270 }
02271 tracetarget_ = (Trace *) obj;
02272 return TCL_OK;
02273 }
02274 else if (strcasecmp (argv[1], "addr") == 0) {
02275 int temp;
02276 temp = Address::instance().str2addr(argv[2]);
02277 myaddr_ = temp;
02278 return TCL_OK;
02279 }
02280 else if (strcasecmp (argv[1], "set-update-period") == 0) {
02281 update_period_ = atof(argv[2]);
02282 if(adverts_type_ != SUPPRESS)
02283 update_timeout_ = update_period_ + 4 * LM_STARTUP_JITTER;
02284 return TCL_OK;
02285 }
02286 else if (strcasecmp (argv[1], "set-update-timeout") == 0) {
02287 update_timeout_ = atof(argv[2]);
02288 return TCL_OK;
02289 }
02290 else if (strcasecmp (argv[1], "start-tag-motion") == 0) {
02291 mobility_period_ = atof(argv[2]);
02292 Scheduler::instance().schedule(tag_mobility_,tag_mobility_event_,Random::uniform(mobility_period_));
02293 return (TCL_OK);
02294 }
02295 else if (strcasecmp (argv[1], "attach-tag-dbase") == 0)
02296 {
02297 TclObject *obj;
02298 if ((obj = TclObject::lookup (argv[2])) == 0)
02299 {
02300 fprintf (stderr, "%s: %s lookup of %s failed\n", __FILE__, argv[1],
02301 argv[2]);
02302 return TCL_ERROR;
02303 }
02304 tag_dbase_ = (tags_database *) obj;
02305 return TCL_OK;
02306 }
02307 else if (strcasecmp (argv[1], "node") == 0)
02308 {
02309 assert(node_ == NULL);
02310 TclObject *obj;
02311 if ((obj = TclObject::lookup (argv[2])) == 0)
02312 {
02313 fprintf (stderr, "%s: %s lookup of %s failed\n", __FILE__, argv[1],
02314 argv[2]);
02315 return TCL_ERROR;
02316 }
02317 node_ = (MobileNode *) obj;
02318 return TCL_OK;
02319 }
02320 else if (strcmp (argv[1], "query-debug") == 0)
02321 {
02322 qry_debug_ = atoi(argv[2]);
02323 return (TCL_OK);
02324 }
02325 else if (strcasecmp (argv[1], "ll-queue") == 0)
02326 {
02327 if (!(ll_queue = (PriQueue *) TclObject::lookup (argv[2])))
02328 {
02329 fprintf (stderr, "Landmark_Agent: ll-queue lookup of %s failed\n", argv[2]);
02330 return TCL_ERROR;
02331 }
02332
02333 return TCL_OK;
02334 }
02335 }
02336
02337 return (Agent::command (argc, argv));
02338 }
02339
02340
02341
02342
02343 void
02344 LandmarkAgent::startUp()
02345 {
02346 int i,ntags, j = 0, read_new_mobile_tags = 0;
02347 Scheduler &s = Scheduler::instance();
02348 compr_taglist *local_tags0, *local_tags1, *local_tags2, *t_ptr;
02349 compr_taglist *tag_ptr1, *tag_ptr2;
02350 God *gd = God::instance();
02351
02352 int *nbrs;
02353 int num_nbrs = 0, num_nodes = 0;
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379 trace("Node %d: LM Agent starting up at time %f",myaddr_,NOW);
02380
02381
02382 node_dead_ = 0;
02383
02384 double x,y,z;
02385 node_->getLoc(&x,&y,&z);
02386
02387
02388
02389
02390
02391 double r = 60;
02392
02393 local_tags0 = tag_dbase_->Gettags(x,y,r);
02394
02395
02396 t_ptr = local_tags0;
02397 ntags = 0;
02398 while(t_ptr) {
02399
02400 ++ntags;
02401 if(!(t_ptr->next_) && mobile_tags_ && !read_new_mobile_tags) {
02402
02403
02404
02405 read_new_mobile_tags = 1;
02406 t_ptr->next_ = mobile_tags_;
02407 mobile_tags_ = NULL;
02408 }
02409 t_ptr = t_ptr->next_;
02410 }
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453 assert(highest_level_ == 0);
02454 assert(parent_children_list_ == NULL);
02455 parent_children_list_ = new ParentChildrenList(highest_level_, this);
02456 ParentChildrenList **pcl = &parent_children_list_;
02457
02458
02459 assert(highest_level_ == 0);
02460 s.schedule((*pcl)->periodic_handler_, (*pcl)->periodic_update_event_, INITIAL_WAIT_TIME + jitter(LM_STARTUP_JITTER, be_random_));
02461 (*pcl)->tag_list_ = local_tags0;
02462 (*pcl)->num_tags_ = ntags;
02463
02464
02465
02466 promo_timer_running_ = 1;
02467 num_resched_ = 0;
02468
02469
02470
02471
02472 total_wait_time_ = 0;
02473 wait_state_ = 1;
02474 double wait_time = WAIT_TIME * radius(highest_level_) + INITIAL_WAIT_TIME + LM_STARTUP_JITTER;
02475 total_wait_time_ += wait_time;
02476
02477 promo_timer_->sched(wait_time);
02478
02479
02480 }
02481
02482
02483
02484
02485 compr_taglist *
02486 LandmarkAgent::aggregate_taginfo(compr_taglist *unagg_tags, int agg_level, int *num_tags)
02487 {
02488 compr_taglist *agg_tags, *agg_ptr1, *agg_ptr2, *last_agg_ptr;
02489 int found;
02490
02491 *num_tags = 0;
02492
02493
02494 agg_ptr1 = unagg_tags;
02495 agg_tags = NULL;
02496
02497 while(agg_ptr1) {
02498 if(agg_level == 1) {
02499 found = FALSE;
02500 if(agg_tags) {
02501 agg_ptr2 = agg_tags;
02502 while(agg_ptr2) {
02503 if((((agg_ptr2->obj_name_ >> 24) & 0xFF) == ((agg_ptr1->obj_name_ >> 24) & 0xFF)) && (((agg_ptr2->obj_name_ >> 16) & 0xFF) == ((agg_ptr1->obj_name_ >> 16) & 0xFF))) {
02504 found = TRUE;
02505 break;
02506 }
02507 last_agg_ptr = agg_ptr2;
02508 agg_ptr2 = agg_ptr2->next_;
02509 }
02510 }
02511
02512 if(!found) {
02513 ++(*num_tags);
02514 if(!agg_tags) {
02515 agg_tags = new compr_taglist;
02516 last_agg_ptr = agg_tags;
02517 }
02518 else {
02519 last_agg_ptr->next_ = new compr_taglist;
02520 last_agg_ptr = last_agg_ptr->next_;
02521 }
02522 last_agg_ptr->obj_name_ = (agg_ptr1->obj_name_ & 0xFFFF0000);
02523 }
02524 }
02525 else if(agg_level >= 2) {
02526 found = FALSE;
02527 if(agg_tags) {
02528 agg_ptr2 = agg_tags;
02529 while(agg_ptr2) {
02530 if(((agg_ptr2->obj_name_ >> 24) & 0xFF) == ((agg_ptr1->obj_name_ >> 24) & 0xFF)) {
02531 found = TRUE;
02532 break;
02533 }
02534 last_agg_ptr = agg_ptr2;
02535 agg_ptr2 = agg_ptr2->next_;
02536 }
02537 }
02538
02539 if(!found) {
02540 ++(*num_tags);
02541 if(!agg_tags) {
02542 agg_tags = new compr_taglist;
02543 last_agg_ptr = agg_tags;
02544 }
02545 else {
02546 last_agg_ptr->next_ = new compr_taglist;
02547 last_agg_ptr = last_agg_ptr->next_;
02548 }
02549 last_agg_ptr->obj_name_ = (agg_ptr1->obj_name_ & 0xFF000000);
02550 }
02551 }
02552 agg_ptr1 = agg_ptr1->next_;
02553 }
02554 return(agg_tags);
02555 }
02556
02557
02558
02559
02560
02561 compr_taglist *
02562 LandmarkAgent::aggregate_tags(compr_taglist *unagg_tags, int agg_level, int *num_tags)
02563 {
02564 compr_taglist *agg_tags = NULL, *tag_ptr;
02565 aggreg_taglist *t1, *t2, *t3, *tmp_ptr;
02566 aggreg_taglist *list1 = NULL, *list2 = NULL, *list3 = NULL, *list = NULL;
02567 aggreg_taglist *prev_tag, *next_tag, *old_list;
02568 int found;
02569 int p1,p2,p3,q1,q2,q3,object_name;
02570
02571
02572
02573
02574
02575
02576
02577 tag_ptr = unagg_tags;
02578 while(tag_ptr) {
02579 p1 = (tag_ptr->obj_name_ >> 24) & 0xFF;
02580 p2 = (tag_ptr->obj_name_ >> 16) & 0xFF;
02581 p3 = tag_ptr->obj_name_ & 0xFFFF;
02582 found = 0;
02583
02584 if(p1 && p2 && p3) {
02585
02586
02587 object_name = (int)((p1 * pow(2,24)) + (p2 * pow(2,16))) ;
02588 old_list = list2;
02589 while(old_list) {
02590 if(old_list->obj_name_ == object_name) {
02591 found = TRUE;
02592 break;
02593 }
02594 old_list = old_list->next_;
02595 }
02596
02597
02598 old_list = list1;
02599 while(old_list) {
02600 q1 = (old_list->obj_name_ >> 24) & 0xFF;
02601 if(p1 == q1) {
02602 found = TRUE;
02603 break;
02604 }
02605 old_list = old_list->next_;
02606 }
02607
02608 tmp_ptr = list3;
02609 while(tmp_ptr && !found) {
02610 q1 = (tmp_ptr->obj_name_ >> 24) & 0xFF;
02611 q2 = (tmp_ptr->obj_name_ >> 16) & 0xFF;
02612 q3 = tmp_ptr->obj_name_ & 0xFFFF;
02613
02614
02615
02616 if(p1 == q1 && p2 == q2 && p3 != q3) {
02617 if(!list2) {
02618 list2 = new aggreg_taglist;
02619 t2 = list2;
02620 }
02621 else {
02622 t2->next_ = new aggreg_taglist;
02623 t2 = t2->next_;
02624 }
02625 t2->obj_name_ = object_name;
02626
02627
02628 t2->marked_ = 1;
02629
02630
02631 tmp_ptr->obj_name_ = -1;
02632 found = TRUE;
02633 break;
02634 }
02635 else if(p1 == q1 && p2 == q2 && p3 == q3) {
02636 found = TRUE;
02637 break;
02638 }
02639 tmp_ptr = tmp_ptr->next_;
02640 }
02641
02642 if(found) {
02643 tag_ptr = tag_ptr->next_;
02644 continue;
02645 }
02646
02647 if(!list3) {
02648 list3 = new aggreg_taglist;
02649 t3 = list3;
02650 }
02651 else {
02652 t3->next_ = new aggreg_taglist;
02653 t3 = t3->next_;
02654 }
02655 t3->obj_name_ = tag_ptr->obj_name_;
02656 }
02657 else if(p1 && p2 && !p3) {
02658
02659
02660 object_name = (int)(p1 * pow(2,24)) ;
02661 if(list1) {
02662 old_list = list1;
02663 while(old_list) {
02664 if(old_list->obj_name_ == object_name) {
02665 found = TRUE;
02666 break;
02667 }
02668 old_list = old_list->next_;
02669 }
02670 }
02671
02672 tmp_ptr = list2;
02673 while(tmp_ptr && !found) {
02674 q1 = (tmp_ptr->obj_name_ >> 24) & 0xFF;
02675 q2 = (tmp_ptr->obj_name_ >> 16) & 0xFF;
02676
02677
02678 if(p1 == q1 && p2 != q2 && !tmp_ptr->marked_) {
02679 if(!list1) {
02680 list1 = new aggreg_taglist;
02681 t1 = list1;
02682 }
02683 else {
02684 t1->next_ = new aggreg_taglist;
02685 t1 = t1->next_;
02686 }
02687 t1->obj_name_ = object_name;
02688
02689
02690 t1->marked_ = 1;
02691
02692
02693 tmp_ptr->obj_name_ = -1;
02694
02695
02696 old_list = list3;
02697 while(old_list) {
02698 q1 = (old_list->obj_name_ >> 24) & 0xFF;
02699 if(p1 == q1)
02700 old_list->obj_name_ = -1;
02701 old_list = old_list->next_;
02702 }
02703
02704 found = TRUE;
02705 break;
02706 }
02707 else if(p1 == q1 && p2 == q2) {
02708 found = TRUE;
02709 break;
02710 }
02711 tmp_ptr = tmp_ptr->next_;
02712 }
02713
02714 if(found) {
02715 tag_ptr = tag_ptr->next_;
02716 continue;
02717 }
02718
02719 if(!list2) {
02720 list2 = new aggreg_taglist;
02721 t2 = list2;
02722 }
02723 else {
02724 t2->next_ = new aggreg_taglist;
02725 t2 = t2->next_;
02726 }
02727 t2->obj_name_ = tag_ptr->obj_name_;
02728
02729
02730 old_list = list3;
02731 while(old_list) {
02732 q1 = (old_list->obj_name_ >> 24) & 0xFF;
02733 q2 = (old_list->obj_name_ >> 16) & 0xFF;
02734 if(p1 == q1 && p2 == q2)
02735 old_list->obj_name_ = -1;
02736 old_list = old_list->next_;
02737 }
02738 }
02739 else if(p1 && !p2 && !p3) {
02740
02741 tmp_ptr = list1;
02742 while(tmp_ptr) {
02743 if(tmp_ptr->obj_name_ == tag_ptr->obj_name_) {
02744 found = TRUE;
02745 break;
02746 }
02747 tmp_ptr = tmp_ptr->next_;
02748 }
02749
02750
02751 if(!found) {
02752 if(!list1) {
02753 list1 = new aggreg_taglist;
02754 t1 = list1;
02755 }
02756 else {
02757 t1->next_ = new aggreg_taglist;
02758 t1 = t1->next_;
02759 }
02760 t1->obj_name_ = tag_ptr->obj_name_;
02761 }
02762
02763
02764 old_list = list2;
02765 while(old_list) {
02766 q1 = (old_list->obj_name_ >> 24) & 0xFF;
02767 if(p1 == q1)
02768 old_list->obj_name_ = -1;
02769 old_list = old_list->next_;
02770 }
02771
02772
02773 old_list = list3;
02774 while(old_list) {
02775 q1 = (old_list->obj_name_ >> 24) & 0xFF;
02776 if(p1 == q1)
02777 old_list->obj_name_ = -1;
02778 old_list = old_list->next_;
02779 }
02780 }
02781 else
02782 assert(0);
02783 tag_ptr = tag_ptr->next_;
02784 }
02785
02786
02787 list = NULL;
02788 if(list3) {
02789 list = list3;
02790 if(list2) {
02791 t3->next_ = list2;
02792 if(list1) {
02793 t2->next_ = list1;
02794 }
02795 }
02796 else if(list1)
02797 t3->next_ = list1;
02798 }
02799 else if(list2) {
02800 list = list2;
02801 if(list1)
02802 t2->next_ = list1;
02803 }
02804 else if(list1)
02805 list = list1;
02806
02807
02808
02809
02810 *num_tags = 0;
02811 agg_tags = NULL;
02812 tmp_ptr = list;
02813 while(tmp_ptr) {
02814 if(tmp_ptr->obj_name_ != -1) {
02815 if(!agg_tags) {
02816 agg_tags = new compr_taglist;
02817 tag_ptr = agg_tags;
02818 }
02819 else {
02820 tag_ptr->next_ = new compr_taglist;
02821 tag_ptr = tag_ptr->next_;
02822 }
02823 ++(*num_tags);
02824 tag_ptr->obj_name_ = tmp_ptr->obj_name_;
02825 }
02826 tmp_ptr = tmp_ptr->next_;
02827 }
02828
02829
02830 list1 = NULL;
02831 list2 = NULL;
02832 list1 = list;
02833 while(list1) {
02834 list2 = list1;
02835 list1 = list1->next_;
02836 delete list2;
02837 }
02838
02839 return(agg_tags);
02840 }
02841
02842
02843
02844
02845
02846
02847 void
02848 LandmarkAgent::recv(Packet *p, Handler *)
02849 {
02850 hdr_ip *iph = HDR_IP(p);
02851 hdr_cmn *cmh = HDR_CMN(p);
02852
02853
02854
02855
02856
02857 if(node_dead_) {
02858 Packet::free(p);
02859 return;
02860 }
02861
02862 if(iph->saddr() == myaddr_ && iph->sport() == 0) {
02863
02864
02865
02866 cmh->size() += IP_HDR_LEN;
02867
02868 }
02869
02870
02871
02872
02873 else if(iph->saddr() == myaddr_) {
02874 Packet::free(p);
02875
02876 return;
02877 }
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889 cmh->direction_ = hdr_cmn::DOWN;
02890
02891 unsigned char *walk = p->accessdata();
02892 int action = *walk++;
02893
02894 int data_pkt = 0;
02895 if(action == QUERY_PKT || action == HASH_PKT || action == HASH_ACK_PKT || action == REHASH_PKT || action == DIR_QUERY_PKT || action == DIR_RESPONSE_PKT || action == OBJECT_QUERY_PKT || action == OBJECT_RESPONSE_PKT)
02896 data_pkt = 1;
02897
02898 if ((iph->saddr() != myaddr_) && (iph->dport() == ROUTER_PORT) && !data_pkt)
02899 {
02900 ProcessHierUpdate(p);
02901 }
02902 else
02903 {
02904 ForwardPacket(p);
02905 }
02906 }
02907
02908 void
02909 LandmarkAgent::ForwardPacket(Packet *p)
02910 {
02911 hdr_ip *iph = HDR_IP(p);
02912 hdr_cmn *cmh = HDR_CMN(p);
02913 Packet *newp;
02914 hdr_ip *new_iph;
02915 hdr_cmn *new_cmh;
02916 unsigned char *walk, *X_ptr, *Y_ptr, *level_ptr, *num_src_hops_ptr;
02917 unsigned char *last_hop_ptr, *pkt_end_ptr;
02918 int X, Y, next_hop_level, prev_hop_level, obj_name, num_src_hops;
02919 double local_x, local_y, local_z;
02920 int num_dst = 0, action, origin_time;
02921 NodeIDList *dst_nodes = NULL, *dst_ptr = NULL;
02922 int query_for_us = FALSE;
02923 Scheduler &s = Scheduler::instance();
02924 double now = s.clock();
02925 nsaddr_t last_hop_id;
02926 int cache_index = -1;
02927 int found = FALSE;
02928
02929 walk = p->accessdata();
02930
02931
02932 action = *walk++;
02933
02934 X = 0;
02935 X_ptr = walk;
02936 X = *walk++;
02937 X = (X << 8) | *walk++;
02938
02939 Y_ptr = walk;
02940 Y = *walk++;
02941 Y = (Y << 8) | *walk++;
02942
02943
02944 level_ptr = walk;
02945 next_hop_level = *walk++;
02946
02947 obj_name = *walk++;
02948 obj_name = (obj_name << 8) | *walk++;
02949 obj_name = (obj_name << 8) | *walk++;
02950 obj_name = (obj_name << 8) | *walk++;
02951
02952
02953 origin_time = *walk++;
02954 origin_time = (origin_time << 8) | *walk++;
02955 origin_time = (origin_time << 8) | *walk++;
02956 origin_time = (origin_time << 8) | *walk++;
02957
02958 num_src_hops_ptr = walk;
02959 num_src_hops = *walk++;
02960 num_src_hops = (num_src_hops << 8) | *walk++;
02961
02962 assert(num_src_hops <= 30);
02963
02964 last_hop_ptr = NULL;
02965 for(int i = 0; i < num_src_hops; ++i) {
02966 last_hop_ptr = walk;
02967 walk += 3;
02968 }
02969
02970 if(last_hop_ptr) {
02971 prev_hop_level = *(last_hop_ptr+2);
02972 last_hop_id = *last_hop_ptr;
02973 last_hop_id = (last_hop_id << 8) | *(last_hop_ptr+1);
02974 }
02975 else {
02976 prev_hop_level = 0;
02977 last_hop_id = NO_NEXT_HOP;
02978 }
02979
02980
02981 pkt_end_ptr = walk;
02982
02983
02984 if(cache_) {
02985 if(X != 65000 && Y != 65000) {
02986 if(num_cached_items_ < MAX_CACHE_ITEMS) {
02987
02988 int replace_index = num_cached_items_;
02989
02990 for(int i = 0; i < num_cached_items_; ++i) {
02991 if(tag_cache_[i].obj_name_ == obj_name && tag_cache_[i].origin_time_ < origin_time) {
02992 replace_index = i;
02993 break;
02994 }
02995 }
02996
02997 tag_cache_[replace_index].obj_name_ = obj_name;
02998 tag_cache_[replace_index].origin_time_ = origin_time;
02999 tag_cache_[replace_index].X_ = X;
03000 tag_cache_[replace_index].Y_ = Y;
03001 ++num_cached_items_;
03002 }
03003 else {
03004
03005 int replace_index = 0;
03006 int least_time = tag_cache_[replace_index].origin_time_;
03007 for(int i = 0; i < MAX_CACHE_ITEMS; ++i) {
03008 if(tag_cache_[i].origin_time_ < least_time)
03009 replace_index = i;
03010 }
03011 tag_cache_[replace_index].obj_name_ = obj_name;
03012 tag_cache_[replace_index].origin_time_ = origin_time;
03013 tag_cache_[replace_index].X_ = X;
03014 tag_cache_[replace_index].Y_ = Y;
03015 }
03016 }
03017 else {
03018
03019
03020 found = FALSE;
03021 for(int i = 0; i < num_cached_items_; ++i) {
03022 if(tag_cache_[i].obj_name_ == obj_name && tag_cache_[i].origin_time_ > origin_time - 600) {
03023 found = TRUE;
03024 cache_index = i;
03025 break;
03026 }
03027 }
03028 }
03029 }
03030
03031
03032
03033
03034
03035
03036
03037
03038 cmh->direction() = hdr_cmn::DOWN;
03039 if(iph->daddr() == myaddr_)
03040 query_for_us = TRUE;
03041
03042
03043 if(X == 65000 && Y == 65000) {
03044
03045 if(query_for_us || found) {
03046 if(qry_debug_)
03047 trace("Node %d: Rcved qry for us from node %d at time %f",myaddr_,last_hop_id,s.clock());
03048 if(!found)
03049 dst_nodes = search_tag(obj_name,prev_hop_level,next_hop_level,last_hop_id,&num_dst);
03050
03051 if((num_dst == 0 && dst_nodes) || found) {
03052 delete dst_nodes;
03053
03054
03055
03056 if(found) {
03057 (*X_ptr++) = ((int)tag_cache_[cache_index].X_ >> 8) & 0xFF;
03058 (*X_ptr) = ((int)tag_cache_[cache_index].X_) & 0xFF;
03059 (*Y_ptr++) = ((int)tag_cache_[cache_index].Y_ >> 8) & 0xFF;
03060 (*Y_ptr) = ((int)tag_cache_[cache_index].Y_) & 0xFF;
03061 }
03062 else {
03063 node_->getLoc(&local_x, &local_y, &local_z);
03064 (*X_ptr++) = ((int)local_x >> 8) & 0xFF;
03065 (*X_ptr) = ((int)local_x) & 0xFF;
03066 (*Y_ptr++) = ((int)local_y >> 8) & 0xFF;
03067 (*Y_ptr) = ((int)local_y) & 0xFF;
03068 }
03069
03070
03071 iph->ttl_ = 1000;
03072
03073 cmh->size() += 50;
03074
03075 if(!num_src_hops) {
03076 iph->daddr() = myaddr_;
03077 iph->dport() = 0;
03078 cmh->next_hop_ = myaddr_;
03079 }
03080 else {
03081 --num_src_hops;
03082 *num_src_hops_ptr = (num_src_hops >> 8) & 0xFF;
03083 *(num_src_hops_ptr + 1) = num_src_hops & 0xFF;
03084
03085 cmh->size() -= 4;
03086
03087 iph->daddr() = *last_hop_ptr++;
03088 iph->daddr() = (iph->daddr() << 8) | *last_hop_ptr++;
03089 if(!num_src_hops)
03090 iph->dport() = 0;
03091 else
03092 iph->dport() = ROUTER_PORT;
03093
03094 int relevant_level = *last_hop_ptr;
03095 cmh->next_hop_ = get_next_hop(iph->daddr(),relevant_level);
03096
03097 if(cmh->next_hop_ == NO_NEXT_HOP) {
03098 Packet::free(p);
03099 trace("Node %d: Packet dropped because of no next hop info",myaddr_);
03100 return;
03101 }
03102 *level_ptr = *last_hop_ptr;
03103 }
03104
03105
03106
03107
03108
03109
03110 if(!num_src_hops && iph->daddr() == myaddr_) {
03111
03112
03113 Packet::free(p);
03114 trace("Node %d: Found object %d.%d.%d at (%d,%d) at time %f",myaddr_, (obj_name >> 24) & 0xFF, (obj_name >> 16) & 0xFF, obj_name & 0xFFFF,X,Y,s.clock());
03115 return;
03116 }
03117 else if(iph->daddr() == myaddr_) {
03118 ForwardPacket(p);
03119 }
03120 else {
03121 s.schedule(target_,p,0);
03122 }
03123 }
03124 else if(num_dst >= 1) {
03125
03126 if(--iph->ttl_ == 0) {
03127 drop(p, DROP_RTR_TTL);
03128 return;
03129 }
03130
03131
03132
03133 ++num_src_hops;
03134 *num_src_hops_ptr = (num_src_hops >> 8) & 0xFF;
03135 *(num_src_hops_ptr+1) = num_src_hops & 0xFF;
03136 *pkt_end_ptr++ = (myaddr_ >> 8) & 0xFF;
03137 *pkt_end_ptr++ = myaddr_ & 0xFF;
03138
03139
03140 *pkt_end_ptr = (next_hop_level+1) & 0xFF;
03141
03142 cmh->size() += 4;
03143
03144 dst_ptr = dst_nodes;
03145
03146 iph->daddr() = dst_ptr->dst_node_;
03147 iph->dport() = ROUTER_PORT;
03148 cmh->next_hop_ = dst_ptr->dst_next_hop_;
03149 cmh->addr_type_ = NS_AF_INET;
03150
03151
03152 int tmp_next_hop_level = dst_ptr->next_hop_level_;
03153
03154 if(qry_debug_)
03155 trace("Node %d: Forwarding qry to node %d at time %f",myaddr_,dst_ptr->dst_node_,s.clock());
03156
03157 dst_ptr = dst_ptr->next_;
03158 delete dst_nodes;
03159 dst_nodes = dst_ptr;
03160
03161 for(int i = 1; i < num_dst; ++i) {
03162 if(qry_debug_)
03163 trace("Node %d: Forwarding qry to node %d at time %f",myaddr_,dst_ptr->dst_node_,s.clock());
03164
03165
03166 *level_ptr = dst_ptr->next_hop_level_;
03167
03168 newp = p->copy();
03169
03170 new_iph = HDR_IP(newp);
03171 new_cmh = HDR_CMN(newp);
03172
03173 new_iph->daddr() = dst_ptr->dst_node_;
03174 new_iph->dport() = ROUTER_PORT;
03175 new_cmh->next_hop_ = dst_ptr->dst_next_hop_;
03176 new_cmh->addr_type_ = NS_AF_INET;
03177
03178 if(new_iph->daddr() == myaddr_)
03179 ForwardPacket(newp);
03180 else
03181 s.schedule(target_,newp,0);
03182
03183 dst_ptr = dst_ptr->next_;
03184 delete dst_nodes;
03185 dst_nodes = dst_ptr;
03186 }
03187
03188 *level_ptr = tmp_next_hop_level;
03189
03190 if(iph->daddr() == myaddr_) {
03191 ForwardPacket(p);
03192 }
03193 else
03194 s.schedule(target_,p,0);
03195 }
03196 else if(num_dst == 0) {
03197
03198 if(qry_debug_)
03199 trace("Node %d: Dropping query from %d at time %f,num_src_hops %d",myaddr_,iph->saddr(),s.clock(),num_src_hops);
03200
03201 Packet::free(p);
03202 return;
03203 }
03204 }
03205 else {
03206
03207 if(qry_debug_)
03208 trace("Node %d: Forwarding query to node %d at time %f,num_src_hops %d",myaddr_,iph->daddr(),s.clock(),num_src_hops);
03209
03210 if(--iph->ttl_ == 0) {
03211 drop(p, DROP_RTR_TTL);
03212 return;
03213 }
03214
03215 cmh->next_hop_ = get_next_hop(iph->daddr(),next_hop_level+1);
03216
03217 if(cmh->next_hop_ == NO_NEXT_HOP) {
03218 Packet::free(p);
03219 trace("Node %d: Packet dropped because of no next hop info",myaddr_);
03220 return;
03221 }
03222 s.schedule(target_,p,0);
03223 }
03224 }
03225 else {
03226
03227 if(qry_debug_)
03228 trace("Node %d: Forwarding response to node %d at time %f,num_src_hops %d",myaddr_,iph->daddr(),s.clock(),num_src_hops);
03229 if(--iph->ttl_ == 0) {
03230 drop(p, DROP_RTR_TTL);
03231 return;
03232 }
03233
03234
03235 if(query_for_us) {
03236 if(!num_src_hops) {
03237 iph->daddr() = myaddr_;
03238 iph->dport() = 0;
03239 cmh->next_hop_ = myaddr_;
03240 }
03241 else {
03242 --num_src_hops;
03243 *num_src_hops_ptr = (num_src_hops >> 8) & 0xFF;
03244 *(num_src_hops_ptr + 1) = num_src_hops & 0xFF;
03245
03246 cmh->size() -= 4;
03247
03248 iph->daddr() = *last_hop_ptr++;
03249 iph->daddr() = (iph->daddr() << 8) | *last_hop_ptr++;
03250
03251 if(!num_src_hops)
03252 iph->dport() = 0;
03253 else
03254 iph->dport() = ROUTER_PORT;
03255
03256 int relevant_level = *last_hop_ptr;
03257 cmh->next_hop_ = get_next_hop(iph->daddr(),relevant_level);
03258
03259 if(cmh->next_hop_ == NO_NEXT_HOP) {
03260 Packet::free(p);
03261 trace("Node %d: Packet dropped because of no next hop info",myaddr_);
03262 return;
03263 }
03264
03265 *level_ptr = *last_hop_ptr;
03266 }
03267 if(!num_src_hops && iph->daddr() == myaddr_) {
03268
03269
03270 Packet::free(p);
03271 trace("Node %d: Found object %d.%d.%d at (%d,%d) at time %f",myaddr_, (obj_name >> 24) & 0xFF, (obj_name >> 16) & 0xFF, obj_name & 0xFFFF,X,Y,s.clock());
03272 return;
03273 }
03274 else if(iph->daddr() == myaddr_)
03275 ForwardPacket(p);
03276 else
03277 s.schedule(target_,p,0);
03278 }
03279 else {
03280 cmh->next_hop_ = get_next_hop(iph->daddr(),next_hop_level);
03281
03282 if(cmh->next_hop_ == NO_NEXT_HOP) {
03283 Packet::free(p);
03284 trace("Node %d: Packet dropped because of no next hop info",myaddr_);
03285 return;
03286 }
03287 s.schedule(target_,p,0);
03288 }
03289 }
03290 }
03291
03292
03293
03294
03295 NodeIDList *
03296 LandmarkAgent::search_tag(int obj_name, int prev_hop_level, int next_hop_level,nsaddr_t last_hop_id, int *num_dst)
03297 {
03298 ParentChildrenList *pcl = parent_children_list_;
03299 LMNode *child;
03300 compr_taglist *tag_ptr;
03301 int forward = FALSE;
03302 NodeIDList *nlist = NULL, *nlist_ptr = NULL;
03303 int p1, p2, p3, q1, q2, q3;
03304 int match = 0, exact_match = 0;
03305
03306 *num_dst = 0;
03307
03308
03309 while(pcl) {
03310 if(pcl->level_ == 0)
03311 break;
03312 pcl = pcl->next_;
03313 }
03314
03315 if(!pcl)
03316 return(NULL);
03317
03318
03319
03320 tag_ptr = pcl->tag_list_;
03321 while(tag_ptr) {
03322 if(tag_ptr->obj_name_ == obj_name) {
03323 nlist = new NodeIDList;
03324 nlist->dst_node_ = myaddr_;
03325 nlist->dst_next_hop_ = myaddr_;
03326 return(nlist);
03327 }
03328 tag_ptr = tag_ptr->next_;
03329 }
03330
03331
03332
03333
03334
03335
03336
03337 p1 = (obj_name >> 24) & 0xFF;
03338 p2 = (obj_name >> 16) & 0xFF;
03339 p3 = obj_name & 0xFFFF;
03340
03341 pcl = parent_children_list_;
03342 while(pcl) {
03343 if(pcl->level_ == next_hop_level)
03344 break;
03345 pcl = pcl->next_;
03346 }
03347
03348 if(!pcl)
03349 return(NULL);
03350
03351
03352 child = pcl->pchildren_;
03353 while(child) {
03354
03355
03356
03357 forward = FALSE;
03358 if(next_hop_level < prev_hop_level || (child->id_ != last_hop_id && next_hop_level >= prev_hop_level))
03359 forward = TRUE;
03360 if(child->child_flag_ == IS_CHILD && forward) {
03361 tag_ptr = child->tag_list_;
03362 match = 0;
03363 exact_match = 0;
03364 while(tag_ptr) {
03365 q1 = (tag_ptr->obj_name_ >> 24) & 0xFF;
03366 q2 = (tag_ptr->obj_name_ >> 16) & 0xFF;
03367 q3 = tag_ptr->obj_name_ & 0xFFFF;
03368 if(p1 == q1 && p2 == q2 && p3 == q3)
03369 exact_match = 1;
03370 else if((p1 == q1 && p2 == q2 && !q3) || (p1 == q1 && !q2 && !q3))
03371 match = 1;
03372 if(match) {
03373 if(!nlist) {
03374 nlist = new NodeIDList;
03375 nlist_ptr = nlist;
03376 }
03377 else {
03378 nlist_ptr->next_ = new NodeIDList;
03379 nlist_ptr = nlist_ptr->next_;
03380 }
03381 nlist_ptr->dst_node_ = child->id_;
03382 nlist_ptr->dst_next_hop_ = child->next_hop_;
03383 nlist_ptr->next_hop_level_= next_hop_level - 1;
03384 ++(*num_dst);
03385 break;
03386 }
03387 else if(exact_match) {
03388
03389 NodeIDList *n1, *n2;
03390 n1 = nlist;
03391 while(n1) {
03392 n2 = n1;
03393 n1 = n1->next_;
03394 delete n2;
03395 }
03396
03397
03398 nlist = new NodeIDList;
03399 nlist->dst_node_ = child->id_;
03400 nlist->dst_next_hop_ = child->next_hop_;
03401 nlist->next_hop_level_= next_hop_level - 1;
03402 (*num_dst) = 1;
03403 return(nlist);
03404 }
03405 tag_ptr = tag_ptr->next_;
03406 }
03407 }
03408 child = child->next_;
03409 }
03410
03411
03412 if(next_hop_level >= prev_hop_level && pcl->parent_) {
03413 if(!nlist) {
03414 nlist = new NodeIDList;
03415 nlist_ptr = nlist;
03416 }
03417 else {
03418 nlist_ptr->next_ = new NodeIDList;
03419 nlist_ptr = nlist_ptr->next_;
03420 }
03421 nlist_ptr->dst_node_ = (pcl->parent_)->id_;
03422 nlist_ptr->dst_next_hop_ = (pcl->parent_)->next_hop_;
03423 nlist_ptr->next_hop_level_= next_hop_level + 1;
03424 ++(*num_dst);
03425 }
03426
03427 return(nlist);
03428 }
03429
03430
03431
03432 nsaddr_t
03433 LandmarkAgent::get_next_hop(nsaddr_t dst, int next_hop_level)
03434 {
03435 ParentChildrenList *pcl = parent_children_list_;
03436 LMNode *pchild;
03437
03438 while(pcl->level_ != next_hop_level) {
03439 pcl = pcl->next_;
03440 }
03441
03442 assert(pcl);
03443 pchild = pcl->pchildren_;
03444 while(pchild) {
03445 if(pchild->id_ == dst)
03446 return(pchild->next_hop_);
03447 pchild = pchild->next_;
03448 }
03449
03450 return(NO_NEXT_HOP);
03451 }
03452
03453
03454 void
03455 LandmarkAgent::get_nbrinfo()
03456 {
03457 ParentChildrenList *pcl;
03458 LMNode *pchild;
03459 int num_nbrs = 0;
03460
03461 pcl = parent_children_list_;
03462
03463 if(!pcl) {
03464 trace("Node %d: Neighbour info not available; perhaps the node is down");
03465 return;
03466 }
03467
03468 while(pcl) {
03469 if(pcl->level_ == 1)
03470 break;
03471 pcl = pcl->next_;
03472 }
03473
03474
03475
03476 if(!pcl) {
03477 trace("Node %d: Neighbour info not available; perhaps the node is down");
03478 return;
03479 }
03480
03481 pchild = pcl->pchildren_;
03482
03483
03484 while(pchild) {
03485 if(pchild->num_hops_ == 1)
03486 ++num_nbrs;
03487 pchild = pchild->next_;
03488 }
03489
03490 trace("Node %d: Number of neighbours: %d",myaddr_,num_nbrs);
03491 }
03492
03493
03494
03495
03496 void
03497 LandmarkAgent::MoveTags() {
03498 ParentChildrenList *pcl = parent_children_list_;
03499 compr_taglist *tag = NULL, *prev_tag, *next_tag;
03500 int removed_tag = 0, our_tags_changed = 0;
03501
03502 trace("Node %d: Moving tags at time %f", myaddr_,NOW);
03503
03504 if(!pcl && !mobile_tags_) {
03505 Scheduler::instance().schedule(tag_mobility_,tag_mobility_event_,tag_rng_->uniform(mobility_period_));
03506 return;
03507 }
03508
03509 if(pcl) {
03510
03511 while(pcl) {
03512 if(pcl->level_ == 0)
03513 break;
03514 pcl = pcl->next_;
03515 }
03516 assert(pcl);
03517 }
03518
03519
03520
03521 if(pcl)
03522 tag = pcl->tag_list_;
03523 else
03524 tag = mobile_tags_;
03525
03526 prev_tag = tag;
03527 while(tag) {
03528 removed_tag = 0;
03529
03530 if((tag->obj_name_ & 0xFFFF) > 30) {
03531
03532 int n = tag_rng_->uniform(10);
03533 if(n <= 2) {
03534 assert(nbrs_);
03535 int nbr_index = tag_rng_->uniform(num_nbrs_);
03536 LandmarkAgent *nbr_agent = (LandmarkAgent *)AgentList::instance()->GetAgent(nbrs_[nbr_index]);
03537 assert(nbr_agent);
03538
03539 trace("Node %d: Moving tag %d.%d.%d at time %f to nbr %d",myaddr_,(tag->obj_name_ >> 24) & 0xFF,(tag->obj_name_ >> 16) & 0xFF,tag->obj_name_ & 0xFFFF,NOW,nbrs_[nbr_index]);
03540
03541
03542 removed_tag = 1;
03543 our_tags_changed = 1;
03544 if(prev_tag == tag) {
03545 if(pcl)
03546 pcl->tag_list_ = tag->next_;
03547 else if(mobile_tags_)
03548 mobile_tags_ = tag->next_;
03549 prev_tag = tag->next_;
03550 }
03551 else
03552 prev_tag->next_ = tag->next_;
03553
03554 next_tag = tag->next_;
03555
03556 if(pcl)
03557 --(pcl->num_tags_);
03558
03559
03560 nbr_agent->AddMobileTag(tag);
03561 }
03562 }
03563 if(!removed_tag) {
03564 prev_tag = tag;
03565 tag = tag->next_;
03566 }
03567 else {
03568 tag = next_tag;
03569 }
03570 }
03571
03572
03573 if(our_tags_changed)
03574 SendChangedTagListUpdate(our_tags_changed,0);
03575
03576 Scheduler::instance().schedule(tag_mobility_,tag_mobility_event_,tag_rng_->uniform(mobility_period_));
03577 }
03578
03579
03580
03581
03582
03583 void
03584 LandmarkAgent::AddMobileTag(void *mobile_tag)
03585 {
03586 ParentChildrenList *pcl = parent_children_list_;
03587 compr_taglist *tag = NULL, *new_tag = (compr_taglist *)mobile_tag;
03588
03589
03590
03591 new_tag->next_ = NULL;
03592
03593 if(pcl) {
03594
03595 while(pcl) {
03596 if(pcl->level_ == 0)
03597 break;
03598 pcl = pcl->next_;
03599 }
03600 assert(pcl);
03601
03602 ++(pcl->num_tags_);
03603
03604 if(!pcl->tag_list_) {
03605 pcl->tag_list_ = new_tag;
03606 }
03607 else {
03608 tag = pcl->tag_list_;
03609 while(tag->next_) {
03610 tag = tag->next_;
03611 }
03612 tag->next_ = new_tag;
03613 }
03614 }
03615 else {
03616 if(!mobile_tags_) {
03617 mobile_tags_ = new_tag;
03618 }
03619 else {
03620 tag = mobile_tags_;
03621 while(tag->next_) {
03622 tag = tag->next_;
03623 }
03624 tag->next_ = new_tag;
03625 }
03626 }
03627
03628
03629
03630 if(tag_advt_event_->uid_ < 0)
03631 Scheduler::instance().schedule(tag_advt_handler_, tag_advt_event_, Random::uniform(10));
03632 }
03633
03634
03635
03636
03637
03638
03639
03640 void
03641 LandmarkAgent::SendChangedTagListUpdate(int our_tag_changed, int level)
03642 {
03643 ParentChildrenList *pcl = parent_children_list_;
03644 ParentChildrenList *child_pcl, *parent_pcl;
03645 compr_taglist *tag_ptr1 = NULL, *tag_ptr2 = NULL, *tag_list = NULL;
03646 compr_taglist *agg_tags = NULL;
03647 LMNode *lmnode;
03648 int upd_time, num_tags = 0;
03649 Scheduler &s = Scheduler::instance();
03650 double now = s.clock();
03651
03652 if(node_dead_ || !pcl || level >= highest_level_)
03653 return;
03654
03655 if(myaddr_ == 45)
03656 trace("Node %d: SendChangedTagListUpdate, level %d at time %f",myaddr_,level,now);
03657
03658 while(pcl) {
03659 if(pcl->level_ == level)
03660 child_pcl = pcl;
03661 else if(pcl->level_ == level + 1)
03662 parent_pcl = pcl;
03663 pcl = pcl->next_;
03664 }
03665
03666 if(our_tag_changed) {
03667 assert(level == 0);
03668 upd_time = (int) now;
03669 upd_time = (upd_time << 16) | (parent_pcl->seqnum_ & 0xFFFF);
03670 ++(parent_pcl->seqnum_);
03671 parent_pcl->UpdatePotlChild(myaddr_, myaddr_,0,0,0,(int) node_->energy(),upd_time,IS_CHILD,FALSE,child_pcl->tag_list_);
03672
03673
03674 Packet *newp = makeUpdate(child_pcl,HIER_ADVS,PERIODIC_ADVERTS);
03675 child_pcl->last_update_sent_ = now;
03676 s.schedule(target_,newp,0);
03677 }
03678
03679 while(level < highest_level_) {
03680
03681 if(myaddr_ == 45)
03682 trace("Node %d: Updating tag lists, level %d",myaddr_,level);
03683
03684 lmnode = parent_pcl->pchildren_;
03685 tag_list = NULL;
03686
03687
03688 while(lmnode) {
03689 if(lmnode->child_flag_ == IS_CHILD) {
03690 tag_ptr1 = lmnode->tag_list_;
03691
03692 while(tag_ptr1) {
03693 if(!tag_list) {
03694 tag_list = new compr_taglist;
03695 tag_ptr2 = tag_list;
03696 }
03697 else {
03698 tag_ptr2->next_ = new compr_taglist;
03699 tag_ptr2 = tag_ptr2->next_;
03700 }
03701
03702 tag_ptr2->obj_name_ = tag_ptr1->obj_name_;
03703 tag_ptr1 = tag_ptr1->next_;
03704 }
03705 }
03706 lmnode = lmnode->next_;
03707 }
03708
03709
03710 agg_tags = aggregate_taginfo(tag_list,parent_pcl->level_,&num_tags);
03711
03712
03713 tag_ptr1 = tag_list;
03714 while(tag_ptr1) {
03715 tag_ptr2 = tag_ptr1;
03716 tag_ptr1 = tag_ptr1->next_;
03717 delete tag_ptr2;
03718 }
03719
03720 if(!compare_tag_lists(parent_pcl->tag_list_,parent_pcl->num_tags_,agg_tags,num_tags)) {
03721
03722 tag_ptr1 = parent_pcl->tag_list_;
03723 while(tag_ptr1) {
03724 tag_ptr2 = tag_ptr1;
03725 tag_ptr1 = tag_ptr1->next_;
03726 delete tag_ptr2;
03727 }
03728
03729 parent_pcl->tag_list_ = agg_tags;
03730 parent_pcl->num_tags_ = num_tags;
03731
03732
03733 Packet *newp = makeUpdate(parent_pcl,HIER_ADVS,PERIODIC_ADVERTS);
03734 parent_pcl->last_update_sent_ = now;
03735 s.schedule(target_,newp,0);
03736
03737 ++level;
03738
03739 pcl = parent_children_list_;
03740 parent_pcl = NULL;
03741 child_pcl = NULL;
03742 while(pcl) {
03743 if(pcl->level_ == level)
03744 child_pcl = pcl;
03745 else if(pcl->level_ == level + 1)
03746 parent_pcl = pcl;
03747 pcl = pcl->next_;
03748 }
03749 upd_time = (int) now;
03750 upd_time = (upd_time << 16) | (parent_pcl->seqnum_ & 0xFFFF);
03751 ++(parent_pcl->seqnum_);
03752 parent_pcl->UpdatePotlChild(myaddr_, myaddr_,0,0,0,(int) node_->energy(),upd_time,IS_CHILD,FALSE,child_pcl->tag_list_);
03753 }
03754 else {
03755
03756
03757 tag_ptr1 = agg_tags;
03758 while(tag_ptr1) {
03759 tag_ptr2 = tag_ptr1;
03760 tag_ptr1 = tag_ptr1->next_;
03761 delete tag_ptr2;
03762 }
03763 break;
03764 }
03765 }
03766 }
03767
03768
03769
03770
03771 int
03772 LandmarkAgent::compare_tag_lists(compr_taglist *tag_list1, int num_tags1, compr_taglist *tag_list2, int num_tags2)
03773 {
03774 compr_taglist *tag1 = tag_list1, *tag2 = tag_list2;
03775 int found;
03776
03777
03778 if(num_tags1 == -1) {
03779 num_tags1 = 0;
03780 while(tag1) {
03781 ++num_tags1;
03782 tag1 = tag1->next_;
03783 }
03784 tag1 = tag_list1;
03785 }
03786
03787 if(num_tags2 == -1) {
03788 num_tags2 = 0;
03789 while(tag2) {
03790 ++num_tags2;
03791 tag2 = tag2->next_;
03792 }
03793 tag2 = tag_list2;
03794 }
03795
03796 if(num_tags1 != num_tags2)
03797 return(FALSE);
03798
03799 while(tag1) {
03800 found = 0;
03801 while(tag2) {
03802 if(tag1->obj_name_ == tag2->obj_name_) {
03803 found = 1;
03804 break;
03805 }
03806 tag2 = tag2->next_;
03807 }
03808 if(!found)
03809 return(FALSE);
03810 tag1 = tag1->next_;
03811 }
03812
03813 return(TRUE);
03814 }
03815