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

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * flooding.cc
  3.  * Copyright (C) 2000 by the University of Southern California
  4.  * $Id: flooding.cc,v 1.9 2005/08/25 18:58:03 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. /****************************************************************/
  46. /* flooding.cc : Chalermek Intanagonwiwat (USC/ISI)  05/18/99   */
  47. /****************************************************************/
  48. // Share api with diffusion and omnicient multicast
  49. // Using diffusion packet header 
  50. #include <assert.h>
  51. #include <math.h>
  52. #include <stdio.h>
  53. #include <signal.h>
  54. #include <float.h>
  55. #include <stdlib.h>
  56. #include <tcl.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 "flooding.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. static class FloodingClass : public TclClass {
  76. public:
  77.   FloodingClass() : TclClass("Agent/Flooding") {}
  78.   TclObject* create(int argc, const char*const* argv) {
  79.     return(new FloodingAgent());
  80.   }
  81. } class_flooding;
  82. FloodingAgent::FloodingAgent() : Agent(PT_DIFF)
  83. {
  84.   // Initialize variables.
  85.   pk_count = 0;
  86.   target_ = 0;
  87.   node = NULL;
  88.   tracetarget = NULL;
  89. }
  90. void FloodingAgent::recv(Packet* packet, Handler*)
  91. {
  92.   hdr_cdiff* dfh = HDR_CDIFF(packet);
  93.   // Packet Hash Table is used to keep info about experienced pkts.
  94.   Pkt_Hash_Entry *hashPtr= PktTable.GetHash(dfh->sender_id, dfh->pk_num);
  95.      // Received this packet before ?
  96.      if (hashPtr != NULL) {
  97.        Packet::free(packet);        
  98.        return;
  99.      }
  100.      // Never receive it before ? Put in hash table.
  101.      PktTable.put_in_hash(dfh);
  102.      // Take action for a new pkt.
  103.        
  104.      ConsiderNew(packet);     
  105. }
  106. void FloodingAgent::ConsiderNew(Packet *pkt)
  107. {
  108.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  109.   unsigned char msg_type = dfh->mess_type;
  110.   unsigned int dtype = dfh->data_type;
  111.   Pkt_Hash_Entry *hashPtr;
  112.   Agent_List *agentPtr;
  113.   PrvCurPtr  RetVal;
  114.   nsaddr_t   from_nodeID, forward_nodeID;
  115.   Packet *gen_pkt;
  116.   hdr_cdiff *gen_dfh;
  117.   switch (msg_type) {
  118.     case INTEREST : 
  119.       hashPtr = PktTable.GetHash(dfh->sender_id, dfh->pk_num);
  120.       // Check if it comes from sink agent of this node
  121.       // If so we have to keep it in sink list 
  122.       from_nodeID = (dfh->sender_id).addr_;
  123.       forward_nodeID = (dfh->forward_agent_id).addr_;
  124.       if (THIS_NODE == from_nodeID) {       
  125. // It's from a sink on this node.
  126. // Is it already in list ?
  127. RetVal = INTF_FIND(routing_table[dtype].sink, dfh->sender_id);
  128. if (RetVal.cur == NULL) {            
  129.   // No, it's not.
  130.   agentPtr = new Agent_List;
  131.   AGT_ADDR(agentPtr) = dfh->sender_id;
  132.   INTF_INSERT(routing_table[dtype].sink, agentPtr);
  133.   God::instance()->AddSink(dtype, THIS_NODE);
  134. }
  135.       }
  136.   
  137.       Packet::free(pkt);
  138.       return;
  139.     case DATA_READY :
  140.       // put source_agent in source list of routing table
  141.       agentPtr = new Agent_List;
  142.       AGT_ADDR(agentPtr) = dfh->sender_id;
  143.       agentPtr->next = routing_table[dtype].source;
  144.       routing_table[dtype].source = agentPtr;
  145.       God::instance()->AddSource(dtype, (dfh->sender_id).addr_);
  146.       gen_pkt = prepare_message(dtype, dfh->sender_id, DATA_REQUEST);
  147.       gen_dfh = HDR_CDIFF(gen_pkt);
  148.       gen_dfh->report_rate = ORIGINAL;
  149.       send_to_dmux(gen_pkt, 0);
  150.       Packet::free(pkt);
  151.       return;
  152.  
  153.     case DATA :
  154.       DataForSink(pkt);
  155.       MACprepare(pkt);
  156.       MACsend(pkt, JITTER*Random::uniform(1.0));
  157.       return;
  158.     default : 
  159.       
  160.       Packet::free(pkt);        
  161.       break;
  162.   }
  163. }
  164. void FloodingAgent::reset()
  165. {
  166.   PktTable.reset();
  167.   for (int i=0; i<MAX_DATA_TYPE; i++) {
  168.     routing_table[i].reset();
  169.   }
  170. }
  171. void FloodingAgent::Terminate() 
  172. {
  173. #ifdef DEBUG_OUTPUT
  174. printf("node %d: remaining energy %f, initial energy %fn", THIS_NODE, 
  175.        node->energy_model()->energy(), 
  176.        node->energy_model()->initialenergy() );
  177. #endif
  178. }
  179. void FloodingAgent::StopSource()
  180. {
  181.   Agent_List *cur;
  182.   for (int i=0; i<MAX_DATA_TYPE; i++) {
  183.     for (cur=routing_table[i].source; cur!=NULL; cur=AGENT_NEXT(cur) ) {
  184.       SEND_MESSAGE(i, AGT_ADDR(cur), DATA_STOP);
  185.     }
  186.   }
  187. }
  188. Packet * FloodingAgent:: create_packet()
  189. {
  190.   Packet *pkt = allocpkt();
  191.   if (pkt==NULL) return NULL;
  192.   hdr_cmn*  cmh = HDR_CMN(pkt);
  193.   cmh->size() = 36;
  194.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  195.   dfh->ts_ = NOW;
  196.   return pkt;
  197. }
  198. Packet *FloodingAgent::prepare_message(unsigned int dtype, ns_addr_t to_addr, 
  199.   int msg_type)
  200. {
  201.   Packet *pkt;
  202.   hdr_cdiff *dfh;
  203.   hdr_ip *iph;
  204.     pkt = create_packet();
  205.     dfh = HDR_CDIFF(pkt);
  206.     iph = HDR_IP(pkt);
  207.     
  208.     dfh->mess_type = msg_type;
  209.     dfh->pk_num = pk_count;
  210.     pk_count++;
  211.     dfh->sender_id = here_;
  212.     dfh->data_type = dtype;
  213.     dfh->forward_agent_id = here_;
  214.     dfh->ts_ = NOW;
  215.     dfh->num_next = 1;
  216.     dfh->next_nodes[0] = to_addr.addr_;
  217.     
  218.     iph->src_ = here_;
  219.     iph->dst_ = to_addr;
  220.     return pkt;
  221. }
  222. void FloodingAgent::MACprepare(Packet *pkt)
  223. {
  224.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  225.   hdr_cmn* cmh = HDR_CMN(pkt);
  226.   hdr_ip*  iph = HDR_IP(pkt);
  227.   dfh->forward_agent_id = here_; 
  228.   cmh->xmit_failure_ = 0;
  229.   cmh->next_hop() = MAC_BROADCAST;
  230.   cmh->addr_type() = NS_AF_ILINK;
  231.   cmh->direction() = hdr_cmn::DOWN;
  232.   iph->src_ = here_;
  233.   iph->dst_.addr_ = MAC_BROADCAST;
  234.   iph->dst_.port_ = ROUTING_PORT;
  235.   dfh->num_next = 1;
  236.   dfh->next_nodes[0] = MAC_BROADCAST;
  237. }
  238. void FloodingAgent::MACsend(Packet *pkt, Time delay)
  239. {
  240.   hdr_cmn*  cmh = HDR_CMN(pkt);
  241.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  242.   if (dfh->mess_type == DATA)
  243.     cmh->size() = (God::instance()->data_pkt_size) + 4*(dfh->num_next - 1);
  244.   else
  245.     cmh->size() = 36 + 4*(dfh->num_next -1);
  246.   Scheduler::instance().schedule(ll, pkt, delay);
  247. }
  248. void FloodingAgent::DataForSink(Packet *pkt)
  249. {
  250.   hdr_cdiff     *dfh  = HDR_CDIFF(pkt);
  251.   unsigned int dtype = dfh->data_type;
  252.   Agent_List   *cur_agent;
  253.   Packet       *cur_pkt;
  254.   hdr_cdiff     *cur_dfh;
  255.   hdr_ip       *cur_iph;
  256.   for (cur_agent= (routing_table[dtype]).sink; cur_agent != NULL; 
  257.    cur_agent= AGENT_NEXT(cur_agent) ) {
  258.       cur_pkt       = pkt->copy();
  259.       cur_iph       = HDR_IP(cur_pkt);
  260.       cur_iph->dst_ = AGT_ADDR(cur_agent);
  261.       cur_dfh       = HDR_CDIFF(cur_pkt);
  262.       cur_dfh->forward_agent_id = here_;
  263.       cur_dfh->num_next = 1;
  264.       cur_dfh->next_nodes[0] = NODE_ADDR(cur_agent);
  265.       send_to_dmux(cur_pkt, 0);
  266.   }
  267. }
  268. void FloodingAgent::trace (char *fmt,...)
  269. {
  270.   va_list ap;
  271.   if (!tracetarget)
  272.     return;
  273.   va_start (ap, fmt);
  274.   vsprintf (tracetarget->pt_->buffer(), fmt, ap);
  275.   tracetarget->pt_->dump ();
  276.   va_end (ap);
  277. }
  278. int FloodingAgent::command(int argc, const char*const* argv)
  279. {  
  280.   Tcl& tcl =  Tcl::instance();
  281.   if (argc == 2) {
  282.     if (strcasecmp(argv[1], "reset-state")==0) {
  283.       
  284.       reset();
  285.       return TCL_OK;
  286.     }
  287.     if (strcasecmp(argv[1], "reset")==0) {
  288.       
  289.       return Agent::command(argc, argv);
  290.     }
  291.     if (strcasecmp(argv[1], "start")==0) {
  292.       return TCL_OK;
  293.     }
  294.     if (strcasecmp(argv[1], "stop")==0) {
  295.       return TCL_OK;
  296.     }
  297.     if (strcasecmp(argv[1], "terminate")==0) {
  298.       Terminate();
  299.       return TCL_OK;
  300.     }
  301.     if (strcasecmp(argv[1], "stop-source")==0) {
  302.       StopSource();
  303.       return TCL_OK;
  304.     }
  305.   } else if (argc == 3) {
  306.     if (strcasecmp(argv[1], "on-node")==0) {
  307.       node = (Node *)tcl.lookup(argv[2]);
  308.       return TCL_OK;
  309.     }
  310.     if (strcasecmp(argv[1], "add-ll") == 0) {
  311.       TclObject *obj;
  312.       if ( (obj = TclObject::lookup(argv[2])) == 0) {
  313. fprintf(stderr, "Flooding Node: %d lookup of %s failedn", THIS_NODE,
  314. argv[2]);
  315. return TCL_ERROR;
  316.       }
  317.       ll = (NsObject *) obj;
  318.      return TCL_OK;
  319.     }
  320.     if (strcasecmp (argv[1], "tracetarget") == 0) {
  321.       TclObject *obj;
  322.       if ((obj = TclObject::lookup (argv[2])) == 0) {
  323.   fprintf (stderr, "%s: %s lookup of %s failedn", __FILE__, argv[1],
  324.    argv[2]);
  325.   return TCL_ERROR;
  326.       }
  327.       tracetarget = (Trace *) obj;
  328.       return TCL_OK;
  329.     }
  330.     if (strcasecmp(argv[1], "port-dmux") == 0) {
  331.       TclObject *obj;
  332.       if ( (obj = TclObject::lookup(argv[2])) == 0) {
  333. fprintf(stderr, "Flooding Node: %d lookup of %s failedn", THIS_NODE,
  334. argv[2]);
  335. return TCL_ERROR;
  336.       }
  337.       port_dmux = (NsObject *) obj;
  338.       return TCL_OK;
  339.     }
  340.   } 
  341.   return Agent::command(argc, argv);
  342. }
  343. // Some methods for Flooding Entry
  344. void Flooding_Entry::reset()
  345. {
  346.     clear_agentlist(source);
  347.     clear_agentlist(sink);
  348.     source = NULL;
  349.     sink = NULL;
  350. }
  351. void Flooding_Entry::clear_agentlist(Agent_List *list)
  352. {
  353.   Agent_List *cur=list;
  354.   Agent_List *temp = NULL;
  355.   while (cur != NULL) {
  356.     temp = AGENT_NEXT(cur);
  357.     delete cur;
  358.     cur = temp;
  359.   }
  360. }