gaf.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * gaf.cc
00004  * Copyright (C) 2000 by the University of Southern California
00005  * $Id: gaf.cc,v 1.6 2005/08/25 18:58:05 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 
00048 #include <template.h>
00049 #include <gaf/gaf.h>
00050 #include <random.h>
00051 #include <address.h>
00052 #include <mobilenode.h>
00053 #include <god.h>
00054 #include <phy.h>
00055 #include <wireless-phy.h>
00056 #include <energy-model.h>
00057 
00058 
00059 
00060 int hdr_gaf::offset_;
00061 static class GAFHeaderClass : public PacketHeaderClass {
00062 public:
00063     GAFHeaderClass() : PacketHeaderClass("PacketHeader/GAF",
00064                          sizeof(hdr_gaf)) {
00065         bind_offset(&hdr_gaf::offset_);
00066     }
00067 } class_gafhdr;
00068 
00069 static class GAFAgentClass : public TclClass {
00070 public:
00071     GAFAgentClass() : TclClass("Agent/GAF") {}
00072     TclObject* create(int argc, const char*const* argv) {
00073             assert(argc == 5);
00074         return (new GAFAgent((nsaddr_t) atoi(argv[4])));
00075     }
00076 } class_gafagent;
00077 
00078 static class GAFPartnerClass : public TclClass {
00079 public:
00080         GAFPartnerClass() : TclClass("GAFPartner") {}
00081         TclObject* create(int, const char*const*) {
00082                 return (new GAFPartner());
00083         }
00084 } class_gafparnter;
00085 
00086 
00087 static inline double 
00088 gafjitter (double max, int be_random_)
00089 {
00090   return (be_random_ ? Random::uniform(max) : max);
00091 }
00092 
00093 
00094 GAFAgent::GAFAgent(nsaddr_t id) : Agent(PT_GAF), beacon_(1), randomflag_(1), timer_(this), stimer_(this), dtimer_(this), maxttl_(5), state_(GAF_FREE),leader_settime_(0),adapt_mobility_(0)
00095 {
00096         double x = 0.0, y = 0.0, z = 0.0;
00097 
00098     seqno_ = -1;
00099     nid_ = id;
00100     thisnode = Node::get_node_by_address(nid_); 
00101     // gid_ = nid_; // temporary setting, MUST BE RESET
00102 
00103     // grid caculation
00104     // no need to update location becasue getLoc will do it
00105 
00106     ((MobileNode *)thisnode)->getLoc(&x, &y, &z);
00107     gid_ = God::instance()->getMyGrid(x,y);
00108         
00109     if (gid_ < 0) {
00110         printf("fatal error: node is outside topography\n");
00111     }
00112 }
00113 
00114 void GAFAgent::recv(Packet* p, Handler *)
00115 {
00116     hdr_gaf *gafh = hdr_gaf::access(p);
00117 
00118     switch (gafh->type_) {
00119 
00120     case GAF_DISCOVER:
00121 
00122       if (state_ != GAF_SLEEP)
00123           processDiscoveryMsg(p);
00124       Packet::free(p);
00125       break;
00126 
00127     default:
00128       Packet::free(p);
00129       break;
00130     }
00131 }
00132 
00133 
00134 void GAFAgent::processDiscoveryMsg(Packet* p)
00135 {
00136     struct DiscoveryMsg emsg;
00137     u_int32_t dst;
00138     unsigned char *w = p->accessdata ();
00139     double x = 0.0, y = 0.0, z = 0.0;
00140     int ttl;
00141 
00142 
00143     dst = *(w++);
00144     dst = dst << 8 | *(w++);
00145         dst = dst << 8 | *(w++);
00146         dst = dst << 8 | *(w++);
00147     
00148     emsg.gid = dst;
00149     
00150     dst = *(w++);
00151         dst = dst << 8 | *(w++);
00152         dst = dst << 8 | *(w++);
00153         dst = dst << 8 | *(w++);
00154 
00155     emsg.nid = dst;
00156 
00157     dst = *(w++);
00158         dst = dst << 8 | *(w++);
00159         dst = dst << 8 | *(w++);
00160         dst = dst << 8 | *(w++);
00161     
00162     emsg.state = dst;
00163 
00164     dst = *(w++);
00165         dst = dst << 8 | *(w++);
00166         dst = dst << 8 | *(w++);
00167         dst = dst << 8 | *(w++);
00168     
00169     emsg.ttl = dst;
00170     
00171     dst = *(w++);
00172         dst = dst << 8 | *(w++);
00173         dst = dst << 8 | *(w++);
00174         dst = dst << 8 | *(w++);
00175     
00176     emsg.stime = dst;
00177 
00178 
00179     // first, check if this node has changed its grid
00180     ((MobileNode *)thisnode)->getLoc(&x, &y, &z);
00181         gid_  = God::instance()->getMyGrid(x,y);
00182     
00183     // If the msg is not from my grid, ignore it
00184     if (((u_int32_t)gid_) != (u_int32_t)emsg.gid) return;
00185 
00186 
00187     switch (emsg.state) {
00188 
00189     case GAF_LEADER:
00190 
00191       // I receives a "whoami" msg from the leader in this grid
00192       // I am supposed to discard if I am in GAF_LEADER
00193       // state too, or put myself into sleep if I am in GAF_FREE
00194       
00195       switch (state_) {
00196       case GAF_LEADER:
00197 
00198         ttl = (int)(leader_settime_ - NOW);
00199         if (ttl < 0) ttl = 0;
00200 
00201             if ( ((u_int32_t)ttl) > (u_int32_t) emsg.ttl) {
00202                   //supress the partner
00203                   send_discovery();
00204           return; 
00205             
00206         } else {
00207                   if (((u_int32_t)ttl) == emsg.ttl && (u_int32_t)nid_ < emsg.nid) {
00208                       send_discovery();
00209                   return;
00210           }
00211           // from LEADER to SLEEP, cancel my timer
00212           stimer_.force_cancel();
00213           leader_settime_ = 0;
00214 
00215           // turn off my self
00216           schedule_wakeup(emsg);
00217         }
00218 
00219         break;
00220       
00221       case GAF_FREE:
00222         schedule_wakeup(emsg);
00223 
00224         break;
00225       default:
00226         break;
00227 
00228       }
00229 
00230       break;
00231     case GAF_FREE:
00232       if (state_ == GAF_FREE) {
00233           if ((ttl = (int)myttl()) > MIN_LIFETIME) {
00234                  ttl = ttl/2;
00235               }
00236     
00237               if ( ttl > (int)emsg.ttl) {
00238                   //supress other node
00239                   send_discovery();
00240           return; 
00241               } else {
00242                   if ((u_int32_t)ttl == emsg.ttl && (u_int32_t)nid_ < emsg.nid) {
00243                       send_discovery();
00244                   return;
00245                   }
00246     
00247           schedule_wakeup(emsg);
00248 
00249           }         
00250           }
00251       
00252       if (state_ == GAF_LEADER) {
00253           send_discovery();
00254       }
00255 
00256       break;
00257     default:
00258       printf("%d gets wrong discovery msg\n",nid_ );;
00259       break;
00260     }
00261 
00262 }
00263 
00264 void GAFAgent::schedule_wakeup(struct DiscoveryMsg emsg) {
00265 
00266   int waketime;
00267   waketime = emsg.ttl;
00268  
00269   // control whether using mobility adaption
00270   if (adapt_mobility_ > 0 ) {
00271       if (emsg.stime < emsg.ttl) waketime = emsg.stime;
00272   }
00273 
00274   // node does not go switch to sleep if the lifetime
00275   // it senses is less than MIN_SWITCHTIME
00276 
00277   if (waketime > MIN_TURNOFFTIME ) { 
00278      node_off();
00279      dtimer_.resched(Random::uniform(waketime/2, waketime)); 
00280   }
00281 }
00282 
00283 double GAFAgent::myttl()
00284 {
00285   double ce,maxp;
00286   Phy *phyp; 
00287   double ttl; 
00288   
00289   ce = (thisnode->energy_model())->energy();
00290 
00291   phyp = (thisnode->ifhead()).lh_first;
00292 
00293   assert (phyp != 0);
00294   maxp = ((WirelessPhy *)phyp)->getPtconsume();
00295   ttl = ce/maxp;
00296   
00297   return ttl;
00298 
00299 }
00300 
00301 // timeout process for discovery phase
00302 void GAFAgent::timeout(GafMsgType msgt)
00303 {
00304   
00305   int ttl;
00306 
00307 //printf ("Node (%d %d) get signal %d at %f\n",nid_, gid_, msgt, Scheduler::instance().clock());
00308 
00309     switch (msgt) {
00310     case GAF_DISCOVER:
00311 
00312       switch (state_) {
00313       case GAF_SLEEP:
00314     break;
00315        
00316       case GAF_FREE:
00317 
00318     if ((ttl = (int)myttl()) > MIN_LIFETIME) {
00319                 ttl = (int) ttl/2;
00320         }
00321         
00322     leader_settime_ = (int) (ttl + NOW);  
00323 
00324     // schdule to tell me that I can switch after ttl
00325 
00326     stimer_.resched(ttl); 
00327     
00328     setGAFstate(GAF_LEADER);
00329 
00330     send_discovery();
00331 
00332     //printf ("Node (%d %d) becomes a leader at %f\n",nid_, gid_, Scheduler::instance().clock());
00333 
00334          timer_.resched(Random::uniform(MAX_DISCOVERY_TIME-1,MAX_DISCOVERY_TIME));
00335     
00336     // fall through
00337          break; 
00338 
00339       case GAF_LEADER:
00340 
00341     send_discovery();
00342 
00343         timer_.resched(Random::uniform(MAX_DISCOVERY_TIME-1,MAX_DISCOVERY_TIME));
00344     break;
00345       default:
00346     break;
00347 
00348       }
00349 
00350       break;
00351 
00352     case GAF_SELECT:
00353         switch (state_) {
00354 
00355       case GAF_LEADER:
00356 
00357         // I just finish my LEADER role, put myself into FREE
00358         // state so that I have chance to go sleep
00359         // put myself into FREE does not hurt anything
00360 
00361         //printf("Node (%d %d) go BACK to FREE from LEADER at %f\n",nid_,gid_,Scheduler::instance().clock());
00362 
00363         duty_timeout();
00364 
00365         leader_settime_ = 0;
00366 
00367         break;
00368 
00369       case GAF_FREE:
00370       case GAF_SLEEP:
00371         break;
00372       default:
00373         break;
00374         }
00375     break;
00376     case GAF_DUTY:
00377         duty_timeout();
00378         break;
00379     default:
00380         printf("Wrong GAF msg time!\n");
00381     }
00382 
00383 }
00384 
00385 // adaptive fidelity timeout
00386 
00387 void GAFAgent::duty_timeout()
00388 {
00389     double x=0.0, y=0.0, z=0.0;
00390 
00391     // find where I am
00392     
00393     ((MobileNode *)thisnode)->getLoc(&x, &y, &z);
00394     gid_ = God::instance()->getMyGrid(x,y);
00395 
00396 
00397     // wake up myself
00398     node_on();
00399     
00400     // send discovery first to try to find whether
00401     // there is a leader around me
00402 
00403     send_discovery();
00404 
00405     // schedule the discovery timer randomly
00406     // can wait longer to get a chance to be replaced
00407 
00408     timer_.resched(gafjitter(GAF_NONSTART_JITTER, 1));
00409 
00410 }
00411 
00412 int GAFAgent::command(int argc, const char*const* argv)
00413 {
00414         if (argc == 2) {
00415       if (strcmp (argv[1], "start-gaf") == 0) {
00416         // schedule the discovery timer randomly
00417         timer_.resched(gafjitter(GAF_STARTUP_JITTER, 1));
00418         // schedule the select phase after certain time
00419         // of discovery msg exchange, as fast as possible
00420         // stimer_.resched(Random::uniform(GAF_LEADER_JITTER,GAF_LEADER_JITTER+1)); 
00421 
00422         return (TCL_OK); 
00423       }
00424           
00425     }
00426     if (argc == 3) {
00427         if (strcmp(argv[1], "adapt-mobility") == 0) {
00428             adapt_mobility_ = atoi(argv[2]);
00429             //timer_.resched(Random::uniform(0, beacon_));
00430             return TCL_OK;
00431         }
00432     
00433         if (strcmp(argv[1], "maxttl") == 0) {
00434         maxttl_ = atoi(argv[2]);
00435         return TCL_OK;
00436         }
00437 
00438     }
00439     return (Agent::command(argc, argv));
00440 }
00441 
00442 void GAFAgent::send_discovery()
00443 {
00444         Packet *p = allocpkt();
00445     double x=0.0, y=0.0, z=0.0;
00446 
00447     hdr_gaf *h = hdr_gaf::access(p);
00448     //hdr_ip *iph = hdr_ip::access(p);
00449 
00450     h->type_ = GAF_DISCOVER;
00451     h->seqno_ = ++seqno_;
00452 
00453     // update my grid infomation
00454     
00455     ((MobileNode *)thisnode)->getLoc(&x, &y, &z);
00456     gid_ = God::instance()->getMyGrid(x,y);
00457     
00458     makeUpDiscoveryMsg(p);
00459 
00460     send(p,0);
00461 }
00462 
00463 void
00464 GAFAgent::makeUpDiscoveryMsg(Packet *p)
00465 {
00466   hdr_ip *iph = hdr_ip::access(p);
00467   hdr_cmn *hdrc = hdr_cmn::access(p);
00468   u_int32_t ttl,stime;
00469   unsigned char *walk;
00470   double gridsize, speed;
00471 
00472   // fill up the header
00473   hdrc->next_hop_ = IP_BROADCAST;
00474   hdrc->addr_type_ = NS_AF_INET;
00475   iph->daddr() = IP_BROADCAST << Address::instance().nodeshift();
00476   iph->dport() = 254;
00477 
00478   // hdrc->direction() = hdr_cmn::DOWN;
00479 
00480   // fill up the data
00481 
00482   p->allocdata(sizeof(DiscoveryMsg));
00483   walk = p->accessdata ();
00484   hdrc->size_ = sizeof(DiscoveryMsg) + IP_HDR_LEN; // Existence Msg + IP
00485 
00486   *(walk++) = gid_ >> 24;
00487   *(walk++) = (gid_ >> 16) & 0xFF;
00488   *(walk++) = (gid_ >> 8) & 0xFF;
00489   *(walk++) = (gid_ >> 0) & 0xFF;
00490   *(walk++) = nid_ >> 24;
00491   *(walk++) = (nid_ >> 16) & 0xFF;
00492   *(walk++) = (nid_ >> 8) & 0xFF;
00493   *(walk++) = (nid_ >> 0) & 0xFF;
00494 
00495   // access my state
00496 
00497   *(walk++) = state_ >> 24;
00498   *(walk++) = (state_ >> 16) & 0xFF;
00499   *(walk++) = (state_ >> 8) & 0xFF;
00500   *(walk++) = (state_ >> 0) & 0xFF;  
00501 
00502 
00503   // ttl tells the receiver that how much longer the sender can
00504   // survive, cut it into half for the purpose of load balance
00505 
00506   if (state_ == GAF_LEADER) {
00507       // must send real msg because I am the leader
00508     ttl = (int)(leader_settime_ - NOW);
00509     if (ttl < 0) ttl = 0;
00510 
00511   } else {
00512 
00513       if ((ttl = (u_int32_t)myttl()) > MIN_LIFETIME) {
00514           ttl = (u_int32_t) ttl/2;
00515       }
00516 
00517   }
00518   *(walk++) = ttl >> 24;
00519   *(walk++) = (ttl >> 16) & 0xFF;
00520   *(walk++) = (ttl >> 8) & 0xFF;
00521   *(walk++) = (ttl >> 0) & 0xFF;
00522   
00523 
00524   // fill my possible time of leaving this grid
00525   
00526   
00527   speed = ((MobileNode*)thisnode)->speed();
00528 
00529   if (speed == 0) {
00530     // make stime big enough
00531     stime = 2*ttl;
00532   } else {
00533     gridsize = God::instance()->getMyGridSize();
00534     stime = (u_int32_t) (gridsize/speed);
00535   }
00536 
00537   *(walk++) = stime >> 24;
00538   *(walk++) = (stime >> 16) & 0xFF;
00539   *(walk++) = (stime >> 8) & 0xFF;
00540   *(walk++) = (stime >> 0) & 0xFF;
00541 
00542   //printf("Node %d send out Exitence msg gid/nid %d %d\n", nid_, gid_, nid_);
00543 
00544 }
00545 
00546 
00547 void
00548 GAFAgent::node_off()
00549 {
00550     Phy *p;
00551     EnergyModel *em;
00552 
00553     //printf ("Node (%d %d) goes SLEEP from %d at %f\n",nid_, gid_, state_, Scheduler::instance().clock());
00554 
00555     
00556     // if I am in the data transfer state, do not turn off
00557 
00558     // if (state_ == GAF_TRAFFIC) return;
00559 
00560     // set node state
00561     em = thisnode->energy_model();
00562     em->node_on() = false;
00563     //((MobileNode *)thisnode->energy_model())->node_on() = false;
00564 
00565     // notify phy
00566     p  = (thisnode->ifhead()).lh_first;
00567     if (p) {
00568     ((WirelessPhy *)p)->node_off();
00569     }
00570     // change agent state
00571     setGAFstate(GAF_SLEEP);
00572 }
00573 
00574 void
00575 GAFAgent::node_on()
00576 {
00577     Phy *p;
00578     EnergyModel* em;
00579 
00580     // set node state
00581 
00582     em = thisnode->energy_model();
00583     em->node_on() = true;
00584 
00585     //(MobileNode *)thisnode->energy_model()->node_on() = true;
00586 
00587     // notify phy
00588 
00589     p = (thisnode->ifhead()).lh_first;
00590     if (p) {
00591         ((WirelessPhy *)p)->node_on();
00592     }
00593     
00594     setGAFstate(GAF_FREE);
00595 }
00596 
00597 void 
00598 GAFAgent::setGAFstate(GafNodeState gs)
00599 {
00600   //printf("Node (%d %d) changes state from %d to %d at %f\n", nid_, gid_, state_,gs,Scheduler::instance().clock());
00601 
00602    state_ = gs;
00603 }
00604 
00605 GAFPartner::GAFPartner() : Connector(), gafagent_(1),mask_(0xffffffff),
00606         shift_(8)
00607 {
00608         bind("addr_", (int*)&(here_.addr_));
00609         bind("port_", (int*)&(here_.port_));
00610         bind("shift_", &shift_);
00611         bind("mask_", &mask_);
00612 }
00613 
00614 void GAFPartner::recv(Packet* p, Handler *h)
00615 {
00616         hdr_ip* hdr = hdr_ip::access(p);
00617     hdr_cmn *hdrc = hdr_cmn::access(p);
00618 
00619     /* handle PT_GAF packet only */
00620     /* convert the dst ip if it is -1, change it into node's */
00621     /* own ip address */    
00622     if ( hdrc->ptype() == PT_GAF ) {
00623       if (gafagent_ == 1) {
00624         if (((u_int32_t)hdr->daddr()) == IP_BROADCAST) {
00625         hdr->daddr() = here_.addr_;
00626         }       
00627       } else {
00628         /* if gafagent is not installed, drop the packet */
00629         drop (p);
00630         return;
00631       }
00632     }
00633     
00634     target_->recv(p,h);
00635 
00636 
00637 }
00638 
00639 int GAFPartner::command(int argc, const char*const* argv)
00640 {
00641         if (argc == 3) {
00642       if (strcmp (argv[1], "set-gafagent") == 0) {
00643         gafagent_ = atoi(argv[2]);
00644         return (TCL_OK); 
00645       }
00646     }
00647     return Connector::command(argc, argv); 
00648 }
00649 
00650 void GAFDiscoverTimer::expire(Event *) {
00651   a_->timeout(GAF_DISCOVER);
00652 }
00653 
00654 void GAFSelectTimer::expire(Event *) {
00655   a_->timeout(GAF_SELECT);
00656 }
00657 
00658 void GAFDutyTimer::expire(Event *) {
00659   a_->timeout(GAF_DUTY);
00660 }
00661 
00662 
00663 
00664 

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