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

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * diff_prob.cc
  3.  * Copyright (C) 2000 by the University of Southern California
  4.  * $Id: diff_prob.cc,v 1.10 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. /* diff_prob.cc : Chalermek Intanagonwiwat (USC/ISI)  05/18/99  */
  47. /****************************************************************/
  48. // Important Note: Work still in progress !
  49. #include <assert.h>
  50. #include <math.h>
  51. #include <stdio.h>
  52. #include <signal.h>
  53. #include <float.h>
  54. #include <tcl.h>
  55. #include <stdlib.h>
  56. #include "diff_header.h"
  57. #include "agent.h"
  58. #include "tclcl.h"
  59. #include "ip.h"
  60. #include "config.h"
  61. #include "packet.h"
  62. #include "trace.h"
  63. #include "random.h"
  64. #include "classifier.h"
  65. #include "node.h"
  66. #include "diffusion.h"
  67. #include "iflist.h"
  68. #include "hash_table.h"
  69. #include "arp.h"
  70. #include "mac.h"
  71. #include "ll.h"
  72. #include "dsr/path.h"
  73. #include "god.h"
  74. #include "routing_table.h"
  75. #include "diff_prob.h"
  76. static class DiffusionProbClass : public TclClass {
  77. public:
  78.   DiffusionProbClass() : TclClass("Agent/Diffusion/ProbGradient") {}
  79.   TclObject* create(int , const char*const* ) {
  80.     return(new DiffusionProb());
  81.   }
  82. } class_diffusion_probability;
  83. void InterestTimer::expire(Event *)
  84. {
  85.   a_->InterestPropagate(pkt_, hashPtr_);
  86. }
  87. void EnergyTimer::expire(Event *)
  88. {
  89.   if (node_->energy_model()->energy() < threshold_) {    
  90.     if (a_->NEG_REINF_ == true) {
  91.       a_->SendNegReinf();
  92.     }
  93.     threshold_ = threshold_/2;
  94.     a_->is_low_power = true;
  95.   }
  96.   if (threshold_ >= init_eng_/8) 
  97.     resched(ENERGY_CHECK); 
  98. }
  99. DiffusionProb::DiffusionProb() : DiffusionAgent()
  100. {
  101.   is_low_power = false;
  102.   num_neg_bcast_send = 0;
  103.   num_neg_bcast_rcv = 0;
  104. }
  105. void DiffusionProb::recv(Packet* packet, Handler*)
  106. {
  107.   hdr_cdiff* dfh = HDR_CDIFF(packet);
  108.   // Packet Hash Table is used to keep info about experienced pkts.
  109.   Pkt_Hash_Entry *hashPtr= PktTable.GetHash(dfh->sender_id, dfh->pk_num);
  110. #ifdef DEBUG_PROB
  111.      printf("DF node %x recv %s (%x, %x, %d)n",
  112.     THIS_NODE, MsgStr[dfh->mess_type], (dfh->sender_id).addr_, 
  113.     (dfh->sender_id).port_, dfh->pk_num);
  114. #endif
  115.      // Received this packet before ?
  116.      if (hashPtr != NULL) {
  117.        consider_old(packet);
  118.        return;
  119.      }
  120.      // Never receive it before ? Put in hash table.
  121.      PktTable.put_in_hash(dfh);
  122.      // Take action for a new pkt.
  123.        
  124.      consider_new(packet);     
  125. }
  126. void DiffusionProb::consider_old(Packet *pkt)
  127. {
  128.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  129.   unsigned char msg_type = dfh->mess_type;
  130.   unsigned int dtype = dfh->data_type;
  131.   Pkt_Hash_Entry *hashPtr;
  132.   From_List  *fromPtr;
  133.   nsaddr_t from_nodeID, forward_nodeID;
  134.   switch (msg_type) {
  135.     case INTEREST :
  136.       hashPtr = PktTable.GetHash(dfh->sender_id, dfh->pk_num);
  137.       if (hashPtr->is_forwarded == true) {
  138. Packet::free(pkt);
  139. return;
  140.       }
  141.       from_nodeID = (dfh->sender_id).addr_;
  142.       forward_nodeID = (dfh->forward_agent_id).addr_;
  143.       hashPtr->num_from++;
  144.       fromPtr = new From_List;
  145.       AGT_ADDR(fromPtr) = dfh->forward_agent_id;
  146.       fromPtr->rank = hashPtr->num_from;
  147.       if (from_nodeID == forward_nodeID)
  148. fromPtr->is_sink = true;
  149.       fromPtr->next = hashPtr->from_agent;
  150.       hashPtr->from_agent = fromPtr;
  151.       // Check if this hashPtr has timer, and if lists already exist,
  152.       // to decide whether to create or update Out_List and In_List
  153.       if (hashPtr->timer == NULL) {
  154. if (hashPtr->has_list==false) {
  155.   CreateIOList(hashPtr, dtype);
  156.         } 
  157. else {
  158.   UpdateIOList(fromPtr, dtype);
  159. }
  160.       }
  161.       
  162.       Packet::free(pkt);
  163.       break;
  164.     default : 
  165.       Packet::free(pkt);        
  166.       break;
  167.   }
  168. }
  169. void DiffusionProb::consider_new(Packet *pkt)
  170. {
  171.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  172.   unsigned char msg_type = dfh->mess_type;
  173.   unsigned int dtype = dfh->data_type;
  174.   Pkt_Hash_Entry *hashPtr;
  175.   From_List  *fromPtr;
  176.   Agent_List *agentPtr;
  177.   Agent_List *cur;
  178.   PrvCurPtr  RetVal;
  179.   nsaddr_t   from_nodeID, forward_nodeID;
  180.   int i;
  181.   switch (msg_type) {
  182.     case INTEREST : 
  183.       hashPtr = PktTable.GetHash(dfh->sender_id, dfh->pk_num);
  184.       // Check if it comes from sink agent of this node
  185.       // If so we have to keep it in sink list 
  186.       from_nodeID = (dfh->sender_id).addr_;
  187.       forward_nodeID = (dfh->forward_agent_id).addr_;
  188.       if (THIS_NODE == from_nodeID) {       
  189. // It's from a sink on this node.
  190. // Is it already in list ?
  191. RetVal = INTF_FIND(routing_table[dtype].sink, dfh->sender_id);
  192. if (RetVal.cur == NULL) {            
  193.   // No, it's not.
  194.   agentPtr = new Agent_List;
  195.   AGT_ADDR(agentPtr) = dfh->sender_id;
  196.   INTF_INSERT(routing_table[dtype].sink, agentPtr);
  197.   God::instance()->AddSink(dtype, THIS_NODE);
  198. }
  199.       }
  200.       else {                             
  201. // It's not from a sink on this node.
  202. fromPtr = new From_List;
  203. hashPtr->from_agent = fromPtr;
  204. hashPtr->num_from = 1;
  205. AGT_ADDR(fromPtr) = dfh->forward_agent_id;
  206. fromPtr->rank = 1;
  207. fromPtr->next = NULL;    
  208. // Is the forwarder node is a sink node ? 
  209. // This information is useful when we do negative reinforcement.
  210. if ( from_nodeID == forward_nodeID )
  211.   fromPtr->is_sink = true;
  212.       }
  213.       // Do we have to request data ?
  214.       if (routing_table[dtype].source == NULL) {     
  215. // No, we don't. Better forward the interest.
  216. hashPtr->timer = new InterestTimer(this, hashPtr, pkt);
  217. (hashPtr->timer)->sched(INTEREST_DELAY*Random::uniform(1.0));
  218.       } 
  219.       else {
  220. // Since this node has sources,it won't propagate the interest.
  221. // We need to create Out_List and In_List in routing table [dtype] now.
  222. CreateIOList(hashPtr, dtype);
  223.         data_request_all(dtype);
  224. Packet::free(pkt);
  225.       }
  226.       break;
  227.     case POS_REINFORCE :
  228.       if ( POS_REINF_ == false ) {
  229. printf("Hey, we are not in pos_reinf mode.n");
  230. Packet::free(pkt);
  231. exit(-1);
  232.       }
  233.       IncGradient(dtype, dfh->forward_agent_id);
  234.       CAL_RANGE(routing_table[dtype].active);
  235.       if (routing_table[dtype].source == NULL) {
  236. if (is_low_power == false) {
  237.   FwdPosReinf(dtype, pkt);
  238.   return;
  239. }
  240.       } 
  241.       Packet::free(pkt);
  242.       break;
  243.     case NEG_REINFORCE :  
  244.       if (NEG_REINF_ == false) {
  245. printf("Hey, we are not in neg_reinf mode.n");
  246. Packet::free(pkt);
  247. exit(-1);
  248.       }
  249.       // Negative Reinforcement won't be forwarded.
  250.       num_neg_bcast_rcv++;
  251.       for (i=0; i<MAX_DATA_TYPE; i++) {
  252. RetVal = INTF_FIND(routing_table[i].active, dfh->sender_id);
  253. if (RetVal.cur == NULL ) {
  254.   continue;
  255. }
  256. // If it is not a sink, we decrease the gradient.
  257. if ( IS_SINK(RetVal.cur) == false) {
  258.   DecGradient(i, dfh->sender_id);
  259.   CAL_RANGE(routing_table[i].active);
  260. }
  261.       }
  262.       Packet::free(pkt);
  263.       break;
  264.     case DATA_READY :
  265.       // put source_agent in source list of routing table
  266.       agentPtr = new Agent_List;
  267.       AGT_ADDR(agentPtr) = dfh->sender_id;
  268.       agentPtr->next = routing_table[dtype].source;
  269.       routing_table[dtype].source = agentPtr;
  270.       if (routing_table[dtype].active != NULL ||
  271.   routing_table[dtype].sink != NULL) {
  272. SEND_MESSAGE(dtype, dfh->sender_id, DATA_REQUEST);
  273.       }
  274.       Packet::free(pkt);
  275.       break;
  276.     case DATA :
  277.       DataForSink(pkt);
  278.       routing_table[dtype].IncRecvCnt(dfh->forward_agent_id);
  279.       ForwardData(pkt);
  280.       if (routing_table[dtype].counter >= MAX_REINFORCE_COUNTER) {
  281. if (is_low_power == false) {
  282.   if (POS_REINF_ == true)
  283.     GenPosReinf(dtype);
  284.   return;
  285. }
  286. if (routing_table[dtype].sink != NULL) {
  287.   if (POS_REINF_ == true)
  288.     GenPosReinf(dtype);
  289.   return;
  290. }
  291.       }
  292.       break;
  293.     case INHIBIT :
  294.       if (routing_table[dtype].active == NULL) {
  295.         Packet::free(pkt);
  296.         return;
  297.       }
  298.       RetVal=INTF_FIND(routing_table[dtype].active, dfh->sender_id);
  299.       if (RetVal.cur == NULL){
  300. Packet::free(pkt);
  301. return;
  302.       }
  303.       INTF_REMOVE(RetVal.prv, RetVal.cur);
  304.       INTF_INSERT(routing_table[dtype].inactive, RetVal.cur);
  305.       routing_table[dtype].num_active --;
  306.       NORMALIZE(routing_table[dtype].active);
  307.       CAL_RANGE(routing_table[dtype].active);
  308.       if (routing_table[dtype].num_active < 1) {
  309. // *** You need to stop the source if you have one. *****
  310. if (routing_table[dtype].source != NULL ) {
  311.   for (cur=routing_table[dtype].source; cur != NULL; 
  312.        cur=AGENT_NEXT(cur)) {
  313.     SEND_MESSAGE(dtype, AGT_ADDR(cur), DATA_STOP);
  314.   }
  315.   Packet::free(pkt);
  316.   return;
  317. }
  318. // If not, send inhibit signal upstream
  319. SendInhibit(dtype);
  320.       }
  321.       
  322.       Packet::free(pkt);
  323.       return;
  324.     case TX_FAILED :
  325.       if (BACKTRACK_ == false) {
  326. printf("We are not in backtracking mode.n");
  327. Packet::free(pkt);
  328. exit(-1);
  329.       }
  330.       if (routing_table[dtype].active == NULL) {
  331.         ForwardTxFailed(pkt);
  332.         return;
  333.       }
  334.       //      RetVal=INTF_FIND(routing_table[dtype].active, dfh->sender_id);
  335.       RetVal=INTF_FIND(routing_table[dtype].active, dfh->forward_agent_id);
  336.       if (RetVal.cur != NULL){
  337. INTF_REMOVE(RetVal.prv, RetVal.cur);
  338. INTF_INSERT(routing_table[dtype].inactive, RetVal.cur);
  339. routing_table[dtype].num_active --;
  340. NORMALIZE(routing_table[dtype].active);
  341. CAL_RANGE(routing_table[dtype].active);
  342.       }
  343.       if (routing_table[dtype].num_active < 1) {
  344. ForwardTxFailed(pkt);
  345. return;
  346.       }
  347.       
  348.       ReTxData(pkt);
  349.       Packet::free(pkt);
  350.       return;
  351.     default : 
  352.       
  353.       Packet::free(pkt);        
  354.       break;
  355.   }
  356. }
  357. void DiffusionProb::InterestPropagate(Packet *pkt, 
  358.        Pkt_Hash_Entry *hashPtr)
  359. {
  360.   hdr_cdiff *dfh = HDR_CDIFF(pkt);
  361.   unsigned int dtype=dfh->data_type;
  362.   CreateIOList(hashPtr, dtype);
  363.   if ( routing_table[dtype].source != NULL ) { 
  364.     data_request_all(dtype);
  365.     Packet::free(pkt);
  366.     return;
  367.   }
  368.   MACprepare(pkt, MAC_BROADCAST, NS_AF_ILINK, 0);
  369.   MACsend(pkt, 0);
  370.   overhead++;
  371.   hashPtr->is_forwarded = true;
  372. }
  373. void DiffusionProb::ForwardData(Packet *pkt)
  374. {
  375.   hdr_cdiff     *dfh  = HDR_CDIFF(pkt);
  376.   unsigned int dtype =dfh->data_type;
  377.   Out_List     *cur_out;
  378.   Packet       *cur_pkt;
  379.   hdr_cdiff     *cur_dfh;
  380.   hdr_ip       *cur_iph;
  381.   cur_out = WHERE_TO_GO(routing_table[dtype].active);
  382.   if (cur_out !=NULL) {
  383.     // Got somewhere to go.
  384.       cur_pkt = pkt;
  385.       cur_iph = HDR_IP(cur_pkt);
  386.       cur_iph->dst_ = AGT_ADDR(cur_out);
  387.       cur_dfh = HDR_CDIFF(cur_pkt);
  388.       cur_dfh->forward_agent_id = here_;
  389.       cur_dfh->num_next = 1;
  390.       cur_dfh->next_nodes[0] = NODE_ADDR(cur_out);
  391.       cur_out->num_data_send++;
  392. #ifdef DEBUG_PROB
  393.       printf("DF node %x will send data (%x, %x, %d) to %xn",
  394.        THIS_NODE, (cur_dfh->sender_id).addr_,
  395.        (cur_dfh->sender_id).port_, cur_dfh->pk_num,
  396.        AGT_ADDR(cur_out));
  397. #endif
  398.       MACprepare(cur_pkt, NODE_ADDR(cur_out), NS_AF_INET, 1);
  399.       MACsend(cur_pkt, 0);
  400.       return;
  401.   }
  402.   if (routing_table[dtype].sink != NULL) {
  403.     // No where to go but have sinks.
  404.     Packet::free(pkt);
  405.     return;
  406.   }
  407.   // No where to go and no sink.    
  408.   // Check if we have sources on this node.
  409.   // If so, we stop the sources. Otherwise, we generate the transmission
  410.   // failure packet. 
  411.   Agent_List *cur;
  412.   if (routing_table[dtype].source != NULL ) {
  413.     for (cur=routing_table[dtype].source; cur != NULL; cur=AGENT_NEXT(cur)) {
  414.       // DATA_STOP never go out of the node, so don't care if wireless.
  415.       SEND_MESSAGE(dtype, AGT_ADDR(cur), DATA_STOP);
  416.     }
  417.     Packet::free(pkt);
  418.     return;
  419.   }
  420.   // No source, generate the transmission failure packet.
  421.   if (BACKTRACK_ == false) {
  422.     Packet::free(pkt);
  423.     return;
  424.   }
  425.   // YES, we are in backtracking mode so send TX_FAILED to the forwarder.
  426.   cur_pkt = prepare_message(dtype, dfh->forward_agent_id, TX_FAILED);
  427.   cur_dfh = HDR_CDIFF(cur_pkt);
  428.   cur_dfh->info.sender = dfh->sender_id;
  429.   cur_dfh->info.seq = dfh->pk_num;
  430.   hdr_cmn *cmh = HDR_CMN(pkt);
  431.   cur_dfh->info.size = cmh->size_;
  432.   MACprepare(cur_pkt, (dfh->forward_agent_id).addr_, NS_AF_INET, 0);
  433.   MACsend(cur_pkt, 0);
  434.   Packet::free(pkt);
  435. }
  436. void DiffusionProb::ForwardTxFailed(Packet *pkt)
  437. {
  438.   hdr_cdiff *dfh = HDR_CDIFF(pkt);
  439.   hdr_ip   *iph = HDR_IP(pkt);
  440.   dfh->forward_agent_id = here_;
  441.   Pkt_Hash_Entry *hashPtr=PktTable.GetHash(dfh->info.sender, dfh->info.seq);
  442.   if (hashPtr == NULL) {
  443.     Packet::free(pkt);
  444.     return;
  445.   }
  446.   iph->dst_ = hashPtr->forwarder_id;
  447.   dfh->num_next = 1;
  448.   dfh->next_nodes[0] = (hashPtr->forwarder_id).addr_;
  449.   MACprepare(pkt, (hashPtr->forwarder_id).addr_, NS_AF_INET, 0);
  450.   MACsend(pkt, 0);
  451.   overhead++;
  452. }
  453. void DiffusionProb::ReTxData(Packet *pkt)
  454. {
  455.   hdr_cdiff *dfh = HDR_CDIFF(pkt);  
  456.   Pkt_Hash_Entry *hashPtr=PktTable.GetHash(dfh->info.sender, dfh->info.seq);
  457.   // Make sure it has data on its cache.
  458.   if (hashPtr == NULL) {
  459.     printf("No hash for (%x, %x, %d)n", (dfh->info.sender).addr_, 
  460.    (dfh->info.sender).port_, dfh->info.seq);
  461.     return;
  462.   }
  463.   int dtype = dfh->data_type;
  464.   Out_List *to_out = WHERE_TO_GO(routing_table[dtype].active);
  465.   if (to_out == NULL) return;
  466.   Packet *rtxPkt = prepare_message(dtype, AGT_ADDR(to_out), DATA);
  467.   hdr_cdiff *rtx_dfh = HDR_CDIFF(rtxPkt);
  468.   hdr_cmn  *rtx_cmh = HDR_CMN(rtxPkt);
  469.   rtx_dfh->sender_id = dfh->info.sender;
  470.   rtx_dfh->pk_num = dfh->info.seq;
  471.   rtx_cmh->size_ = dfh->info.size;
  472.   
  473.   MACprepare(rtxPkt, NODE_ADDR(to_out), NS_AF_INET, 1);
  474.   MACsend(rtxPkt, 0);
  475.   printf("Retransmit (%d,%d,%d)n",(rtx_dfh->sender_id).addr_, 
  476.  (rtx_dfh->sender_id).port_, rtx_dfh->pk_num);
  477. }
  478. void DiffusionProb::data_request_all(unsigned int dtype)
  479. {
  480.   Agent_List *cur_agent;
  481.   for (cur_agent=routing_table[dtype].source; cur_agent != NULL; 
  482.        cur_agent = AGENT_NEXT(cur_agent) ) {
  483.     SEND_MESSAGE(dtype, AGT_ADDR(cur_agent), DATA_REQUEST);
  484.   }
  485. }
  486. void DiffusionProb::CreateIOList(Pkt_Hash_Entry *hashPtr, 
  487.   unsigned int dtype)
  488. {
  489.   From_List *fromPtr;
  490.   // Better clear out all existing IO lists first.
  491.   INTF_FREEALL(routing_table[dtype].active);
  492.   INTF_FREEALL(routing_table[dtype].inactive);
  493.   INTF_FREEALL(routing_table[dtype].iif);
  494.   INTF_FREEALL(routing_table[dtype].down_iif);
  495.   routing_table[dtype].num_active=0;
  496.   routing_table[dtype].counter=0;
  497.   for (fromPtr = hashPtr->from_agent; fromPtr != NULL;
  498.        fromPtr = FROM_NEXT(fromPtr) ) {
  499.     add_outlist(dtype, fromPtr);
  500.   }
  501.   hashPtr->has_list = true;
  502.   CalGradient(dtype);
  503.   CAL_RANGE(routing_table[dtype].active);
  504. }
  505. void DiffusionProb::UpdateIOList(From_List *fromPtr, 
  506.   unsigned int dtype)
  507. {
  508.   add_outlist(dtype, fromPtr);
  509.   CalGradient(dtype);
  510.   CAL_RANGE(routing_table[dtype].active);
  511. }
  512. void DiffusionProb::add_outlist(unsigned int dtype, From_List *foundPtr)
  513. {
  514.   Out_List *outPtr = new Out_List;
  515.   AGT_ADDR(outPtr) = AGT_ADDR(foundPtr);
  516.   outPtr->rank = foundPtr->rank;
  517.   outPtr->is_sink = foundPtr->is_sink;
  518.   INTF_INSERT(routing_table[dtype].active, outPtr);
  519.   routing_table[dtype].num_active ++;
  520. }
  521. void DiffusionProb::Print_IOlist()
  522. {
  523.   Out_List *cur_out;
  524.   In_List *cur_in;
  525.   int     i;
  526.   for (i=0; i<1; i++) {
  527.     printf("Node %d neg bcast send %d, neg bcast rcv %dn",
  528.    THIS_NODE, num_neg_bcast_send, num_neg_bcast_rcv);
  529.     for (cur_out = routing_table[i].active; cur_out != NULL; 
  530.  cur_out = OUT_NEXT(cur_out) ) {
  531.       printf("DF node %d has oif %d (%f,%d) send data %d recv neg %d pos %dn", 
  532.            THIS_NODE, NODE_ADDR(cur_out), GRADIENT(cur_out),
  533.            routing_table[i].num_active, NUM_DATA_SEND(cur_out), 
  534.    NUM_NEG_RECV(cur_out), NUM_POS_RECV(cur_out));
  535.     }
  536.     for (cur_in = routing_table[i].iif; cur_in != NULL;
  537.  cur_in = IN_NEXT(cur_in) ) {
  538.       printf("Diffusion node %d has iif for %dn", 
  539.      THIS_NODE, NODE_ADDR(cur_in));
  540.     }
  541.     for (cur_out = routing_table[i].inactive; cur_out != NULL; 
  542.  cur_out = OUT_NEXT(cur_out) ) {
  543.       printf("Diffusion node %d has down oif %d (%f, %d) send %dn", 
  544.            THIS_NODE, NODE_ADDR(cur_out), cur_out->gradient,
  545.            routing_table[i].num_active, cur_out->num_data_send);
  546.     }
  547.     for (cur_in = routing_table[i].down_iif; cur_in != NULL;
  548.  cur_in = IN_NEXT(cur_in) ) {
  549.       printf("Diffusion node %d has down_iif for %d (recv %d)n", THIS_NODE, 
  550.      NODE_ADDR(cur_in), cur_in->total_received);
  551.     }
  552.   }
  553.   
  554. }
  555. void DiffusionProb::CalGradient(unsigned int dtype)
  556. {
  557.   Out_List *cur_out;
  558.   
  559.   for (cur_out = routing_table[dtype].active; cur_out != NULL;
  560.        cur_out = OUT_NEXT(cur_out) ) {
  561.     cur_out->gradient = pow(2, routing_table[dtype].num_active - 
  562.     cur_out->rank) / 
  563.                        ( pow(2, routing_table[dtype].num_active) - 1);
  564.   }
  565. }
  566. void DiffusionProb::IncGradient(unsigned int dtype, ns_addr_t addr)
  567. {
  568.   Out_List *cur_out;
  569.   PrvCurPtr RetVal;
  570.   RetVal=INTF_FIND(routing_table[dtype].active, addr);
  571.   if (RetVal.cur != NULL) {
  572.     cur_out = (Out_List *)(RetVal.cur);
  573.     GRADIENT(cur_out) = GRADIENT(cur_out) + 0.99;
  574.     NORMALIZE(routing_table[dtype].active);
  575.   }
  576. }
  577. void DiffusionProb::DecGradient(unsigned int dtype, ns_addr_t addr)
  578. {
  579.   Out_List *cur_out;
  580.   PrvCurPtr RetVal;
  581.   RetVal=INTF_FIND(routing_table[dtype].active, addr);
  582.   if (RetVal.cur != NULL) {
  583.     for (cur_out = routing_table[dtype].active; cur_out != NULL;
  584.  cur_out = OUT_NEXT(cur_out) ) 
  585.       GRADIENT(cur_out) = GRADIENT(cur_out) + 1.0;
  586.     cur_out = (Out_List *)(RetVal.cur);
  587.     GRADIENT(cur_out) = GRADIENT(cur_out) - 1.99;
  588.     if (GRADIENT(cur_out)< 0.0) {
  589.        GRADIENT(cur_out) = 0.0;
  590.     }
  591.     NORMALIZE(routing_table[dtype].active);
  592.   }
  593. }
  594. void DiffusionProb::GenPosReinf(unsigned int dtype)
  595. {
  596.   In_List *cur_in, *max_in;
  597.   Packet *pkt;
  598.   max_in = FIND_MAX_IN(routing_table[dtype].iif);
  599.   if (max_in != NULL) {
  600.    if ( (max_in->total_received - max_in->prev_received) < 
  601.          routing_table[dtype].counter) {
  602.       pkt=prepare_message(dtype, AGT_ADDR(max_in), POS_REINFORCE);
  603.       MACprepare(pkt, NODE_ADDR(max_in), NS_AF_INET, 0);
  604.       MACsend(pkt, 0);
  605.       overhead++;
  606.     }
  607.   }
  608.   routing_table[dtype].counter = 0;
  609.   for (cur_in = routing_table[dtype].iif; cur_in != NULL;
  610.        cur_in = IN_NEXT(cur_in) ) {
  611.     cur_in->prev_received = cur_in->total_received;
  612.   }
  613. }
  614. void DiffusionProb::FwdPosReinf(unsigned int dtype, Packet *pkt)
  615. {
  616.   In_List  *cur_in, *max_in=NULL;
  617.   hdr_ip   *iph = HDR_IP(pkt);
  618.   hdr_cdiff *dfh = HDR_CDIFF(pkt);
  619.   max_in = FIND_MAX_IN(routing_table[dtype].iif);
  620.   if (max_in != NULL) {
  621.     iph->dst_ = AGT_ADDR(max_in);
  622.     dfh->num_next = 1;
  623.     dfh->next_nodes[0] = NODE_ADDR(max_in);
  624.     dfh->forward_agent_id = here_;
  625.     MACprepare(pkt, NODE_ADDR(max_in), NS_AF_INET, 0);
  626.     MACsend(pkt, 0);
  627.     overhead++;
  628.   }
  629.   else {
  630.     Packet::free(pkt);
  631.   }
  632.   routing_table[dtype].counter = 0;
  633.   for (cur_in = routing_table[dtype].iif; cur_in != NULL;
  634.        cur_in = IN_NEXT(cur_in) ) {
  635.     cur_in->prev_received = cur_in->total_received;
  636.   }
  637. }
  638. void DiffusionProb::Start()
  639. {
  640.   DiffusionAgent::Start();
  641.   energy_timer = new EnergyTimer(this, node);
  642.   energy_timer->resched(ENERGY_CHECK + ENERGY_CHECK * Random::uniform(1.0));
  643. }
  644. void DiffusionProb::InterfaceDown(int dtype, ns_addr_t DownDiff)
  645. {
  646.   PrvCurPtr RetVal;
  647.   RetVal = INTF_FIND(routing_table[dtype].iif, DownDiff);
  648.   if (RetVal.cur != NULL) {
  649.     INTF_REMOVE(RetVal.prv, RetVal.cur);
  650.     INTF_INSERT(routing_table[dtype].down_iif, RetVal.cur);
  651.     return;
  652.   }
  653.   RetVal = INTF_FIND(routing_table[dtype].active, DownDiff);
  654.   if (RetVal.cur == NULL)
  655.     return;
  656.   INTF_REMOVE(RetVal.prv, RetVal.cur);
  657.   INTF_INSERT(routing_table[dtype].inactive, RetVal.cur);
  658.   routing_table[dtype].num_active --;
  659.   NORMALIZE(routing_table[dtype].active);
  660.   CAL_RANGE(routing_table[dtype].active);
  661.   if (routing_table[dtype].num_active < 1) {
  662.     // ** If we have a source, stop the source.
  663.     // If not, send inhibit signal upstream. **
  664.     Agent_List *cur;
  665.     if (routing_table[dtype].source != NULL ) {
  666.       for (cur=routing_table[dtype].source; cur != NULL; cur=AGENT_NEXT(cur)) {
  667.      SEND_MESSAGE(dtype, AGT_ADDR(cur), DATA_STOP);
  668.       }
  669.     }
  670.     else {
  671.       SendInhibit(dtype);
  672.     }
  673.   }
  674. }
  675. void DiffusionProb::SendInhibit(int dtype)
  676. {
  677.   // Wireless. Just use one MAC broadcast.
  678.     ns_addr_t bcast_addr;
  679.     bcast_addr.addr_ = MAC_BROADCAST;
  680.     bcast_addr.port_ = ROUTING_PORT;
  681.     Packet *pkt = prepare_message(dtype, bcast_addr, INHIBIT);
  682.     MACprepare(pkt, MAC_BROADCAST, NS_AF_ILINK, 0);
  683.     MACsend(pkt, 0);
  684.     overhead++;
  685.     return;
  686. }
  687. // For negative reinforcement, we don't care the data type.
  688. // Any neighbor upstream of any data type should be informed.
  689. void DiffusionProb::SendNegReinf()
  690. {
  691.     ns_addr_t bcast_addr;
  692.     bcast_addr.addr_ = MAC_BROADCAST;
  693.     bcast_addr.port_ = ROUTING_PORT;
  694.     Packet *pkt = prepare_message(0, bcast_addr, NEG_REINFORCE);
  695.     MACprepare(pkt, MAC_BROADCAST, NS_AF_ILINK, 0);
  696.     MACsend(pkt, 0);
  697.     overhead++;
  698.     return;
  699. }