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

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * diffusion.cc
  3.  * Copyright (C) 2000 by the University of Southern California
  4.  * $Id: diffusion.cc,v 1.14 2006/03/10 12:25:28 mahrenho 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 * modified versions; it is their choice whether to do so.  The GNU
  38.  * General Public License gives permission to release a modified
  39.  * version without this exception; this exception also makes it
  40.  * possible to release a modified version which carries forward this
  41.  * exception.
  42.  *
  43.  */
  44. //
  45. // $Header: /cvsroot/nsnam/ns-2/diffusion/diffusion.cc,v 1.14 2006/03/10 12:25:28 mahrenho Exp $
  46. /****************************************************************/
  47. /* diffusion.cc : Chalermek Intanagonwiwat (USC/ISI)  05/18/99  */
  48. /****************************************************************/
  49. // Important Note: Work still in progress !
  50. #include <assert.h>
  51. #include <math.h>
  52. #include <stdio.h>
  53. #include <signal.h>
  54. #include <float.h>
  55. #include <tcl.h>
  56. #include <stdlib.h>
  57. #include "diff_header.h"
  58. #include "agent.h"
  59. #include "tclcl.h"
  60. #include "ip.h"
  61. #include "config.h"
  62. #include "packet.h"
  63. #include "trace.h"
  64. #include "random.h"
  65. #include "classifier.h"
  66. #include "node.h"
  67. #include "diffusion.h"
  68. #include "iflist.h"
  69. #include "hash_table.h"
  70. #include "arp.h"
  71. #include "mac.h"
  72. #include "ll.h"
  73. #include "dsr/path.h"
  74. #include "god.h"
  75. #include "routing_table.h"
  76. /* Callback helper */
  77. void XmitFailedCallback(Packet *pkt, void *data)
  78. {
  79.   DiffusionAgent *agent = (DiffusionAgent *)data;  // cast of trust
  80.   agent->xmitFailed(pkt);
  81. }
  82. char *MsgStr[]= {"", "INTEREST", "DATA", "DATA_READY", "DATA_REQUEST",
  83. "POS_REINFORCE", "NEG_REINFORCE", "INHIBIT", "TX_FAILED",
  84. "DATA_STOP" };
  85. int hdr_cdiff::offset_;
  86. static class DiffHeaderClass : public PacketHeaderClass {
  87. public:
  88. DiffHeaderClass() : PacketHeaderClass("PacketHeader/Diffusion", 
  89.       sizeof(hdr_cdiff)) {
  90. bind_offset(&hdr_cdiff::offset_);
  91. }
  92. } class_diffhdr;
  93. static class DiffusionClass : public TclClass {
  94. public:
  95.   DiffusionClass() : TclClass("Agent/Diffusion") {}
  96.   TclObject* create(int , const char*const* ) {
  97.     return(new DiffusionAgent());
  98.   }
  99. } class_diffusion;
  100. void ArpBufferTimer::expire(Event *e)
  101. {
  102.   a_->ArpBufferCheck();
  103.   resched(ARP_BUFFER_CHECK + ARP_BUFFER_CHECK * 
  104.   (double) ((long) e>>5 & 0xff) /256.0);
  105. }
  106. void SendBufTimer::expire(Event *e)
  107. {
  108.   a_->SendBufferCheck();
  109.   resched(SEND_BUFFER_CHECK + SEND_BUFFER_CHECK * (double) ((long) e>>5 & 0xff)/256.0);
  110. }
  111. void DiffusionAgent::DataForSink(Packet *pkt)
  112. {
  113.   hdr_cdiff     *dfh  = HDR_CDIFF(pkt);
  114.   unsigned int dtype = dfh->data_type;
  115.   Agent_List   *cur_agent;
  116.   Packet       *cur_pkt;
  117.   hdr_cdiff     *cur_dfh;
  118.   hdr_ip       *cur_iph;
  119.   // Give it to sink agents on this node. Don't care if wireless.
  120.   for (cur_agent= (routing_table[dtype]).sink; cur_agent != NULL; 
  121.    cur_agent= AGENT_NEXT(cur_agent) ) {
  122.       cur_pkt       = pkt->copy();
  123.       cur_iph       = HDR_IP(cur_pkt);
  124.       cur_iph->dst_ = AGT_ADDR(cur_agent);
  125.       cur_dfh       = HDR_CDIFF(cur_pkt);
  126.       cur_dfh->forward_agent_id = here_;
  127.       cur_dfh->num_next = 1;
  128.       cur_dfh->next_nodes[0] = NODE_ADDR(cur_agent);
  129.       send_to_dmux(cur_pkt, 0);
  130.   }
  131. }
  132. Packet *DiffusionAgent::prepare_message(unsigned int dtype, ns_addr_t to_addr, 
  133.   int msg_type)
  134. {
  135.   Packet *pkt;
  136.   hdr_cdiff *dfh;
  137.   hdr_ip *iph;
  138.     pkt = create_packet();
  139.     dfh = HDR_CDIFF(pkt);
  140.     iph = HDR_IP(pkt);
  141.     
  142.     dfh->mess_type = msg_type;
  143.     dfh->pk_num = pk_count;
  144.     pk_count++;
  145.     dfh->sender_id = here_;
  146.     dfh->data_type = dtype;
  147.     dfh->forward_agent_id = here_;
  148.     dfh->ts_ = NOW;
  149.     dfh->num_next = 1;
  150.     dfh->next_nodes[0] = to_addr.addr_;
  151.     
  152.     iph->src_ = here_;
  153.     iph->dst_ = to_addr;
  154.     return pkt;
  155. }
  156. DiffusionAgent::DiffusionAgent() : Agent(PT_DIFF), arp_buf_timer(this), 
  157.   send_buf_timer(this)
  158. {
  159.   POS_REINF_ = true;
  160.   NEG_REINF_ = true;
  161.   overhead = 0;
  162.   pk_count = 0;
  163.   target_ = 0;
  164.   node = NULL;
  165.   tracetarget = NULL;
  166. }
  167. void DiffusionAgent::recv(Packet* packet, Handler*)
  168. {
  169.   hdr_cdiff* dfh = HDR_CDIFF(packet);
  170.   // Packet Hash Table is used to keep info about experienced pkts.
  171.   Pkt_Hash_Entry *hashPtr= PktTable.GetHash(dfh->sender_id, dfh->pk_num);
  172.      // Received this packet before ?
  173.      if (hashPtr != NULL) {
  174.        consider_old(packet);
  175.        return;
  176.      }
  177.      // Never receive it before ? Put in hash table.
  178.      PktTable.put_in_hash(dfh);
  179.      // Take action for a new pkt.
  180.      consider_new(packet);     
  181. }
  182. void DiffusionAgent::consider_old(Packet *pkt)
  183. {
  184.       Packet::free(pkt);        
  185. }
  186. void DiffusionAgent::consider_new(Packet *pkt)
  187. {
  188.       Packet::free(pkt);        
  189. }
  190. void DiffusionAgent::Terminate() 
  191. {
  192. #ifdef DEBUG_OUTPUT
  193. printf("Diffusion node %d : terminates (overhead %d)n", 
  194.        THIS_NODE, overhead);  
  195. printf("node %d: remaining energy %f, initial energy %fn", THIS_NODE, 
  196.        node->energy_model()->energy(), 
  197.        node->energy_model()->initialenergy() );
  198. Print_IOlist();
  199. #endif
  200. }
  201. void DiffusionAgent::Print_IOlist()
  202. {
  203. }
  204. void DiffusionAgent::Start()
  205. {
  206.   arp_buf_timer.sched(ARP_BUFFER_CHECK + ARP_BUFFER_CHECK * 
  207.       Random::uniform(1.0));   
  208.   send_buf_timer.sched(SEND_BUFFER_CHECK + SEND_BUFFER_CHECK *
  209.    Random::uniform(1.0));
  210. }
  211. int DiffusionAgent::command(int argc, const char*const* argv)
  212. {  
  213.   Tcl& tcl =  Tcl::instance();
  214.   if (argc == 2) {
  215.     if (strcasecmp(argv[1], "reset-state")==0) {
  216.       
  217.       reset();
  218.       return TCL_OK;
  219.     }
  220.     if (strcasecmp(argv[1], "reset")==0) {
  221.       
  222.       return Agent::command(argc, argv);
  223.     }
  224.     if (strcasecmp(argv[1], "start")==0) {
  225.       Start();
  226.       return TCL_OK;
  227.     }
  228.     if (strcasecmp(argv[1], "stop")==0) {
  229.       return TCL_OK;
  230.     }
  231.     if (strcasecmp(argv[1], "terminate")==0) {
  232.       Terminate();
  233.       return TCL_OK;
  234.     }
  235.     if (strcasecmp(argv[1], "stop-source")==0) {
  236.       StopSource();
  237.       return TCL_OK;
  238.     }
  239.     if (strcasecmp(argv[1], "enable-pos") == 0) {
  240.       POS_REINF_ = true;
  241.       return TCL_OK;
  242.     }
  243.     if (strcasecmp(argv[1], "enable-neg") == 0) {
  244.       NEG_REINF_ = true;
  245.       return TCL_OK;
  246.     }
  247.     if (strcasecmp(argv[1], "disable-pos") == 0) {
  248.       POS_REINF_ = false;
  249.       return TCL_OK;
  250.     }
  251.     if (strcasecmp(argv[1], "disable-neg") == 0) {
  252.       NEG_REINF_ = false;
  253.       return TCL_OK;
  254.     }
  255.   } else if (argc == 3) {
  256.     if (strcasecmp(argv[1], "on-node")==0) {
  257.       node = (Node *)tcl.lookup(argv[2]);
  258.       return TCL_OK;
  259.     }
  260.     if (strcasecmp(argv[1], "add-ll") == 0) {
  261.       TclObject *obj;
  262.       if ( (obj = TclObject::lookup(argv[2])) == 0) {
  263. fprintf(stderr, "Diffusion Node: %d lookup of %s failedn", THIS_NODE,
  264. argv[2]);
  265. return TCL_ERROR;
  266.       }
  267.       ll = (NsObject *) obj;
  268.       // What a hack !!!
  269.       arp_table = ((LL *)ll)->arp_table();
  270.       if (arp_table == NULL) 
  271. return TCL_ERROR;
  272.      return TCL_OK;
  273.     }
  274.     if (strcasecmp (argv[1], "tracetarget") == 0) {
  275.       TclObject *obj;
  276.       if ((obj = TclObject::lookup (argv[2])) == 0) {
  277.   fprintf (stderr, "%s: %s lookup of %s failedn", __FILE__, argv[1],
  278.    argv[2]);
  279.   return TCL_ERROR;
  280.       }
  281.       tracetarget = (Trace *) obj;
  282.       return TCL_OK;
  283.     }
  284.     if (strcasecmp(argv[1], "port-dmux") == 0) {
  285.       TclObject *obj;
  286.       if ( (obj = TclObject::lookup(argv[2])) == 0) {
  287. fprintf(stderr, "Diffusion Node: %d lookup of %s failedn", THIS_NODE,
  288. argv[2]);
  289. return TCL_ERROR;
  290.       }
  291.       port_dmux = (NsObject *) obj;
  292.       return TCL_OK;
  293.     }
  294.   } 
  295.   return Agent::command(argc, argv);
  296. }
  297. void DiffusionAgent::StopSource()
  298. {
  299.   Agent_List *cur;
  300.   for (int i=0; i<MAX_DATA_TYPE; i++) {
  301.     for (cur=routing_table[i].source; cur!=NULL; cur=AGENT_NEXT(cur) ) {
  302.       SEND_MESSAGE(i, AGT_ADDR(cur), DATA_STOP);
  303.     }
  304.   }
  305. }
  306. Packet * DiffusionAgent:: create_packet()
  307. {
  308.   Packet *pkt = allocpkt();
  309.   if (pkt==NULL) return NULL;
  310.   hdr_cmn*  cmh = HDR_CMN(pkt);
  311.   cmh->size() = 36;
  312.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  313.   dfh->ts_ = NOW;
  314.   return pkt;
  315. }
  316. void DiffusionAgent::MACprepare(Packet *pkt, nsaddr_t next_hop, 
  317. int type, bool lk_dtct)
  318. {
  319.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  320.   hdr_cmn* cmh = HDR_CMN(pkt);
  321.   hdr_ip*  iph = HDR_IP(pkt);
  322.   dfh->forward_agent_id = here_; 
  323.   if (type == (int) NS_AF_ILINK && next_hop == (nsaddr_t) MAC_BROADCAST) {
  324.       cmh->xmit_failure_ = 0;
  325.       cmh->next_hop() = MAC_BROADCAST;
  326.       cmh->addr_type() = NS_AF_ILINK;
  327.       cmh->direction() = hdr_cmn::DOWN;
  328.       
  329.       iph->src_ = here_;
  330.       iph->dst_.addr_ = next_hop;
  331.       iph->dst_.port_ = ROUTING_PORT;
  332.       dfh->num_next = 1;
  333.       dfh->next_nodes[0] = next_hop;
  334.       return;     
  335.   }  
  336.   if (lk_dtct != 0) {
  337.     cmh->xmit_failure_ = XmitFailedCallback;
  338.     cmh->xmit_failure_data_ = (void *) this;
  339.   }
  340.   else {
  341.     cmh->xmit_failure_ = 0;
  342.   }
  343.   cmh->direction() = hdr_cmn::DOWN;
  344.   cmh->next_hop() = next_hop;
  345.   cmh->addr_type() = type;  
  346.   iph->src_ = here_;
  347.   iph->dst_.addr_ = next_hop;
  348.   iph->dst_.port_ = ROUTING_PORT;
  349.   
  350.   dfh->num_next = 1;
  351.   dfh->next_nodes[0] = next_hop;
  352. }
  353. void DiffusionAgent::MACsend(Packet *pkt, Time delay)
  354. {
  355.   hdr_cmn*  cmh = HDR_CMN(pkt);
  356.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  357.   if (dfh->mess_type == DATA)
  358.     cmh->size() = (God::instance()->data_pkt_size) + 4*(dfh->num_next - 1);
  359.   else
  360.     cmh->size() = 36 + 4*(dfh->num_next -1);
  361.   Scheduler::instance().schedule(ll, pkt, delay);
  362. }
  363. void DiffusionAgent::xmitFailed(Packet *)
  364. {
  365.   // For future use, if needed.
  366. }
  367. void DiffusionAgent::StickPacketInArpBuffer(Packet *pkt)
  368. {
  369.   Time min = DBL_MAX;
  370.   int  min_index = 0;
  371.   int  c;
  372.   for (c=0; c < ARP_BUF_SIZE; c++) {
  373.     if (arp_buf[c].p == NULL) {
  374.       arp_buf[c].t = NOW;
  375.       arp_buf[c].attempt = 1;
  376.       arp_buf[c].p = pkt;
  377.       return;
  378.     }
  379.     else if (arp_buf[c].t < min) {
  380.       min = arp_buf[c].t;
  381.       min_index = c;
  382.     }
  383.   }
  384.   // Before killing somebody, let him get a last chance to send.
  385.   ARPEntry *llinfo;
  386.   hdr_cmn*  cmh = HDR_CMN(arp_buf[min_index].p);
  387.   llinfo= arp_table->arplookup(cmh->next_hop());
  388.   if (llinfo == 0) {
  389.     // printf("ARP fails. And must give up slot.n");
  390.       xmitFailed(arp_buf[min_index].p);
  391.   }
  392.   else
  393.       MACsend(arp_buf[min_index].p, 0);
  394.   // The new packet is taking over the slot of the dead guy.
  395.   arp_buf[min_index].t = NOW;
  396.   arp_buf[min_index].attempt = 1;
  397.   arp_buf[min_index].p = pkt;
  398. }
  399. void DiffusionAgent::ArpBufferCheck()
  400. {
  401.   int c;
  402.   ARPEntry *llinfo;
  403.   hdr_cmn*  cmh;
  404.   for (c = 0; c < ARP_BUF_SIZE; c++) {
  405.     if (arp_buf[c].p == NULL)
  406.       continue;
  407.     
  408.     cmh = HDR_CMN(arp_buf[c].p);
  409.     llinfo= arp_table->arplookup(cmh->next_hop());
  410.     if (llinfo != 0) {
  411.       MACsend(arp_buf[c].p, 0);
  412.       arp_buf[c].p = NULL;
  413.       continue;}
  414.     
  415.     if (arp_buf[c].attempt > ARP_MAX_ATTEMPT) {
  416.       // printf("ARP fails. Too many attempts.n");
  417.       xmitFailed(arp_buf[c].p);
  418.       arp_buf[c].p = NULL;
  419.       continue;
  420.     }
  421.     arp_table->arprequest(THIS_NODE, cmh->next_hop(), (LL *)ll);
  422.     arp_buf[c].attempt ++;
  423.   }
  424. }
  425. void DiffusionAgent::StickPacketInSendBuffer(Packet *p)
  426. {
  427.   Time min = DBL_MAX;
  428.   int min_index = 0;
  429.   int c;
  430.   for (c = 0 ; c < SEND_BUF_SIZE ; c ++)
  431.     if (send_buf[c].p  == NULL)
  432.       {
  433. send_buf[c].t = NOW;
  434. send_buf[c].p = p;
  435. return;
  436.       }
  437.     else if (send_buf[c].t < min)
  438.       {
  439. min = send_buf[c].t;
  440. min_index = c;
  441.       }
  442.   
  443.   // Before killing somebody, you'd better give him the last chance.
  444.   hdr_cdiff  *dfh = HDR_CDIFF(send_buf[min_index].p);
  445.   hdr_ip    *iph = HDR_IP(send_buf[min_index].p);
  446.   int dtype = dfh->data_type;
  447.   PrvCurPtr RetVal = INTF_FIND(routing_table[dtype].active, iph->dst_);
  448.   if (RetVal.cur != NULL)   
  449.       MACsend(send_buf[min_index].p, 0);
  450.   else
  451.       Packet::free(send_buf[min_index].p);
  452.   // A new packet is taking over the slot.
  453.   send_buf[min_index].t = Scheduler::instance().clock();
  454.   send_buf[min_index].p = p;
  455. }
  456. void DiffusionAgent::SendBufferCheck()
  457. {
  458.   int c;
  459.   hdr_cdiff *dfh;
  460.   hdr_cmn  *cmh;
  461.   hdr_ip   *iph;
  462.   int dtype;
  463.   PrvCurPtr RetVal;
  464.   for (c = 0; c < SEND_BUF_SIZE; c++) {
  465.     if (send_buf[c].p == NULL)
  466.       continue;
  467.     
  468.     dfh = HDR_CDIFF(send_buf[c].p);
  469.     cmh = HDR_CMN(send_buf[c].p);
  470.     iph = HDR_IP(send_buf[c].p);
  471.     dtype = dfh->data_type;
  472.     RetVal = INTF_FIND(routing_table[dtype].active, iph->dst_);
  473.     if (RetVal.cur != NULL) {
  474.       MACsend(send_buf[c].p, 0);
  475.       send_buf[c].p = NULL;
  476.       continue;
  477.     }
  478.     
  479.     if (Scheduler::instance().clock() - send_buf[c].t > SEND_TIMEOUT) {
  480.       Packet::free(send_buf[c].p);
  481.       send_buf[c].p = NULL;
  482.       continue;
  483.     }
  484.   }
  485. }
  486. void DiffusionAgent::trace (char *fmt,...)
  487. {
  488.   va_list ap;
  489.   if (!tracetarget)
  490.     return;
  491.   va_start (ap, fmt);
  492.   vsprintf (tracetarget->pt_->buffer (), fmt, ap);
  493.   tracetarget->pt_->dump ();
  494.   va_end (ap);
  495. }
  496. void DiffusionAgent::reset()
  497. {
  498.   PktTable.reset();
  499.   for (int i=0; i<MAX_DATA_TYPE; i++) {
  500.     routing_table[i].reset();
  501.   }
  502.   clear_arp_buf();
  503.   clear_send_buf();
  504. }
  505. void DiffusionAgent::clear_arp_buf()
  506. {
  507.   for (int i=0; i<ARP_BUF_SIZE; i++) {
  508.     arp_buf[i].t = 0;
  509.     arp_buf[i].attempt = 0;
  510.     if (arp_buf[i].p != NULL) 
  511.       Packet::free(arp_buf[i].p);
  512.     arp_buf[i].p = NULL;
  513.   }
  514. }
  515. void DiffusionAgent::clear_send_buf()
  516. {
  517.   for (int i=0; i<SEND_BUF_SIZE; i++) {
  518.     send_buf[i].t = 0;
  519.     if (send_buf[i].p != NULL)
  520.       Packet::free(send_buf[i].p);
  521.     send_buf[i].p = NULL;
  522.   }
  523. }
  524.