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

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * omni_mcast.cc
  3.  * Copyright (C) 2000 by the University of Southern California
  4.  * $Id: omni_mcast.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
  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. /* omni_mcast.cc : Chalermek Intanagonwiwat (USC/ISI)  05/18/99  */
  47. /*****************************************************************/
  48. // Share api with diffusion and flooding
  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 "omni_mcast.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. /* Callback helper */
  76. void OmniMcastXmitFailedCallback(Packet *pkt, void *data)
  77. {
  78.   OmniMcastAgent *agent = (OmniMcastAgent *)data;  // cast of trust
  79.   agent->xmitFailed(pkt);
  80. }
  81. static class OmniMcastClass : public TclClass {
  82. public:
  83.   OmniMcastClass() : TclClass("Agent/OmniMcast") {}
  84.   TclObject* create(int argc, const char*const* argv) {
  85.     return(new OmniMcastAgent());
  86.   }
  87. } class_omni_mcast;
  88. void OmniMcastArpBufferTimer::expire(Event *e)
  89. {
  90.   a_->ArpBufferCheck();
  91.   resched(ARP_BUFFER_CHECK + ARP_BUFFER_CHECK * 
  92.   (double) ((long) e>>5 & 0xff) /256.0);
  93. }
  94. void OmniMcastSendBufTimer::expire(Event *e)
  95. {
  96.   a_->SendBufferCheck();
  97.   resched(SEND_BUFFER_CHECK + SEND_BUFFER_CHECK * (double) ((long) e>>5 & 0xff)/256.0);
  98. }
  99. void OmniMcastAgent::DataForSink(Packet *pkt)
  100. {
  101.   hdr_cdiff     *dfh  = HDR_CDIFF(pkt);
  102.   unsigned int dtype = dfh->data_type;
  103.   Agent_List   *cur_agent;
  104.   Packet       *cur_pkt;
  105.   hdr_cdiff     *cur_dfh;
  106.   hdr_ip       *cur_iph;
  107.   for (cur_agent= (routing_table[dtype]).sink; cur_agent != NULL; 
  108.    cur_agent= AGENT_NEXT(cur_agent) ) {
  109.       cur_pkt       = pkt->copy();
  110.       cur_iph       = HDR_IP(cur_pkt);
  111.       cur_iph->dst_ = AGT_ADDR(cur_agent);
  112.       cur_dfh       = HDR_CDIFF(cur_pkt);
  113.       cur_dfh->forward_agent_id = here_;
  114.       cur_dfh->num_next = 1;
  115.       cur_dfh->next_nodes[0] = NODE_ADDR(cur_agent);
  116.       send_to_dmux(cur_pkt, 0);
  117.   }
  118. }
  119. void OmniMcastAgent::GodForwardData(Packet *pkt)
  120. {
  121.   hdr_cdiff     *dfh  = HDR_CDIFF(pkt);
  122.   unsigned int dtype = dfh->data_type;
  123.   Packet       *cur_pkt;
  124.   hdr_cdiff     *cur_dfh;
  125.   hdr_ip       *cur_iph;
  126.   nsaddr_t     src_node = (dfh->sender_id).addr_;
  127.   int          ret_num_oif;
  128.   int *next_oif= God::instance()->NextOIFs(dtype, src_node, THIS_NODE, 
  129.    &ret_num_oif);
  130.   if (ret_num_oif == 0) {
  131.     Packet::free(pkt);
  132.     return;
  133.   }
  134.   assert(next_oif != NULL);
  135.   for (int i=0; i<ret_num_oif; i++) {
  136.       cur_pkt       = pkt->copy();
  137.       cur_iph       = HDR_IP(cur_pkt);
  138.       (cur_iph->dst_).addr_ = next_oif[i];
  139.       (cur_iph->dst_).port_ = ROUTING_PORT;
  140.       cur_dfh       = HDR_CDIFF(cur_pkt);
  141.       cur_dfh->forward_agent_id = here_;
  142.       cur_dfh->num_next = 1;
  143.       cur_dfh->next_nodes[0] = next_oif[i];
  144.       MACprepare(cur_pkt, next_oif[i], NS_AF_INET, MAC_RETRY_);
  145.       MACsend(cur_pkt, 0);
  146.   }
  147.    delete []next_oif;
  148.    Packet::free(pkt);
  149. }
  150. Packet *OmniMcastAgent::prepare_message(unsigned int dtype, ns_addr_t to_addr, 
  151.   int msg_type)
  152. {
  153.   Packet *pkt;
  154.   hdr_cdiff *dfh;
  155.   hdr_ip *iph;
  156.     pkt = create_packet();
  157.     dfh = HDR_CDIFF(pkt);
  158.     iph = HDR_IP(pkt);
  159.     
  160.     dfh->mess_type = msg_type;
  161.     dfh->pk_num = pk_count;
  162.     pk_count++;
  163.     dfh->sender_id = here_;
  164.     dfh->data_type = dtype;
  165.     dfh->forward_agent_id = here_;
  166.     dfh->ts_ = NOW;
  167.     dfh->num_next = 1;
  168.     dfh->next_nodes[0] = to_addr.addr_;
  169.     
  170.     iph->src_ = here_;
  171.     iph->dst_ = to_addr;
  172.     return pkt;
  173. }
  174. OmniMcastAgent::OmniMcastAgent() : Agent(PT_DIFF), arp_buf_timer(this), 
  175.   send_buf_timer(this)
  176. {
  177.   pk_count = 0;
  178.   target_ = 0;
  179.   node = NULL;
  180.   tracetarget = NULL;
  181. }
  182. void OmniMcastAgent::recv(Packet* packet, Handler*)
  183. {
  184.   hdr_cdiff* dfh = HDR_CDIFF(packet);
  185.   // Packet Hash Table is used to keep info about experienced pkts.
  186.   Pkt_Hash_Entry *hashPtr= PktTable.GetHash(dfh->sender_id, dfh->pk_num);
  187.      // Received this packet before ?
  188.      if (hashPtr != NULL) {
  189.        Packet::free(packet);
  190.        return;
  191.      }
  192.      // Never receive it before ? Put in hash table.
  193.      PktTable.put_in_hash(dfh);
  194.      // Take action for a new pkt.
  195.      ConsiderNew(packet);     
  196. }
  197. void OmniMcastAgent::ConsiderNew(Packet *pkt)
  198. {
  199.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  200.   unsigned char msg_type = dfh->mess_type;
  201.   unsigned int dtype = dfh->data_type;
  202.   Pkt_Hash_Entry *hashPtr;
  203.   Agent_List *agentPtr;
  204.   PrvCurPtr  RetVal;
  205.   nsaddr_t   from_nodeID, forward_nodeID;
  206.   Packet *gen_pkt;
  207.   hdr_cdiff *gen_dfh;
  208.   switch (msg_type) {
  209.     case INTEREST : 
  210.       hashPtr = PktTable.GetHash(dfh->sender_id, dfh->pk_num);
  211.       // Check if it comes from sink agent of this node
  212.       // If so we have to keep it in sink list 
  213.       from_nodeID = (dfh->sender_id).addr_;
  214.       forward_nodeID = (dfh->forward_agent_id).addr_;
  215.       if (THIS_NODE == from_nodeID) {       
  216. // It's from a sink on this node.
  217. // Is it already in list ?
  218. RetVal = INTF_FIND(routing_table[dtype].sink, dfh->sender_id);
  219. if (RetVal.cur == NULL) {            
  220.   // No, it's not.
  221.   agentPtr = new Agent_List;
  222.   AGT_ADDR(agentPtr) = dfh->sender_id;
  223.   INTF_INSERT(routing_table[dtype].sink, agentPtr);
  224.   God::instance()->AddSink(dtype, THIS_NODE);
  225. }
  226.       }
  227.       Packet::free(pkt);
  228.       return;
  229.     case DATA_READY :
  230.       // put source_agent in source list of routing table
  231.       agentPtr = new Agent_List;
  232.       AGT_ADDR(agentPtr) = dfh->sender_id;
  233.       agentPtr->next = routing_table[dtype].source;
  234.       routing_table[dtype].source = agentPtr;
  235.       God::instance()->AddSource(dtype, (dfh->sender_id).addr_);
  236.       gen_pkt = prepare_message(dtype, dfh->sender_id, DATA_REQUEST);
  237.       gen_dfh = HDR_CDIFF(gen_pkt);
  238.       gen_dfh->report_rate = ORIGINAL;
  239.       send_to_dmux(gen_pkt, 0);
  240.       Packet::free(pkt);
  241.       return;
  242.     case DATA :
  243.       DataForSink(pkt);
  244.       GodForwardData(pkt);
  245.       return;
  246.     default : 
  247.       
  248.       Packet::free(pkt);        
  249.       break;
  250.   }
  251. }
  252. void OmniMcastAgent::Terminate() 
  253. {
  254. #ifdef DEBUG_OUTPUT
  255. printf("node %d: remaining energy %f, initial energy %fn", THIS_NODE, 
  256.        node->energy_model()->energy(), 
  257.        node->energy_model()->initialenergy() );
  258. #endif
  259. }
  260. void OmniMcastAgent::Start()
  261. {
  262.   arp_buf_timer.sched(ARP_BUFFER_CHECK + ARP_BUFFER_CHECK * 
  263.       Random::uniform(1.0));   
  264.   send_buf_timer.sched(SEND_BUFFER_CHECK + SEND_BUFFER_CHECK *
  265.    Random::uniform(1.0));
  266. }
  267. void OmniMcastAgent::StopSource()
  268. {
  269.   Agent_List *cur;
  270.   for (int i=0; i<MAX_DATA_TYPE; i++) {
  271.     for (cur=routing_table[i].source; cur!=NULL; cur=AGENT_NEXT(cur) ) {
  272.       SEND_MESSAGE(i, AGT_ADDR(cur), DATA_STOP);
  273.     }
  274.   }
  275. }
  276. Packet * OmniMcastAgent:: create_packet()
  277. {
  278.   Packet *pkt = allocpkt();
  279.   if (pkt==NULL) return NULL;
  280.   hdr_cmn*  cmh = HDR_CMN(pkt);
  281.   cmh->size() = 36;
  282.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  283.   dfh->ts_ = NOW;
  284.   return pkt;
  285. }
  286. void OmniMcastAgent::MACprepare(Packet *pkt, nsaddr_t next_hop, 
  287. unsigned int type, bool lk_dtct)
  288. {
  289.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  290.   hdr_cmn* cmh = HDR_CMN(pkt);
  291.   hdr_ip*  iph = HDR_IP(pkt);
  292.   dfh->forward_agent_id = here_; 
  293.   if (type == NS_AF_ILINK && next_hop == (nsaddr_t)MAC_BROADCAST) {
  294.       cmh->xmit_failure_ = 0;
  295.       cmh->next_hop() = MAC_BROADCAST;
  296.       cmh->addr_type() = NS_AF_ILINK;
  297.       cmh->direction() = hdr_cmn::DOWN;
  298.       
  299.       iph->src_ = here_;
  300.       iph->dst_.addr_ = next_hop;
  301.       iph->dst_.port_ = ROUTING_PORT;
  302.       dfh->num_next = 1;
  303.       dfh->next_nodes[0] = next_hop;
  304.       return;     
  305.   }  
  306.   if (lk_dtct != 0) {
  307.     cmh->xmit_failure_ = OmniMcastXmitFailedCallback;
  308.     cmh->xmit_failure_data_ = (void *) this;
  309.   }
  310.   else {
  311.     cmh->xmit_failure_ = 0;
  312.   }
  313.   cmh->direction() = hdr_cmn::DOWN;
  314.   cmh->next_hop() = next_hop;
  315.   cmh->addr_type() = type;  
  316.   iph->src_ = here_;
  317.   iph->dst_.addr_ = next_hop;
  318.   iph->dst_.port_ = ROUTING_PORT;
  319.   
  320.   dfh->num_next = 1;
  321.   dfh->next_nodes[0] = next_hop;
  322. }
  323. void OmniMcastAgent::MACsend(Packet *pkt, Time delay)
  324. {
  325.   hdr_cmn*  cmh = HDR_CMN(pkt);
  326.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  327.   if (dfh->mess_type == DATA)
  328.     cmh->size() = (God::instance()->data_pkt_size) + 4*(dfh->num_next - 1);
  329.   else
  330.     cmh->size() = 36 + 4*(dfh->num_next -1);
  331.   Scheduler::instance().schedule(ll, pkt, delay);
  332. }
  333. void OmniMcastAgent::xmitFailed(Packet *pkt)
  334. {
  335.   // For future extension if needed.
  336. }
  337. void OmniMcastAgent::StickPacketInArpBuffer(Packet *pkt)
  338. {
  339.   Time min = DBL_MAX;
  340.   int  min_index = 0;
  341.   int  c;
  342.   for (c=0; c < ARP_BUF_SIZE; c++) {
  343.     if (arp_buf[c].p == NULL) {
  344.       arp_buf[c].t = NOW;
  345.       arp_buf[c].attempt = 1;
  346.       arp_buf[c].p = pkt;
  347.       return;
  348.     }
  349.     else if (arp_buf[c].t < min) {
  350.       min = arp_buf[c].t;
  351.       min_index = c;
  352.     }
  353.   }
  354.   // Before killing somebody, let him get a last chance to send.
  355.   ARPEntry *llinfo;
  356.   hdr_cmn*  cmh = HDR_CMN(arp_buf[min_index].p);
  357.   llinfo= arp_table->arplookup(cmh->next_hop());
  358.   if (llinfo == 0) {
  359.     // printf("ARP fails. And must give up slot.n");
  360.       xmitFailed(arp_buf[min_index].p);
  361.   }
  362.   else
  363.       MACsend(arp_buf[min_index].p, 0);
  364.   // The new packet is taking over the slot of the dead guy.
  365.   arp_buf[min_index].t = NOW;
  366.   arp_buf[min_index].attempt = 1;
  367.   arp_buf[min_index].p = pkt;
  368. }
  369. void OmniMcastAgent::ArpBufferCheck()
  370. {
  371.   int c;
  372.   ARPEntry *llinfo;
  373.   hdr_cmn*  cmh;
  374.   for (c = 0; c < ARP_BUF_SIZE; c++) {
  375.     if (arp_buf[c].p == NULL)
  376.       continue;
  377.     
  378.     cmh = HDR_CMN(arp_buf[c].p);
  379.     llinfo= arp_table->arplookup(cmh->next_hop());
  380.     if (llinfo != 0) {
  381.       MACsend(arp_buf[c].p, 0);
  382.       arp_buf[c].p = NULL;
  383.       continue;}
  384.     
  385.     if (arp_buf[c].attempt > ARP_MAX_ATTEMPT) {
  386.       // printf("ARP fails. Too many attempts.n");
  387.       xmitFailed(arp_buf[c].p);
  388.       arp_buf[c].p = NULL;
  389.       continue;
  390.     }
  391.     arp_table->arprequest(THIS_NODE, cmh->next_hop(), (LL *)ll);
  392.     arp_buf[c].attempt ++;
  393.   }
  394. }
  395. void OmniMcastAgent::StickPacketInSendBuffer(Packet *p)
  396. {
  397.   Time min = DBL_MAX;
  398.   int min_index = 0;
  399.   int c;
  400.   for (c = 0 ; c < SEND_BUF_SIZE ; c ++) {
  401.     if (send_buf[c].p  == NULL)
  402.       {
  403. send_buf[c].t = NOW;
  404. send_buf[c].p = p;
  405. return;
  406.       }
  407.     else if (send_buf[c].t < min)
  408.       {
  409. min = send_buf[c].t;
  410. min_index = c;
  411.       }
  412.   }
  413.   // Before killing somebody, you'd better give him the last chance.
  414.   if (send_buf[min_index].p != NULL) {
  415.     MACsend(send_buf[min_index].p, 0);
  416.   }
  417.   // A new packet is taking over the slot.
  418.   send_buf[min_index].t = Scheduler::instance().clock();
  419.   send_buf[min_index].p = p;
  420. }
  421. void OmniMcastAgent::SendBufferCheck()
  422. {
  423.   for (int c = 0; c < SEND_BUF_SIZE; c++) {
  424.     if (send_buf[c].p != NULL) {
  425.       MACsend(send_buf[c].p, 0);
  426.       send_buf[c].p = NULL;
  427.     }
  428.   }
  429. }
  430. void OmniMcastAgent::trace (char *fmt,...)
  431. {
  432.   va_list ap;
  433.   if (!tracetarget)
  434.     return;
  435.   va_start (ap, fmt);
  436.   vsprintf (tracetarget->pt_->buffer (), fmt, ap);
  437.   tracetarget->pt_->dump ();
  438.   va_end (ap);
  439. }
  440. int OmniMcastAgent::command(int argc, const char*const* argv)
  441. {  
  442.   Tcl& tcl =  Tcl::instance();
  443.   if (argc == 2) {
  444.     if (strcasecmp(argv[1], "reset-state")==0) {
  445.       reset();
  446.       return TCL_OK;
  447.     }
  448.     if (strcasecmp(argv[1], "reset")==0) {
  449.       return Agent::command(argc, argv);
  450.     }
  451.     if (strcasecmp(argv[1], "start")==0) {
  452.       Start();
  453.       return TCL_OK;
  454.     }
  455.     if (strcasecmp(argv[1], "stop")==0) {
  456.       return TCL_OK;
  457.     }
  458.     if (strcasecmp(argv[1], "terminate")==0) {
  459.       Terminate();
  460.       return TCL_OK;
  461.     }
  462.     if (strcasecmp(argv[1], "stop-source")==0) {
  463.       StopSource();
  464.       return TCL_OK;
  465.     }
  466.   } else if (argc == 3) {
  467.     if (strcasecmp(argv[1], "on-node")==0) {
  468.       node = (Node *)tcl.lookup(argv[2]);
  469.       return TCL_OK;
  470.     }
  471.     if (strcasecmp(argv[1], "add-ll") == 0) {
  472.       TclObject *obj;
  473.       if ( (obj = TclObject::lookup(argv[2])) == 0) {
  474. fprintf(stderr, "OmniMcast Node: %d lookup of %s failedn", THIS_NODE,
  475. argv[2]);
  476. return TCL_ERROR;
  477.       }
  478.       ll = (NsObject *) obj;
  479.       // What a hack !!!
  480.       arp_table = ((LL *)ll)->arp_table();
  481.       if (arp_table == NULL) 
  482. return TCL_ERROR;
  483.      return TCL_OK;
  484.     }
  485.     if (strcasecmp (argv[1], "tracetarget") == 0) {
  486.       TclObject *obj;
  487.       if ((obj = TclObject::lookup (argv[2])) == 0) {
  488.   fprintf (stderr, "%s: %s lookup of %s failedn", __FILE__, argv[1],
  489.    argv[2]);
  490.   return TCL_ERROR;
  491.       }
  492.       tracetarget = (Trace *) obj;
  493.       return TCL_OK;
  494.     }
  495.     if (strcasecmp(argv[1], "port-dmux") == 0) {
  496.       TclObject *obj;
  497.       if ( (obj = TclObject::lookup(argv[2])) == 0) {
  498. fprintf(stderr, "OmniMcast Node: %d lookup of %s failedn", THIS_NODE,
  499. argv[2]);
  500. return TCL_ERROR;
  501.       }
  502.       port_dmux = (NsObject *) obj;
  503.       return TCL_OK;
  504.     }
  505.   } 
  506.   return Agent::command(argc, argv);
  507. }
  508. void OmniMcastAgent::reset()
  509. {
  510.   PktTable.reset();
  511.   for (int i=0; i<MAX_DATA_TYPE; i++) {
  512.     routing_table[i].reset();
  513.   }
  514.   clear_arp_buf();
  515.   clear_send_buf();
  516. }
  517. void OmniMcastAgent::clear_arp_buf()
  518. {
  519.   for (int i=0; i<ARP_BUF_SIZE; i++) {
  520.     arp_buf[i].t = 0;
  521.     arp_buf[i].attempt = 0;
  522.     if (arp_buf[i].p != NULL) 
  523.       Packet::free(arp_buf[i].p);
  524.     arp_buf[i].p = NULL;
  525.   }
  526. }
  527. void OmniMcastAgent::clear_send_buf()
  528. {
  529.   for (int i=0; i<SEND_BUF_SIZE; i++) {
  530.     send_buf[i].t = 0;
  531.     if (send_buf[i].p != NULL)
  532.       Packet::free(send_buf[i].p);
  533.     send_buf[i].p = NULL;
  534.   }
  535. }
  536.     
  537. void OmniMcast_Entry::reset()
  538. {
  539.   clear_agentlist(source);
  540.   clear_agentlist(sink);
  541.   source = NULL;
  542.   sink = NULL;
  543. }
  544. void OmniMcast_Entry::clear_agentlist(Agent_List *list)
  545. {
  546.   Agent_List *cur=list;
  547.   Agent_List *temp = NULL;
  548.   while (cur != NULL) {
  549.     temp = AGENT_NEXT(cur);
  550.     delete cur;
  551.     cur = temp;
  552.   }
  553. }