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

landmark.cc

Go to the documentation of this file.
00001 // Copyright (c) 2000 by the University of Southern California
00002 // All rights reserved.
00003 //
00004 // Permission to use, copy, modify, and distribute this software and its
00005 // documentation in source and binary forms for non-commercial purposes
00006 // and without fee is hereby granted, provided that the above copyright
00007 // notice appear in all copies and that both the copyright notice and
00008 // this permission notice appear in supporting documentation. and that
00009 // any documentation, advertising materials, and other materials related
00010 // to such distribution and use acknowledge that the software was
00011 // developed by the University of Southern California, Information
00012 // Sciences Institute.  The name of the University may not be used to
00013 // endorse or promote products derived from this software without
00014 // specific prior written permission.
00015 //
00016 // THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
00017 // the suitability of this software for any purpose.  THIS SOFTWARE IS
00018 // PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
00019 // INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00020 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 //
00022 // Other copyrights might apply to parts of this software and are so
00023 // noted when applicable.
00024 //
00025 // $Header: /nfs/jade/vint/CVSROOT/ns-2/sensor-nets/landmark.cc,v 1.7 2000/09/01 03:04:11 haoboy Exp $
00026 
00027 // Author: Satish Kumar, kkumar@isi.edu
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   // Delete the old tag list if it exists
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   // Copy the specified taglist
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 // Returns a random number between 0 and max
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 // Returns a random number between 0 and max
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   // Cancel any running timers and reset relevant variables
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   // Reset highest level of node
00112   highest_level_ = 0;
00113 
00114   // Delete ParentChildrenList objects for all levels
00115   while(pcl) {
00116     tmp_pcl = pcl;
00117     pcl = pcl->next_;
00118     delete tmp_pcl;
00119   }
00120   parent_children_list_ = NULL;
00121 
00122   // Indicate that node is dead so that packets will not be processed
00123   node_dead_ = 1;
00124 
00125   global_lm_id_ = NO_GLOBAL_LM;
00126   global_lm_level_ = -1;
00127 
00128   // Event id > 0 for scheduled event
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; // Define a variable ap that will refer to each argument in turn
00143 
00144   if (!tracetarget_)
00145     return;
00146 
00147   // Initializes ap to first argument
00148   va_start (ap, fmt); 
00149   // Prints the elements in turn
00150   vsprintf (tracetarget_->buffer (), fmt, ap); 
00151   tracetarget_->dump ();
00152   // Does the necessary clean-up before returning
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   //  bind_time ("promo_timeout_", "&promo_timeout_");
00179   num_resched_ = 0;
00180   tag_dbase_ = NULL;
00181   node_ = NULL;
00182 
00183   cache_ = 0; // default is to disable caching
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   // default value for the update period
00191   update_period_ = 400;
00192   update_timeout_ = update_period_ + 4 * LM_STARTUP_JITTER;
00193 
00194   adverts_type_ = FLOOD;  // default is to flood adverts
00195   global_lm_ = 0; // No global LMs by default
00196   global_lm_id_ = NO_GLOBAL_LM;
00197   global_lm_level_ = -1;
00198 
00199   // myaddr_ not defined at this point ... So use lm_index for init
00200   rn_ = new RNG(RNG::RAW_SEED_SOURCE,lm_index++);;
00201   // Throw away a bunch of initial values
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   //  bind ("myaddr_", &myaddr_);
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   // myaddr_ not defined at this point ... So use lm_index for init
00219   tag_rng_ = new RNG(RNG::RAW_SEED_SOURCE,lm_index++);;
00220   // Throw away a bunch of initial values
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   // If object already exists in cache, update info if necessary
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     // Use LRU cache replacement
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   // Extract seqnum and origin time
00305   int seqnum = origin_time & 0xFFFF;
00306   origin_time = origin_time >> 16;
00307   
00308   assert(num_pparent_ >= 0);
00309 
00310   // cannot delete from an empty list!
00311   if(delete_flag && !pparent_)
00312     return(ENTRY_NOT_FOUND);
00313 
00314   //  if((a_->debug_) && (a_->myaddr_ == 24)) {
00315   //    a_->trace("Node %d: Updating Potl Parent level %d, id %d, delete_flag %d, time %f",a_->myaddr_,level_,id,delete_flag,now);
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       // Check if this is a old message floating around in the network
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         // Check if we got the old update on a shorter path
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         // Make this node as parent if it's closer than current parent
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 { // delete the entry
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         // No parent if potl parent list is empty
00367         if(pparent_ == NULL) {
00368           parent_ = NULL;
00369         }
00370         else if(parent_ == list_ptr) {
00371         // Select new parent if current parent is deleted and
00372         // potl parent is not empty; closest potl parent is new parent
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   // Make this node as parent if it's closer than current parent
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   //  if(a_->debug_) printf("Node %d: Number of potl children %d",a_->myaddr_,num_potl_children_);
00420 
00421   // cannot delete from an empty list!
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       // Check if this is a old message floating around in the network
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         // Check if we got this update on a shorter path; If the update rcvd
00451         // on a shorter path, we need to forward this message to ensure that
00452         // this message reaches all nodes in the advertising node's vicinity
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         // Old entry but the status has changed to child or vice-versa
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           // Delete the old tag list and copy the specified taglist
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   // delete flag must be FALSE if we are here
00510   // assert(!delete_flag);
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   // Packet will have seqnum, level, vicinity radii, parent info
00552   // and possibly potential children (if the node is at level > 0)
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   //  if(now > 412.5) {
00559   //    purify_printf("ProcessHierUpdate1, %f, %d\n",now,myaddr_);
00560   //    purify_new_leaks();
00561   //  }
00562 
00563 
00564   //  if(debug_)
00565   //    trace("Node %d: Received packet from %d with ttl %d", myaddr_,iph->saddr(),iph->ttl_);
00566 
00567   walk = p->accessdata();
00568 
00569   // Originator of the LM advertisement and the next hop to reach originator
00570   origin_id = iph->saddr();    
00571 
00572   // Free and return if we are seeing our own packet again
00573   if(origin_id == myaddr_) {
00574     Packet::free(p);
00575     return;
00576   }
00577   
00578   // type of advertisement
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   // level of the originator
00596   level = *walk++;
00597 
00598     //    if(num_advert_lm_addrs)
00599     //      trace("Node 10: Rcved msg from 0, level %d, num_lm_addrs %d, advert_lm_addrs %x, time %f",level,num_advert_lm_addrs,advert_lm_addrs[0],now);
00600 
00601   //  trace("Node %d: Processing Hierarchy Update Packet", myaddr_);
00602 
00603   //  if((myaddr_ == 153) && (origin_id == 29)) {
00604   //    trace("Node 153: Receiving level %d update from node 29 at time %f,action = %d",level,s.clock(),action);
00605   //  }
00606 
00607   // energy level of advertising node
00608   energy = *walk++;
00609   energy = (energy << 8) | *walk++;
00610   energy = (energy << 8) | *walk++;
00611   energy = (energy << 8) | *walk++;
00612 
00613   // next hop info
00614   next_hop = *walk++;
00615   next_hop = (next_hop << 8) | *walk;
00616 
00617   // Change next hop to ourselves for the outgoing packet
00618   --walk;
00619   (*walk++) = (myaddr_ >> 8) & 0xFF;
00620   (*walk++) = (myaddr_) & 0xFF;
00621   
00622   // vicinity radius
00623   vicinity_radius = *walk++;
00624   vicinity_radius = (vicinity_radius << 8) | *walk++;
00625   // number of hops away from advertising LM
00626   num_hops = vicinity_radius - (iph->ttl_ - 1);
00627 
00628   //  if(myaddr_ == 155)
00629   //    trace("Node 155: Receiving level %d update from node %d at time %f,action = %d, num_hops = %d",level,origin_id,s.clock(),action,num_hops);
00630 
00631   // origin time of advertisement
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   //  if(debug_ && myaddr_ == 33)
00638   //    trace("Node %d: Processing level %d pkt from %d at t=%f, origin %d, num hops %d", myaddr_,level,iph->saddr_,now,origin_time,num_hops);
00639 
00640 
00641   // Parent of the originator
00642   parent = *walk++;
00643   parent = parent << 8 | *walk++;
00644 
00645   // Number of hops has to be less than vicinity radius to ensure that atleast
00646   // 2 level K LMs see each other if they exist
00647   if(level > 0 && (action == PERIODIC_ADVERTS || action == GLOBAL_ADVERT || action == UNICAST_ADVERT_CHILD || action == UNICAST_ADVERT_PARENT)) {
00648     // Number of children
00649     num_children = *walk++;
00650     num_children = num_children << 8 | *walk++;
00651 
00652     // Number of potential children
00653     num_potl_children = *walk++;
00654     num_potl_children = num_potl_children << 8 | *walk++;
00655 
00656   // If level of advertising LM > 1, check if we are in potl children list.
00657   // If so, add as potl parent to level - 1
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   // Store tag info only if the level of advertising LM is less than 
00696   // our highest level; otherwise we dont need this information
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       //        trace("tag name: %d.%d.%d",(tag_ptr->obj_name_ >> 24) & 0xFF,(tag_ptr->obj_name_ >> 16) & 0xFF,(tag_ptr->obj_name_) & 0xFFFF);
00712     }
00713   }
00714 
00715   //  if(level == 253)
00716   //    trace("Level is 253 at time %f\n",now);
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   // Insert parent-child objects for levels: level-1 (if level > 0) & level + 1
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   // check if level > 0
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   // If level is same as our level, we can decrease the promotion timer 
00752   // if it's running provided we havent already heard advertisements from
00753   // this node
00754 
00755   int delete_flag = FALSE; // Add the child/potl parent entry
00756   if(action == DEMOTION) delete_flag = TRUE;
00757   int child_flag = NOT_CHILD; // Indicates whether this node is our child
00758   if(parent == myaddr_) 
00759     child_flag = IS_CHILD;
00760   else if(action == GLOBAL_ADVERT && num_hops > vicinity_radius) 
00761   // The global LM may not be a potential child for us at any level if
00762   // it is farther away than the vicinity radius
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   // Free packet and return if we have seen this packet before
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     // Free the tag list
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   // Send hierarchy advts if tag list has changed due to new child 
00785   // or change in the taglist of an old child
00786   if(ret_value == NEW_CHILD || ret_value == OLD_CHILD_TAGS_CHANGED)
00787     SendChangedTagListUpdate(0,level);
00788   
00789   
00790   //  if(level == highest_level_)
00791   //     num_resched_ = (*pcl2)->num_potl_children_ - 1;
00792 
00793   // If promotion timer is running, decrement by constant amount
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     // Promotion timer is running but is not in wait state
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       //      trace("Node %d: Rescheduling timer in ProcessHierUpdate, now %f, st %f, decr %f, resch %f\n", myaddr_, now, promo_start_time_, promo_timeout_decr_, resched_time);
00800       promo_timer_->resched(resched_time);
00801     }
00802   }
00803 
00804   // If our parent has demoted itself, we might have to start 
00805   // the election process again
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       //      if (debug_) printf("Node %d: sched timer in ProcessHierUpdate\n",myaddr_);
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         // Cancel any timer running in wait state
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   // If the advertising LM is a potl parent, add to level-1 
00842   // ParentChildrenList object
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     // If we receive this message from a parent at some level, update
00848     // the assigned addresses
00849     if((((*pcl1)->parent_)->id_ == origin_id) && (level-1 == highest_level_)) {
00850       //      if(num_lm_addrs) 
00851       //        trace("Node %d: Rcvd higher level lm addr from %d at time %f",myaddr_,origin_id,now);
00852       //      else
00853       //        trace("Node %d: Rcvd higher level lm addr msg with no addrs from %d at time %f",myaddr_,origin_id,now);
00854       ((*pcl1)->mylmaddrs_)->delete_lm_addrs();
00855       assign_lmaddress(lm_addrs, num_lm_addrs, (*pcl1)->level_);
00856     }
00857 
00858     // Check if parent has changed
00859     int new_advert = 0;
00860     // The first condition may arise if the old parent obj is deleted ... (?)
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     // Trigger advertisement if parent has changed
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   // If a parent has been selected for highest_level_, cancel promotion timer
00880   // (for promotion to highest_level_+1) if it's running
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       // Check if the potl parent for highest_level_-1 that we see covers our
00894       // potential children. If so, we can demote ourselves and cancel our 
00895       // current promotion timer
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       // Demotion process
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         // Send out demotion messages
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   // If new entry, flood advertisements for level > adv LM's level
00966   if(ret_value == NEW_ENTRY) {
00967     ParentChildrenList *tmp_pcl = parent_children_list_;
00968     while(tmp_pcl) {
00969       // New nodes should have an initial wait time of atleast 0.1 seconds
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   // Delete tag list
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   // Do not forward demotion message if we have seen this message before
00991   if(action == DEMOTION) {
00992     //    if(myaddr_ == 30)
00993     //      printf("Am here\n");
00994     if(CheckDemotionMsg(origin_id, level, (int)origin_time) == OLD_MESSAGE) {
00995       Packet::free(p);
00996       return;
00997     }
00998   }
00999 
01000   // Do not forward packet if ttl is lower unless the packet is from the global
01001   // LM in which case the packet needs to be flooded throughout the network
01002   if(--iph->ttl_ == 0 && action != GLOBAL_ADVERT) {
01003     //    drop(p, DROP_RTR_TTL);
01004     Packet::free(p);
01005     return;
01006   }
01007 
01008   // Do not forward if the advertisement is for this node
01009   if((iph->daddr() >> 8) == myaddr_) {
01010     //    trace("Node %d: Received unicast advert from %d at level %d for us at time %f",myaddr_,iph->saddr(),level,now);
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     //    if(myaddr_ == 153)
01018     //      trace("Node %d: Received child unicast advert from %d to %d at level %d at time %f, next hop %d",myaddr_,iph->saddr(),iph->daddr(),level,now,hdrc->next_hop());
01019   }
01020   else if(action == UNICAST_ADVERT_PARENT) {
01021     //    trace("Node %d: Received parent unicast advert from %d to %d at level %d at time %f",myaddr_,iph->saddr(),iph->daddr(),level,now);
01022     hdrc->next_hop() = get_next_hop(iph->daddr(),level+2);
01023   }
01024   
01025   assert(hdrc->next_hop() != NO_NEXT_HOP);
01026 
01027   //  if(now > 412.5) {
01028   //    purify_printf("ProcessHierUpdate2\n");
01029   //    purify_new_leaks();
01030   //  }
01031 
01032   // Need to send the packet down the stack
01033   hdrc->direction() = hdr_cmn::DOWN;
01034   
01035   //  if(debug_) printf("Node %d: Forwarding Hierarchy Update Packet", myaddr_);
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   //  assert(root_level != 0);
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     // Update LM address at the appropriate level
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       // ID at a particular level starts from 1
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         // Assign addresses to child nodes
01101         
01102         //      while( j <= MAX_CHILDREN) {
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             //      if(j > MAX_CHILDREN) break;
01117             assert(j <= MAX_CHILDREN);
01118           } /* if */
01119           pchild = pchild->next_;
01120           //      }/* while */
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   //  if(debug_) printf("Periodic Callback for level %d", level);
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   //  if(now > 412.5) {
01147   //    purify_printf("periodic_callback1: %f,%d\n",now,myaddr_);
01148   //    purify_new_leaks();
01149   //  }
01150 
01151   //  if(myaddr_ == 12 && now > 402)
01152   //    purify_new_leaks();
01153 
01154   // Should always have atleast the level 0 object
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   // return if we have been demoted from this level
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   // Create level+1 object if it doesnt exist
01185   if(!pcl2) {
01186     new_pcl->next_ = new ParentChildrenList(level+1, this);
01187     pcl2 = new_pcl->next_;
01188   }
01189 
01190   assert(pcl2);
01191 
01192   // Delete stale potential parent entries
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     // Record next entry in linked list incase the current element is deleted
01199     tmp_lmnode = lmnode->next_;
01200     if(((now - lmnode->last_update_rcvd_) > cur_pcl->update_timeout_)) {
01201       //      if(debug_) trace("Node %d: Deleting stale entry for %d at time %d",myaddr_,lmnode->id_,(int)now);
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   // The first condition may arise if the old parent obj is deleted ... (?)
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   // Delete stale potential children entries
01223   lmnode = cur_pcl->pchildren_;
01224   delete_flag = TRUE;
01225   int demotion = FALSE;
01226   while(lmnode) {
01227     // Record next entry in linked list incase the current element is deleted
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   // Send updates if tag list has changed i.e., when a child has changed
01241   if(child_changed)
01242     SendChangedTagListUpdate(0,level-1);
01243   
01244   // Demote ourself if any child's energy > 30 % of our energy
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   // Check if a parent exists after updating potl parents. If not, start
01254   // promotion timer.
01255   // A LM at level 3 is also at levels 0, 1 and 2. For each of these levels,
01256   // the LM designates itself as parent. At any given instant, only the 
01257   // level 3 (i.e., highest_level_) LM may not have a parent and may need to 
01258   // promote itself. But if the promotion timer is running, then the election
01259   // process for the next level has already begun.
01260 
01261   if(parent_changed && (cur_pcl->parent_ == NULL) && !demotion) {
01262 
01263     // Cancel any promotion timer that is running for promotion from a higher 
01264     // level and send out demotion messages
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       //        trace("Node %d: Entering wait period in periodic_callback at time %f", myaddr_,now);
01289       promo_timer_->resched(wait_time);
01290     }
01291   }
01292 
01293   // Update ourself as potential child and parent for appropriate levels
01294   // in our hierarchy tables
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   // Check if this is the root node. If so, set the unicast flag or suppress
01309   // flag when no changes occur for 3 times the update period
01310   // If this is a lower level node that has a parent, either suppress 
01311   // (for hard-state case) or unicast maintenance messages
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     // Start assigning landmark addresses to child nodes; 
01321     // Shift 1, number of levels * 8 times to left for address of root node
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     // The advertisements from the root LM need to be broadcast in the hash
01328     // scheme
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   //  if(!demotion && (now - cur_pcl->last_update_sent_ >= cur_pcl->update_period_) && !suppress_flag) 
01343   if(!demotion && !suppress_flag) {
01344     //    trace("Node %d: Sending update at time %f",myaddr_,now);
01345     Packet *p = makeUpdate(cur_pcl, HIER_ADVS, action);
01346     unsigned char *walk;
01347     if(unicast_flag) {
01348       if(level) {
01349         // Unicast updates to parent and children for level > 0
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             //    trace("Node %d: Generating unicast advert to child %d at time %f with next hop %d",myaddr_,lmnode->id_,now,lmnode->next_hop_);
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             // Update seqnum field for each packet; Otherwise subsequent 
01371             // (to first) messages would be dropped by intermediate nodes
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           //      trace("Node %d: Generating unicast advert to parent %d at time %f with next hop %d",myaddr_,cur_pcl->parent_->id_,now,(cur_pcl->parent_)->next_hop_);
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           // Update seqnum field for each packet; Otherwise subsequent 
01402           // (to first) messages would be dropped by intermediate nodes
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       //      trace("Node %d: Generating update msg at time %f",myaddr_,now);
01419       s.schedule(target_, p, 0);
01420     }
01421     cur_pcl->last_update_sent_ = now;
01422   }
01423 
01424   // Schedule next update 
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   //  if(now > 412.5) {
01435   //    purify_printf("periodic_callback2: %f,%d\n",now,myaddr_);
01436   //    purify_new_leaks();
01437   //  }
01438 
01439   //  if(myaddr_ == 12 && now > 402)
01440   //    purify_new_leaks();
01441 
01442   // Update entries for levels greater than our highest level in our
01443   // highest_level_ periodic_callback event
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           // Update potential parent list
01453           // Record next entry in list incase current element is deleted
01454           tmp_lmnode = lmnode->next_;
01455           if(((now - lmnode->last_update_rcvd_) > cur_pcl->update_timeout_)) {
01456             //      if(debug_) trace("Node %d: Deleting stale entry for %d at time %d",myaddr_,lmnode->id_,(int)now);
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         // Update children list
01465         lmnode = cur_pcl->pchildren_;
01466         while(lmnode) {
01467           // Record next entry in list incase current element is deleted
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             // Check if global LM entry is being deleted; Global LM at level i
01473             // will have entry in level i+1 pcl object
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; // need to broadcast packet
01505   hdrc->addr_type_ = NS_AF_INET;
01506   iph->daddr() = IP_BROADCAST;  // packet needs to be 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       // A level 0 node cannot be demoted!
01522       assert(action != DEMOTION);
01523 
01524       // No children for level 0 LM
01525       // totally 12 bytes in packet for now; need to add our energy level later
01526       // each tag name is 4 bytes; 2 bytes for num_tags info
01527       // Landmark address; 1 byte to indicate #addrs and 8 bytes for each addr
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       // Packet type; 1 byte
01536       (*walk++) = (action) & 0xFF;
01537 
01538       // Landmark address; 1 byte to indicate #addrs and 8 bytes for each addr
01539       (*walk++) = (num_lm_addrs) & 0xFF;
01540       //      if(num_lm_addrs)
01541       //        trace("Num_lm_addrs = %d",num_lm_addrs);
01542       for(int i = 0; i < num_lm_addrs; ++i) {
01543         // Landmark address of node
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       // level of LM advertisement; 1 byte
01557       (*walk++) = (pcl->level_) & 0xFF;
01558 
01559       // Our energy level; 4 bytes (just integer portion)
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       // make ourselves as next hop; 2 bytes
01567       (*walk++) = (myaddr_ >> 8) & 0xFF;
01568       (*walk++) = (myaddr_) & 0xFF;
01569 
01570       // Vicinity size in number of hops; Carrying this information allows
01571       // different LMs at same level to have different vicinity radii; 2 bytes
01572       (*walk++) = (radius(pcl->level_) >> 8) & 0xFF;
01573       (*walk++) = (radius(pcl->level_)) & 0xFF;
01574 
01575       // Time at which packet was originated;
01576       // 3 bytes for integer portion of time and 1 byte for fraction
01577       // Note that we probably need both an origin_time and sequence number
01578       // field to distinguish between msgs generated at same time.
01579       // (origin_time required to discard old state when net dynamics present)
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       // Parent ID; 2 bytes
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       // In real life each of the above fields would be 
01611       // 4 byte integers; 20 bytes for IP addr + 2 bytes for num_children
01612       // 4 byte for number of tags; 4 byte for each tag name; 4 byte for energy
01613       hdrc->size_ = 20 + 20 + 4 + (4 * pcl->num_tags_) + 4 + 1 + (8*num_lm_addrs); 
01614     }
01615     else {
01616       // Need to list all the potential children LMs
01617       // Pkt size: 12 bytes (as before); 2 each for number of children 
01618       // and potl_children; 
01619       // 2 byte for each child's id + 8 bytes for landmark address
01620       // 4 bytes for each tag name; 2 bytes for num_tags info
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         // Compute number of landmark addrs of children for pkt size calc
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         // Compute number of landmark addrs of this node for pkt size calc
01639         // Landmark address; 1 byte to indicate #addrs and 8 bytes for each 
01640         // addr
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; // Demotion message
01647 
01648       p->allocdata(pkt_size);
01649       walk = p->accessdata();
01650 
01651       // Packet type; 1 byte
01652       (*walk++) = (action) & 0xFF;
01653 
01654       //      if(myaddr_ == 0)
01655       //        trace("Node 0: Generating update message for level %d at time %f, num_lm_addrs %d",pcl->level_,now,num_lm_addrs);
01656 
01657       // Landmark address; 1 byte to indicate #addrs and 8 bytes for each addr
01658       (*walk++) = (num_lm_addrs) & 0xFF;
01659       for(int i = 0; i < num_lm_addrs; ++i) {
01660         // Landmark address of node
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       // level of LM advertisement; 1 byte
01675       (*walk++) = (pcl->level_) & 0xFF;
01676 
01677       // Our energy level; 4 bytes (just integer portion)
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       // make ourselves as next hop; 2 bytes
01685       (*walk++) = (myaddr_ >> 8) & 0xFF;
01686       (*walk++) = (myaddr_) & 0xFF;
01687 
01688       // Vicinity size in number of hops; 2 bytes
01689       (*walk++) = (radius(pcl->level_) >> 8) & 0xFF;
01690       (*walk++) = (radius(pcl->level_)) & 0xFF;
01691 
01692       // Time at which packet was originated;
01693       // 3 bytes for integer portion of time and 1 byte for fraction
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       // Parent's id; 2 bytes
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         // Number of children; 2 bytes
01718         (*walk++) = (pcl->num_children_ >> 8) & 0xFF;
01719         (*walk++) = (pcl->num_children_) & 0xFF;
01720         
01721         // Number of potential children; 2 bytes
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             //      if(myaddr_ == 0 && now > 1000)
01735             //        trace("Node 0: Child %d, num_addrs: %d at time %f",potl_ch->id_,num_addrs,now);
01736 
01737             // Number of landmark addrs
01738             (*walk++) = (num_addrs) & 0xFF;
01739             for(int i = 0; i < num_addrs; ++i) {
01740               // Landmark address of node
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         // 8 addl bytes for num_children and num_potl_children info; Assuming 
01770         // worst case of 8 levels in computing packet size
01771         // SHOULD DISABLE SENDING TAG INFO IN THE HASH SCHEME
01772         // Landmark address; 1 byte to indicate #addrs and 8 bytes 
01773         // for each addr
01774         hdrc->size_ = 20 + 8 + ((4+8) * pcl->num_potl_children_) + 20 + 4 + (4 * pcl->num_tags_) + 4 + 1 + (8 * num_lm_addrs); 
01775         // In real life each of the above fields would be
01776         // 4 byte integers; 20 bytes for IP addr
01777         //      if(myaddr_ == 11) 
01778         //        trace("Node 11: Packet size: %d",hdrc->size_);
01779       }
01780       else if(action == DEMOTION) {
01781         hdrc->size_ = 20 + 20;
01782       }      
01783     }
01784   }
01785 
01786   // Optimization for reducing energy consumption; Just advertise
01787   // sequence number in steady state
01788   //  if(pcl->parent_ == NULL && action != DEMOTION) 
01789   //    hdrc->size_ = 20 + 4;
01790 
01791   // Cancel periodic_callback event if node is being demoted
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   // level i's radius >= (2 *level i-1's radius) + 1
01806   return((int(pow(2,level+1) + pow(2,level) - 1)));
01807 
01808   //  return((level + 1)*2 + 1);
01809   //  return(int(pow(2,level+1)) + 1);
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; // default is to flood adverts
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; // Pointer to new highest_level_-1 object
01835   ParentChildrenList *pcl2 = NULL; // Pointer to new highest_level_+1 object
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   //  if(now > 412.5) {
01847   //    purify_printf("expire1: %f,%d\n",now,a_->myaddr_);
01848   //    purify_new_leaks();
01849   //  }
01850 
01851   while(pcl != NULL) {
01852     if(pcl->level_ == (a_->highest_level_ + 1)) {
01853       // Exclude ourself from the count of the lower level nodes heard
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       // Promotion timeout is num_resched_ times the estimated time for 
01882       // a message to reach other nodes in its vicinity
01883       // PROM0_TIMEOUT_MULTIPLE is an estimate of time for adv to reach 
01884       // all nodes in vicinity
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       //      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_) + (MAX_ENERGY - (a_->node_)->energy())*200/MAX_ENERGY;
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       //      a_->trace("Node %d: Entering wait period in expire1 at time %f, highest level %d", a_->myaddr_,now,a_->highest_level_);
01898       a_->promo_timer_->resched(wait_time);
01899 
01900       // Demote ourself we do not have any children (excluding ourself) after
01901       // waiting for 1.5 times the update period
01902       if(a_->highest_level_ && (a_->total_wait_time_ > (a_->update_period_*1.5))) {
01903         //      a_->trace("Node %d: cur_pcl's number of children %d",a_->myaddr_,cur_pcl->num_children_);
01904 
01905         // Demote ourself from this level if we have only one children
01906         // and we have more than one potential parent at lower level
01907         // If we dont have more than one potl parent at lower level,
01908         // this node will oscillate between the two levels
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            // Update appropriate lists
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         // We must be the global LM
01931         a_->global_lm_id_ = a_->myaddr_;
01932         a_->global_lm_level_ = a_->highest_level_;
01933 
01934         // Get LM addresses if any
01935         (cur_pcl->mylmaddrs_)->get_lm_addrs(&num_my_lm_addrs,&my_lm_addrs);
01936 
01937         // Start assigning landmark addresses to child nodes; 
01938         // Shift 1, number of levels * 8 times to left for address of root node
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           // Generate updates for LM at lower levels as well since their LM
01965           // addresses have also changed
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         // The advertisements from the root LM need to be broadcast in the hash
01981         // scheme
01982         if(num_lm_addrs) delete[] lmaddr;
01983       }
01984     }      
01985     return;
01986   }    
01987   
01988   // Promotion timer is off
01989   a_->promo_timer_running_ = 0;
01990 
01991   // Only one promotion timer can be running at a node at a given instant. 
01992   // On expiry, the node will be promoted one level higher to highest_level_+1
01993   // Add a parentchildrenlist object for the higher level if one doesnt already
01994   // exist
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   // highest_level_-1 object should exist
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   // Create highest_level_+1 object if it doesnt exist
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     //    LMNode *lm = higher_level_pcl->pchildren_;
02041     //    a_->trace("Potential Children:");
02042     //    while(lm) {
02043     //      a_->trace("%d (level %d) Number of hops: %d", lm->id_,lm->level_,lm->num_hops_);
02044     //      lm = lm->next_;
02045     //    }
02046     
02047     //    lm = higher_level_pcl->pparent_;
02048     //    a_->trace("Potential Parent:");
02049     //    while(lm) {
02050     //      a_->trace("%d (level %d)", lm->id_,lm->level_);
02051     //      lm = lm->next_;
02052     //    }
02053   }
02054 
02055 
02056   // Update tag lists and send out corresponding advertisements
02057   a_->SendChangedTagListUpdate(0,a_->highest_level_-1);
02058 
02059   // start off periodic advertisements for this higher level
02060   s.schedule(higher_level_pcl->periodic_handler_, higher_level_pcl->periodic_update_event_, 0);
02061   
02062   // add myself as potential parent for highest_level-1 and child for 
02063   // highest_level+1 
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   // tag_list == NULL doesnt matter because we're at a smaller level than
02075   // pcl2->level_ at this point. periodic_callback_ will update this field
02076   // correctly
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   // If we havent seen a LM that can be our parent at this higher level, start
02083   // promotion timer for promotion to next level
02084   a_->num_resched_ = pcl2->num_heard_ - 1;
02085   if(higher_level_pcl->parent_ == NULL && a_->num_resched_) {
02086     //    if (a_->debug_) printf("PromotionTimer's expire method: Scheduling timer for promo to level %d\n",a_->highest_level_);
02087     // Timer's status is TIMER_HANDLING in handle; so we just reschedule to
02088     // avoid "cant start timer" abort if sched is called
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     //    a_->trace("Node %d: Entering wait period in expire1 at time %f", a_->myaddr_,now);
02106     a_->promo_timer_->resched(wait_time);
02107   }
02108   
02109 
02110   //  if(now > 412.5) {
02111   //    purify_printf("expire2: %f,%d\n",now,a_->myaddr_);
02112   //    purify_new_leaks();
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           // Entries should never timeout in a hard-state scheme
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           //      rtable_ent *prte;
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           //      trace ("Energy consumed by queries: %f", node_->qry_energy());
02176 
02177           /*
02178            * Freeing a routing layer packet --> don't need to
02179            * call drop here.
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   //  AgentList *alist = AgentList::instance();
02352   int *nbrs;
02353   int num_nbrs = 0, num_nodes = 0;
02354   
02355   // Adding ourself to global tag agent database
02356   //  alist->AddAgent(myaddr_,this);
02357 
02358   //  num_nodes = gd->numNodes()-1;
02359 
02360   //  nbrs = new int[num_nodes];
02361   
02362   //  for(i = 1; i <= num_nodes; ++i) {
02363       // God sees node id as id+1 ...
02364   //    if(gd->hops(myaddr_+1,i) == 1) {
02365   //      nbrs[num_nbrs++] = i-1;
02366   //    }
02367   //  }
02368 
02369 
02370   //  trace("Node %d: Number of nbrs %d, Neighbours:",myaddr_,num_nbrs);
02371   //  num_nbrs_ = num_nbrs;
02372   //  nbrs_ = new int[num_nbrs_];
02373   //  for(i = 0; i < num_nbrs_; ++i) {
02374   //    nbrs_[i] = nbrs[i];
02375     //    trace("%d",nbrs_[i]);
02376   //  }
02377   //  if(nbrs) delete[] nbrs;
02378   
02379   trace("Node %d: LM Agent starting up at time %f",myaddr_,NOW);
02380 
02381   // Set node to be alive (this method might be called after a call to reset
02382   node_dead_ = 0;
02383   
02384   double x,y,z;
02385   node_->getLoc(&x,&y,&z);
02386   //  printf("Node %d position: (%f,%f,%f)\n",myaddr_,x,y,z);
02387 
02388   // Detection range smaller than transmission range. This is because, if 
02389   // the tags are passive, they may not have sufficient energy to re-radiate
02390   // information to the sensor
02391   double r = 60;
02392 
02393   local_tags0 = tag_dbase_->Gettags(x,y,r);
02394   //  trace("Node %d's at (%f,%f,%f) senses tags:",myaddr_,x,y,z);
02395 
02396   t_ptr = local_tags0;
02397   ntags = 0;
02398   while(t_ptr) {
02399     //    trace("tag name: %d.%d.%d",(t_ptr->obj_name_ >> 24) & 0xFF,(t_ptr->obj_name_ >> 16) & 0xFF,(t_ptr->obj_name_) & 0xFFFF);
02400     ++ntags;
02401     if(!(t_ptr->next_) && mobile_tags_ && !read_new_mobile_tags) {
02402 
02403       // Update our tag list with any new tags that have come into our range
02404       // while we were dead
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   //  trace("Number of tags: %d",ntags);
02414 
02415   /*
02416   int agg_level = 1;
02417   int num_tags = 0;
02418   local_tags1 = aggregate_tags(local_tags0,agg_level,&num_tags);
02419   trace("Level 1 aggregates, num = %d",num_tags);
02420   t_ptr = local_tags1;
02421   while(t_ptr) {
02422     trace("tag name: %d.%d.%d",(t_ptr->obj_name_ >> 24) & 0xFF,(t_ptr->obj_name_ >> 16) & 0xFF,(t_ptr->obj_name_) & 0xFFFF);
02423     t_ptr = t_ptr->next_;
02424   }
02425 
02426   agg_level = 2;
02427   num_tags = 0;
02428   local_tags2 = aggregate_tags(local_tags1,agg_level,&num_tags);
02429   trace("Level 2 aggregates, num = %d",num_tags);
02430   t_ptr = local_tags2;
02431   while(t_ptr) {
02432     trace("tag name: %d.%d.%d",(t_ptr->obj_name_ >> 24) & 0xFF,(t_ptr->obj_name_ >> 16) & 0xFF,(t_ptr->obj_name_) & 0xFFFF);
02433     t_ptr = t_ptr->next_;
02434   }
02435 
02436   // Delete local_tags1
02437   tag_ptr1 = local_tags1;
02438   while(tag_ptr1) {
02439     tag_ptr2 = tag_ptr1;
02440     tag_ptr1 = tag_ptr1->next_;
02441     delete tag_ptr2;
02442   }
02443 
02444   // Delete local_tags2
02445   tag_ptr1 = local_tags2;
02446   while(tag_ptr1) {
02447     tag_ptr2 = tag_ptr1;
02448     tag_ptr1 = tag_ptr1->next_;
02449     delete tag_ptr2;
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   // Start off periodic LM advertisements
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   // Start off promotion timer
02465   //  if (debug_) printf("startUp: Scheduling timer\n");
02466   promo_timer_running_ = 1;
02467   num_resched_ = 0;
02468 
02469   // Node enters "wait" state where it waits to receive other node's 
02470   // advertisements; Wait for 5 * radius(level) seconds; Should be
02471   // atleast the same as the period of LM advts (10s)
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   //  trace("Node %d: Wait time at startUp: %f",myaddr_,wait_time);
02477   promo_timer_->sched(wait_time);
02478 
02479   //  promo_timer_->sched(promo_timeout_);
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   // agg_level is 1 implies ignore the last field
02493   // agg_level >= 2 implies ignore the last two fields
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   // Tag names have 3 fields
02573   // List 1 is list of tags with first field > 0, last 2 fields = 0
02574   // List 2 is list of tags with first two fields > 0 and last field = 0
02575   // List 3 is list of tags with all three fields > 0 
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       // Check if p1.p2.0 is already in list2; If so, goto next object
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       // Check if p1.0.0 is already in list1; If so, goto next object
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         // If 2 objects have same value for first two fields, store the
02614         // aggregate p1.p2.0 in list2; We have already checked if p1.p2.0
02615         // is already in list2 or not
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           // Indicate that this is a new aggregate
02628           t2->marked_ = 1;
02629           // Remove this object from list3; We simply set the obj_name_ to 1
02630           // to indicate that this tag object is not valid
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       // Check if p1.0.0 is already in list1; If so, goto next object
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         // If 2 objects have same value for the first field, store the
02677         // aggregate in list1 provided the other object is not a new aggregate
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           // Indicate that this is a new aggregate
02690           t1->marked_ = 1;
02691           // Remove this object from list3; We simply set the obj_name_ to 1
02692           // to indicate that this tag object is not valid
02693           tmp_ptr->obj_name_ = -1;
02694 
02695           // Remove any elements p1.*.* from list3 i.e., set obj_name_ to -1
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       // Remove any elements p1.p2.* from list3 i.e., set obj_name_ to -1
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       // Check if object p1.0.0 already in list; If so, goto next object
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       // Add object to list1
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       // Remove any elements p1.*.* from list2 i.e., set obj_name_ to -1
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       // Remove any elements p1.*.* from list3 i.e., set obj_name_ to -1
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   // Make list1, list2, list3 into one list
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   // Return the list of aggregated tags
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   // Delete list
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    *  Must be a packet being originated by the query agent at my node?
02855    */
02856 
02857   if(node_dead_) {
02858     Packet::free(p);
02859     return;
02860   }
02861 
02862   if(iph->saddr() == myaddr_ && iph->sport() == 0) {
02863     /*
02864      * Add the IP Header
02865      */
02866     cmh->size() += IP_HDR_LEN;    
02867 
02868   }
02869   /*
02870    *  I received a packet that I sent.  Probably
02871    *  a routing loop.
02872    */
02873   else if(iph->saddr() == myaddr_) {
02874     Packet::free(p);
02875     //   drop(p, DROP_RTR_ROUTE_LOOP);
02876     return;
02877   }
02878   /*
02879    *  Packet I'm forwarding...
02880    */
02881 
02882   // Move the ttl check to the following methods?
02883   //    if(--iph->ttl_ == 0) {
02884   //      drop(p, DROP_RTR_TTL);
02885   //      return;
02886   //    }
02887   
02888   // Packet will be forwarded down (if it's not dropped)
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; // index into cache if object is found
02927   int found = FALSE; // whether object has been found in cache
02928 
02929   walk = p->accessdata();
02930 
02931   // Type of advertisement
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   // level of our parent/child node that forwarded the query to us
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     // origin time of advertisement
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   // Used to add source route to packet
02981   pkt_end_ptr = walk;
02982   
02983   // If this is a response pkt, cache this information
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         // If object already exists in cache, update info if necessary
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         // Use LRU cache replacement
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       // If this is a query pkt; check if we have the relevant information 
03019       // cached. TTL = 600 seconds for the cache entries
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   // Loop check i.e., if response to our query agent has looped back
03033   // Following not the correct condition to detect a loop!
03034   //  assert(!(iph->daddr() == myaddr_ && iph->dport() == 0));
03035 
03036   // Reduce the source route to just parent-children (O(#levels))
03037   // This is possible since parent and child in each others vicinity
03038   cmh->direction() = hdr_cmn::DOWN;
03039   if(iph->daddr() == myaddr_)
03040     query_for_us = TRUE;
03041 
03042   // Query pkt if X and Y are 65000
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         // if num_dst = 0 but dst_nodes is not NULL, we sense the
03054         // requested tag; add X,Y info and send response
03055         // if found is true, we have the cached information
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         // Send response
03071         iph->ttl_ = 1000;
03072         // Add 50 bytes to response 
03073         cmh->size() += 50;
03074         // Query from an agent at our node
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           // Decr pkt size
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           //      assert(cmh->next_hop_ != NO_NEXT_HOP);          
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         //      if(found) 
03106           //      trace("Node %d: Gen response from cache at time %f to node %d",myaddr_,s.clock(),iph->daddr());
03107         //      else
03108           //      trace("Node %d: Gen response at time %f to node %d",myaddr_,s.clock(),iph->daddr() >> 8);
03109 
03110         if(!num_src_hops && iph->daddr() == myaddr_) {
03111           // TEMPORARY HACK! Cant forward from routing agent to some other
03112           // agent on our node!
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         // Add ourself to source route and increase the number of src hops
03132         //      if(last_hop_id != myaddr_) {
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         // Indicate the level of the pcl object that a node should look-up
03139         // to find the relevant routing table entry
03140         *pkt_end_ptr = (next_hop_level+1) & 0xFF;
03141         // Incr pkt size
03142         cmh->size() += 4;
03143 
03144         dst_ptr = dst_nodes;
03145         // Replicate pkt to each destination
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         // Copy next hop variable to this variable temporarily
03151         // Copy it back into packet before sending the packet
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           // Change level and copy the packet
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         // Free packet if we dont have any dst to forward packet
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       // simply forward to next hop
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       //      assert(cmh->next_hop_ != NO_NEXT_HOP);      
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     // Forward the response packet
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     // Check if query from an agent at our node
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         // Decr pkt size
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         //      assert(cmh->next_hop_ != NO_NEXT_HOP);    
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         // TEMPORARY HACK! Cant forward from routing agent to some other
03269         // agent on our node!
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       //      assert(cmh->next_hop_ != NO_NEXT_HOP);      
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   // Check if our node senses the requested tag
03309   while(pcl) {
03310     if(pcl->level_ == 0)
03311       break;
03312     pcl = pcl->next_;
03313   }
03314 
03315   if(!pcl)
03316     return(NULL);
03317 
03318   // if our node senses the tag, add the node to nlist but do not increase
03319   // num_dst
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   // If next_hop_level = 2, lookup would be done in the level 2 object
03332   // that would have level 1 tag aggregates
03333   //  if(next_hop_level == 2)
03334   //    obj_name = obj_name & 0xFFFF0000;
03335   //  else if(next_hop_level >= 3)
03336   //    obj_name = obj_name & 0xFF000000;
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   //  assert(pcl);
03352   child = pcl->pchildren_;
03353   while(child) {
03354     // Dont forward back to child if child forwarded this query to us
03355     // We should forward to all children though if the message is going
03356     // down the hierarchy
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           // Delete all old elements
03389           NodeIDList *n1, *n2;
03390           n1 = nlist;
03391           while(n1) {
03392             n2 = n1;
03393             n1 = n1->next_;
03394             delete n2;
03395           }
03396           // Return just single element i.e., the ID of the child with an
03397           // exact match for the object name
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   // Add parent if query is travelling up the hierarchy
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   //  assert(pcl);
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   //  assert(pchild);
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     // Get level 0 pcl object
03511     while(pcl) {
03512       if(pcl->level_ == 0)
03513         break;
03514       pcl = pcl->next_;
03515     }
03516     assert(pcl);
03517   }    
03518   
03519   // Pick tag(s) at random and move them to one of the neighbours
03520   // Only tags with the last field > 5 are mobile.
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     // Tags with last field < 30 are not mobile
03530     if((tag->obj_name_ & 0xFFFF) > 30) {
03531       // Move tag to neighbouring node with probability of 0.3
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         // Remove tag from our list
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         // Add this tag to neighbouring node
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   // Trigger hierarchy advertisement if our taglist has changed
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   // Make sure that this tag object is not pointing to next member on
03590   // the previous list that this tag was part of
03591   new_tag->next_ = NULL;
03592 
03593   if(pcl) {
03594     // Get level 0 pcl object
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   // Trigger hierarchy advertisements after a mean of 5 seconds if
03629   // the advt event has not already been scheduled
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 // new tag info received for specified level; Send updates if necessary
03639 // i.e., if aggregates have changed etc.
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     // Send out hierarchy advertisement since the tag list has changed
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     // Loop through all the children and add tags to tag_list
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           //        trace("tag name: %d.%d.%d",(tag_ptr1->obj_name_ >> 24) & 0xFF,(tag_ptr1->obj_name_ >> 16) & 0xFF,(tag_ptr1->obj_name_) & 0xFFFF);
03702           tag_ptr2->obj_name_ = tag_ptr1->obj_name_;
03703           tag_ptr1 = tag_ptr1->next_;
03704         }
03705       }
03706       lmnode = lmnode->next_;
03707     }
03708     
03709     // Aggregate tag_list
03710     agg_tags = aggregate_taginfo(tag_list,parent_pcl->level_,&num_tags);
03711     
03712     // Delete tag_list
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       // Delete parent_pcl's tag_list and update with new tag_list
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       // Send out hierarchy advertisement since the tag list has changed
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       // Update our tag list in the higher level pcl object
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       // Delete agg_tags
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   // if num_tags == -1, it means that the number of tags was not computed
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 

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