gaf.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:15k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * gaf.cc
  3.  * Copyright (C) 2000 by the University of Southern California
  4.  * $Id: gaf.cc,v 1.6 2005/08/25 18:58:05 johnh Exp $
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License,
  8.  * version 2, as published by the Free Software Foundation.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  18.  *
  19.  *
  20.  * The copyright of this module includes the following
  21.  * linking-with-specific-other-licenses addition:
  22.  *
  23.  * In addition, as a special exception, the copyright holders of
  24.  * this module give you permission to combine (via static or
  25.  * dynamic linking) this module with free software programs or
  26.  * libraries that are released under the GNU LGPL and with code
  27.  * included in the standard release of ns-2 under the Apache 2.0
  28.  * license or under otherwise-compatible licenses with advertising
  29.  * requirements (or modified versions of such code, with unchanged
  30.  * license).  You may copy and distribute such a system following the
  31.  * terms of the GNU GPL for this module and the licenses of the
  32.  * other code concerned, provided that you include the source code of
  33.  * that other code when and as the GNU GPL requires distribution of
  34.  * source code.
  35.  *
  36.  * Note that people who make modified versions of this module
  37.  * are not obligated to grant this special exception for their
  38.  * modified versions; it is their choice whether to do so.  The GNU
  39.  * General Public License gives permission to release a modified
  40.  * version without this exception; this exception also makes it
  41.  * possible to release a modified version which carries forward this
  42.  * exception.
  43.  *
  44.  */
  45. #include <template.h>
  46. #include <gaf/gaf.h>
  47. #include <random.h>
  48. #include <address.h>
  49. #include <mobilenode.h>
  50. #include <god.h>
  51. #include <phy.h>
  52. #include <wireless-phy.h>
  53. #include <energy-model.h>
  54. int hdr_gaf::offset_;
  55. static class GAFHeaderClass : public PacketHeaderClass {
  56. public:
  57. GAFHeaderClass() : PacketHeaderClass("PacketHeader/GAF",
  58.      sizeof(hdr_gaf)) {
  59. bind_offset(&hdr_gaf::offset_);
  60. }
  61. } class_gafhdr;
  62. static class GAFAgentClass : public TclClass {
  63. public:
  64. GAFAgentClass() : TclClass("Agent/GAF") {}
  65. TclObject* create(int argc, const char*const* argv) {
  66.         assert(argc == 5);
  67. return (new GAFAgent((nsaddr_t) atoi(argv[4])));
  68. }
  69. } class_gafagent;
  70. static class GAFPartnerClass : public TclClass {
  71. public:
  72.         GAFPartnerClass() : TclClass("GAFPartner") {}
  73.         TclObject* create(int, const char*const*) {
  74.                 return (new GAFPartner());
  75.         }
  76. } class_gafparnter;
  77. static inline double 
  78. gafjitter (double max, int be_random_)
  79. {
  80.   return (be_random_ ? Random::uniform(max) : max);
  81. }
  82. 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)
  83. {
  84.         double x = 0.0, y = 0.0, z = 0.0;
  85. seqno_ = -1;
  86. nid_ = id;
  87. thisnode = Node::get_node_by_address(nid_); 
  88. // gid_ = nid_; // temporary setting, MUST BE RESET
  89. // grid caculation
  90. // no need to update location becasue getLoc will do it
  91. ((MobileNode *)thisnode)->getLoc(&x, &y, &z);
  92. gid_ = God::instance()->getMyGrid(x,y);
  93.         
  94. if (gid_ < 0) {
  95.     printf("fatal error: node is outside topographyn");
  96. }
  97. }
  98. void GAFAgent::recv(Packet* p, Handler *)
  99. {
  100. hdr_gaf *gafh = hdr_gaf::access(p);
  101. switch (gafh->type_) {
  102. case GAF_DISCOVER:
  103.   if (state_ != GAF_SLEEP)
  104.       processDiscoveryMsg(p);
  105.   Packet::free(p);
  106.   break;
  107. default:
  108.   Packet::free(p);
  109.   break;
  110. }
  111. }
  112. void GAFAgent::processDiscoveryMsg(Packet* p)
  113. {
  114. struct DiscoveryMsg emsg;
  115. u_int32_t dst;
  116. unsigned char *w = p->accessdata ();
  117. double x = 0.0, y = 0.0, z = 0.0;
  118. int ttl;
  119. dst = *(w++);
  120. dst = dst << 8 | *(w++);
  121.         dst = dst << 8 | *(w++);
  122.         dst = dst << 8 | *(w++);
  123. emsg.gid = dst;
  124. dst = *(w++);
  125.         dst = dst << 8 | *(w++);
  126.         dst = dst << 8 | *(w++);
  127.         dst = dst << 8 | *(w++);
  128. emsg.nid = dst;
  129. dst = *(w++);
  130.         dst = dst << 8 | *(w++);
  131.         dst = dst << 8 | *(w++);
  132.         dst = dst << 8 | *(w++);
  133. emsg.state = dst;
  134. dst = *(w++);
  135.         dst = dst << 8 | *(w++);
  136.         dst = dst << 8 | *(w++);
  137.         dst = dst << 8 | *(w++);
  138. emsg.ttl = dst;
  139. dst = *(w++);
  140.         dst = dst << 8 | *(w++);
  141.         dst = dst << 8 | *(w++);
  142.         dst = dst << 8 | *(w++);
  143. emsg.stime = dst;
  144. // first, check if this node has changed its grid
  145. ((MobileNode *)thisnode)->getLoc(&x, &y, &z);
  146.         gid_  = God::instance()->getMyGrid(x,y);
  147. // If the msg is not from my grid, ignore it
  148. if (((u_int32_t)gid_) != (u_int32_t)emsg.gid) return;
  149. switch (emsg.state) {
  150. case GAF_LEADER:
  151.   // I receives a "whoami" msg from the leader in this grid
  152.   // I am supposed to discard if I am in GAF_LEADER
  153.   // state too, or put myself into sleep if I am in GAF_FREE
  154.   
  155.   switch (state_) {
  156.   case GAF_LEADER:
  157.     ttl = (int)(leader_settime_ - NOW);
  158.     if (ttl < 0) ttl = 0;
  159.          if ( ((u_int32_t)ttl) > (u_int32_t) emsg.ttl) {
  160.                //supress the partner
  161.                send_discovery();
  162.       return; 
  163.          
  164.     } else {
  165.                if (((u_int32_t)ttl) == emsg.ttl && (u_int32_t)nid_ < emsg.nid) {
  166.                    send_discovery();
  167.            return;
  168.   }
  169.   // from LEADER to SLEEP, cancel my timer
  170.   stimer_.force_cancel();
  171.   leader_settime_ = 0;
  172.   // turn off my self
  173.   schedule_wakeup(emsg);
  174.     }
  175.     break;
  176.   
  177.   case GAF_FREE:
  178.     schedule_wakeup(emsg);
  179.     break;
  180.   default:
  181.     break;
  182.   }
  183.   break;
  184. case GAF_FREE:
  185.   if (state_ == GAF_FREE) {
  186.       if ((ttl = (int)myttl()) > MIN_LIFETIME) {
  187.               ttl = ttl/2;
  188.            }
  189.     
  190.            if ( ttl > (int)emsg.ttl) {
  191.                //supress other node
  192.                send_discovery();
  193.       return; 
  194.            } else {
  195.                if ((u_int32_t)ttl == emsg.ttl && (u_int32_t)nid_ < emsg.nid) {
  196.                    send_discovery();
  197.            return;
  198.                }
  199.     
  200.   schedule_wakeup(emsg);
  201.       }         
  202.        }
  203.   
  204.   if (state_ == GAF_LEADER) {
  205.       send_discovery();
  206.   }
  207.   break;
  208. default:
  209.   printf("%d gets wrong discovery msgn",nid_ );;
  210.   break;
  211. }
  212. }
  213. void GAFAgent::schedule_wakeup(struct DiscoveryMsg emsg) {
  214.   int waketime;
  215.   waketime = emsg.ttl;
  216.  
  217.   // control whether using mobility adaption
  218.   if (adapt_mobility_ > 0 ) {
  219.       if (emsg.stime < emsg.ttl) waketime = emsg.stime;
  220.   }
  221.   // node does not go switch to sleep if the lifetime
  222.   // it senses is less than MIN_SWITCHTIME
  223.   if (waketime > MIN_TURNOFFTIME ) { 
  224.      node_off();
  225.      dtimer_.resched(Random::uniform(waketime/2, waketime)); 
  226.   }
  227. }
  228. double GAFAgent::myttl()
  229. {
  230.   double ce,maxp;
  231.   Phy *phyp; 
  232.   double ttl; 
  233.   
  234.   ce = (thisnode->energy_model())->energy();
  235.   phyp = (thisnode->ifhead()).lh_first;
  236.   assert (phyp != 0);
  237.   maxp = ((WirelessPhy *)phyp)->getPtconsume();
  238.   ttl = ce/maxp;
  239.   
  240.   return ttl;
  241. }
  242. // timeout process for discovery phase
  243. void GAFAgent::timeout(GafMsgType msgt)
  244. {
  245.   
  246.   int ttl;
  247. //printf ("Node (%d %d) get signal %d at %fn",nid_, gid_, msgt, Scheduler::instance().clock());
  248.     switch (msgt) {
  249.     case GAF_DISCOVER:
  250.       switch (state_) {
  251.       case GAF_SLEEP:
  252. break;
  253.        
  254.       case GAF_FREE:
  255. if ((ttl = (int)myttl()) > MIN_LIFETIME) {
  256.                 ttl = (int) ttl/2;
  257.         }
  258.         
  259. leader_settime_ = (int) (ttl + NOW);  
  260. // schdule to tell me that I can switch after ttl
  261. stimer_.resched(ttl); 
  262. setGAFstate(GAF_LEADER);
  263. send_discovery();
  264. //printf ("Node (%d %d) becomes a leader at %fn",nid_, gid_, Scheduler::instance().clock());
  265.          timer_.resched(Random::uniform(MAX_DISCOVERY_TIME-1,MAX_DISCOVERY_TIME));
  266. // fall through
  267.          break; 
  268.       case GAF_LEADER:
  269. send_discovery();
  270.        timer_.resched(Random::uniform(MAX_DISCOVERY_TIME-1,MAX_DISCOVERY_TIME));
  271. break;
  272.       default:
  273. break;
  274.       }
  275.       break;
  276.     case GAF_SELECT:
  277.         switch (state_) {
  278.   case GAF_LEADER:
  279.     // I just finish my LEADER role, put myself into FREE
  280.     // state so that I have chance to go sleep
  281.     // put myself into FREE does not hurt anything
  282.     //printf("Node (%d %d) go BACK to FREE from LEADER at %fn",nid_,gid_,Scheduler::instance().clock());
  283.     duty_timeout();
  284.     leader_settime_ = 0;
  285.     break;
  286.   case GAF_FREE:
  287.   case GAF_SLEEP:
  288.     break;
  289.   default:
  290.     break;
  291.         }
  292. break;
  293.     case GAF_DUTY:
  294.         duty_timeout();
  295.         break;
  296.     default:
  297.         printf("Wrong GAF msg time!n");
  298.     }
  299. }
  300. // adaptive fidelity timeout
  301. void GAFAgent::duty_timeout()
  302. {
  303.     double x=0.0, y=0.0, z=0.0;
  304.     // find where I am
  305.     
  306.     ((MobileNode *)thisnode)->getLoc(&x, &y, &z);
  307.     gid_ = God::instance()->getMyGrid(x,y);
  308.     // wake up myself
  309.     node_on();
  310.     
  311.     // send discovery first to try to find whether
  312.     // there is a leader around me
  313.     send_discovery();
  314.     // schedule the discovery timer randomly
  315.     // can wait longer to get a chance to be replaced
  316.     timer_.resched(gafjitter(GAF_NONSTART_JITTER, 1));
  317. }
  318. int GAFAgent::command(int argc, const char*const* argv)
  319. {
  320.         if (argc == 2) {
  321.   if (strcmp (argv[1], "start-gaf") == 0) {
  322.     // schedule the discovery timer randomly
  323.     timer_.resched(gafjitter(GAF_STARTUP_JITTER, 1));
  324.     // schedule the select phase after certain time
  325.     // of discovery msg exchange, as fast as possible
  326.     // stimer_.resched(Random::uniform(GAF_LEADER_JITTER,GAF_LEADER_JITTER+1));
  327.     return (TCL_OK); 
  328.   }
  329.       
  330. }
  331. if (argc == 3) {
  332.     if (strcmp(argv[1], "adapt-mobility") == 0) {
  333. adapt_mobility_ = atoi(argv[2]);
  334. //timer_.resched(Random::uniform(0, beacon_));
  335. return TCL_OK;
  336.     }
  337.     if (strcmp(argv[1], "maxttl") == 0) {
  338. maxttl_ = atoi(argv[2]);
  339. return TCL_OK;
  340.     }
  341. }
  342. return (Agent::command(argc, argv));
  343. }
  344. void GAFAgent::send_discovery()
  345. {
  346.         Packet *p = allocpkt();
  347. double x=0.0, y=0.0, z=0.0;
  348. hdr_gaf *h = hdr_gaf::access(p);
  349. //hdr_ip *iph = hdr_ip::access(p);
  350. h->type_ = GAF_DISCOVER;
  351. h->seqno_ = ++seqno_;
  352. // update my grid infomation
  353. ((MobileNode *)thisnode)->getLoc(&x, &y, &z);
  354. gid_ = God::instance()->getMyGrid(x,y);
  355.     
  356. makeUpDiscoveryMsg(p);
  357. send(p,0);
  358. }
  359. void
  360. GAFAgent::makeUpDiscoveryMsg(Packet *p)
  361. {
  362.   hdr_ip *iph = hdr_ip::access(p);
  363.   hdr_cmn *hdrc = hdr_cmn::access(p);
  364.   u_int32_t ttl,stime;
  365.   unsigned char *walk;
  366.   double gridsize, speed;
  367.   // fill up the header
  368.   hdrc->next_hop_ = IP_BROADCAST;
  369.   hdrc->addr_type_ = NS_AF_INET;
  370.   iph->daddr() = IP_BROADCAST << Address::instance().nodeshift();
  371.   iph->dport() = 254;
  372.   // hdrc->direction() = hdr_cmn::DOWN;
  373.   // fill up the data
  374.   p->allocdata(sizeof(DiscoveryMsg));
  375.   walk = p->accessdata ();
  376.   hdrc->size_ = sizeof(DiscoveryMsg) + IP_HDR_LEN; // Existence Msg + IP
  377.   *(walk++) = gid_ >> 24;
  378.   *(walk++) = (gid_ >> 16) & 0xFF;
  379.   *(walk++) = (gid_ >> 8) & 0xFF;
  380.   *(walk++) = (gid_ >> 0) & 0xFF;
  381.   *(walk++) = nid_ >> 24;
  382.   *(walk++) = (nid_ >> 16) & 0xFF;
  383.   *(walk++) = (nid_ >> 8) & 0xFF;
  384.   *(walk++) = (nid_ >> 0) & 0xFF;
  385.   // access my state
  386.   *(walk++) = state_ >> 24;
  387.   *(walk++) = (state_ >> 16) & 0xFF;
  388.   *(walk++) = (state_ >> 8) & 0xFF;
  389.   *(walk++) = (state_ >> 0) & 0xFF;  
  390.   // ttl tells the receiver that how much longer the sender can
  391.   // survive, cut it into half for the purpose of load balance
  392.   if (state_ == GAF_LEADER) {
  393.       // must send real msg because I am the leader
  394. ttl = (int)(leader_settime_ - NOW);
  395. if (ttl < 0) ttl = 0;
  396.   } else {
  397.       if ((ttl = (u_int32_t)myttl()) > MIN_LIFETIME) {
  398.           ttl = (u_int32_t) ttl/2;
  399.       }
  400.   }
  401.   *(walk++) = ttl >> 24;
  402.   *(walk++) = (ttl >> 16) & 0xFF;
  403.   *(walk++) = (ttl >> 8) & 0xFF;
  404.   *(walk++) = (ttl >> 0) & 0xFF;
  405.   
  406.   // fill my possible time of leaving this grid
  407.   
  408.   
  409.   speed = ((MobileNode*)thisnode)->speed();
  410.   if (speed == 0) {
  411.     // make stime big enough
  412.     stime = 2*ttl;
  413.   } else {
  414.     gridsize = God::instance()->getMyGridSize();
  415.     stime = (u_int32_t) (gridsize/speed);
  416.   }
  417.   *(walk++) = stime >> 24;
  418.   *(walk++) = (stime >> 16) & 0xFF;
  419.   *(walk++) = (stime >> 8) & 0xFF;
  420.   *(walk++) = (stime >> 0) & 0xFF;
  421.   //printf("Node %d send out Exitence msg gid/nid %d %dn", nid_, gid_, nid_);
  422. }
  423. void
  424. GAFAgent::node_off()
  425. {
  426.     Phy *p;
  427.     EnergyModel *em;
  428.     //printf ("Node (%d %d) goes SLEEP from %d at %fn",nid_, gid_, state_, Scheduler::instance().clock());
  429.     // if I am in the data transfer state, do not turn off
  430.     // if (state_ == GAF_TRAFFIC) return;
  431.     // set node state
  432.     em = thisnode->energy_model();
  433.     em->node_on() = false;
  434.     //((MobileNode *)thisnode->energy_model())->node_on() = false;
  435.     // notify phy
  436.     p  = (thisnode->ifhead()).lh_first;
  437.     if (p) {
  438. ((WirelessPhy *)p)->node_off();
  439.     }
  440.     // change agent state
  441.     setGAFstate(GAF_SLEEP);
  442. }
  443. void
  444. GAFAgent::node_on()
  445. {
  446.     Phy *p;
  447.     EnergyModel* em;
  448.     // set node state
  449.     em = thisnode->energy_model();
  450.     em->node_on() = true;
  451.     //(MobileNode *)thisnode->energy_model()->node_on() = true;
  452.     // notify phy
  453.     p = (thisnode->ifhead()).lh_first;
  454.     if (p) {
  455.         ((WirelessPhy *)p)->node_on();
  456.     }
  457.     
  458.     setGAFstate(GAF_FREE);
  459. }
  460. void 
  461. GAFAgent::setGAFstate(GafNodeState gs)
  462. {
  463.   //printf("Node (%d %d) changes state from %d to %d at %fn", nid_, gid_, state_,gs,Scheduler::instance().clock());
  464.    state_ = gs;
  465. }
  466. GAFPartner::GAFPartner() : Connector(), gafagent_(1),mask_(0xffffffff),
  467.         shift_(8)
  468. {
  469.         bind("addr_", (int*)&(here_.addr_));
  470.         bind("port_", (int*)&(here_.port_));
  471.         bind("shift_", &shift_);
  472.         bind("mask_", &mask_);
  473. }
  474. void GAFPartner::recv(Packet* p, Handler *h)
  475. {
  476.         hdr_ip* hdr = hdr_ip::access(p);
  477. hdr_cmn *hdrc = hdr_cmn::access(p);
  478. /* handle PT_GAF packet only */
  479. /* convert the dst ip if it is -1, change it into node's */
  480. /* own ip address */
  481. if ( hdrc->ptype() == PT_GAF ) {
  482.   if (gafagent_ == 1) {
  483.     if (((u_int32_t)hdr->daddr()) == IP_BROADCAST) {
  484. hdr->daddr() = here_.addr_;
  485.     }     
  486.   } else {
  487.     /* if gafagent is not installed, drop the packet */
  488.     drop (p);
  489.     return;
  490.   }
  491. }
  492. target_->recv(p,h);
  493. }
  494. int GAFPartner::command(int argc, const char*const* argv)
  495. {
  496.         if (argc == 3) {
  497.   if (strcmp (argv[1], "set-gafagent") == 0) {
  498.     gafagent_ = atoi(argv[2]);
  499.     return (TCL_OK); 
  500.   }
  501. }
  502. return Connector::command(argc, argv); 
  503. }
  504. void GAFDiscoverTimer::expire(Event *) {
  505.   a_->timeout(GAF_DISCOVER);
  506. }
  507. void GAFSelectTimer::expire(Event *) {
  508.   a_->timeout(GAF_SELECT);
  509. }
  510. void GAFDutyTimer::expire(Event *) {
  511.   a_->timeout(GAF_DUTY);
  512. }