landmark.cc

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

Generated on Tue Mar 6 16:47:46 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6