diff_prob.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * diff_prob.cc
00004  * Copyright (C) 2000 by the University of Southern California
00005  * $Id: diff_prob.cc,v 1.10 2005/08/25 18:58:03 johnh Exp $
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00019  *
00020  *
00021  * The copyright of this module includes the following
00022  * linking-with-specific-other-licenses addition:
00023  *
00024  * In addition, as a special exception, the copyright holders of
00025  * this module give you permission to combine (via static or
00026  * dynamic linking) this module with free software programs or
00027  * libraries that are released under the GNU LGPL and with code
00028  * included in the standard release of ns-2 under the Apache 2.0
00029  * license or under otherwise-compatible licenses with advertising
00030  * requirements (or modified versions of such code, with unchanged
00031  * license).  You may copy and distribute such a system following the
00032  * terms of the GNU GPL for this module and the licenses of the
00033  * other code concerned, provided that you include the source code of
00034  * that other code when and as the GNU GPL requires distribution of
00035  * source code.
00036  *
00037  * Note that people who make modified versions of this module
00038  * are not obligated to grant this special exception for their
00039  * modified versions; it is their choice whether to do so.  The GNU
00040  * General Public License gives permission to release a modified
00041  * version without this exception; this exception also makes it
00042  * possible to release a modified version which carries forward this
00043  * exception.
00044  *
00045  */
00046 
00047 /****************************************************************/
00048 /* diff_prob.cc : Chalermek Intanagonwiwat (USC/ISI)  05/18/99  */
00049 /****************************************************************/
00050 
00051 // Important Note: Work still in progress !
00052 
00053 #include <assert.h>
00054 #include <math.h>
00055 #include <stdio.h>
00056 #include <signal.h>
00057 #include <float.h>
00058 
00059 #include <tcl.h>
00060 #include <stdlib.h>
00061 
00062 #include "diff_header.h"
00063 #include "agent.h"
00064 #include "tclcl.h"
00065 #include "ip.h"
00066 #include "config.h"
00067 #include "packet.h"
00068 #include "trace.h"
00069 #include "random.h"
00070 #include "classifier.h"
00071 #include "node.h"
00072 #include "diffusion.h"
00073 #include "iflist.h"
00074 #include "hash_table.h"
00075 #include "arp.h"
00076 #include "mac.h"
00077 #include "ll.h"
00078 #include "dsr/path.h"
00079 #include "god.h"
00080 #include "routing_table.h"
00081 #include "diff_prob.h"
00082 
00083 
00084 static class DiffusionProbClass : public TclClass {
00085 public:
00086   DiffusionProbClass() : TclClass("Agent/Diffusion/ProbGradient") {}
00087   TclObject* create(int , const char*const* ) {
00088     return(new DiffusionProb());
00089   }
00090 } class_diffusion_probability;
00091 
00092 
00093 
00094 void InterestTimer::expire(Event *)
00095 {
00096   a_->InterestPropagate(pkt_, hashPtr_);
00097 }
00098 
00099 
00100 void EnergyTimer::expire(Event *)
00101 {
00102   if (node_->energy_model()->energy() < threshold_) {    
00103     if (a_->NEG_REINF_ == true) {
00104       a_->SendNegReinf();
00105     }
00106     threshold_ = threshold_/2;
00107     a_->is_low_power = true;
00108   }
00109 
00110   if (threshold_ >= init_eng_/8) 
00111     resched(ENERGY_CHECK); 
00112 }
00113 
00114 
00115 DiffusionProb::DiffusionProb() : DiffusionAgent()
00116 {
00117   is_low_power = false;
00118   num_neg_bcast_send = 0;
00119   num_neg_bcast_rcv = 0;
00120 }
00121 
00122 
00123 void DiffusionProb::recv(Packet* packet, Handler*)
00124 {
00125   hdr_cdiff* dfh = HDR_CDIFF(packet);
00126 
00127   // Packet Hash Table is used to keep info about experienced pkts.
00128 
00129   Pkt_Hash_Entry *hashPtr= PktTable.GetHash(dfh->sender_id, dfh->pk_num);
00130 
00131 
00132 #ifdef DEBUG_PROB
00133      printf("DF node %x recv %s (%x, %x, %d)\n",
00134         THIS_NODE, MsgStr[dfh->mess_type], (dfh->sender_id).addr_, 
00135         (dfh->sender_id).port_, dfh->pk_num);
00136 #endif
00137 
00138 
00139      // Received this packet before ?
00140 
00141      if (hashPtr != NULL) {
00142        consider_old(packet);
00143        return;
00144      }
00145 
00146      // Never receive it before ? Put in hash table.
00147 
00148      PktTable.put_in_hash(dfh);
00149 
00150      // Take action for a new pkt.
00151        
00152      consider_new(packet);     
00153 }
00154 
00155 
00156 void DiffusionProb::consider_old(Packet *pkt)
00157 {
00158   hdr_cdiff* dfh = HDR_CDIFF(pkt);
00159   unsigned char msg_type = dfh->mess_type;
00160   unsigned int dtype = dfh->data_type;
00161 
00162   Pkt_Hash_Entry *hashPtr;
00163   From_List  *fromPtr;
00164   nsaddr_t from_nodeID, forward_nodeID;
00165 
00166   switch (msg_type) {
00167     case INTEREST :
00168 
00169       hashPtr = PktTable.GetHash(dfh->sender_id, dfh->pk_num);
00170 
00171       if (hashPtr->is_forwarded == true) {
00172     Packet::free(pkt);
00173     return;
00174       }
00175 
00176       from_nodeID = (dfh->sender_id).addr_;
00177       forward_nodeID = (dfh->forward_agent_id).addr_;
00178 
00179 
00180       hashPtr->num_from++;
00181       fromPtr = new From_List;
00182       AGT_ADDR(fromPtr) = dfh->forward_agent_id;
00183       fromPtr->rank = hashPtr->num_from;
00184 
00185       if (from_nodeID == forward_nodeID)
00186     fromPtr->is_sink = true;
00187 
00188       fromPtr->next = hashPtr->from_agent;
00189       hashPtr->from_agent = fromPtr;
00190 
00191       // Check if this hashPtr has timer, and if lists already exist,
00192       // to decide whether to create or update Out_List and In_List
00193 
00194       if (hashPtr->timer == NULL) {
00195     if (hashPtr->has_list==false) {
00196       CreateIOList(hashPtr, dtype);
00197         } 
00198     else {
00199       UpdateIOList(fromPtr, dtype);
00200     }
00201       }
00202       
00203       Packet::free(pkt);
00204       break;
00205 
00206     default : 
00207       Packet::free(pkt);        
00208       break;
00209   }
00210 }
00211 
00212 
00213 void DiffusionProb::consider_new(Packet *pkt)
00214 {
00215   hdr_cdiff* dfh = HDR_CDIFF(pkt);
00216   unsigned char msg_type = dfh->mess_type;
00217   unsigned int dtype = dfh->data_type;
00218 
00219   Pkt_Hash_Entry *hashPtr;
00220   From_List  *fromPtr;
00221   Agent_List *agentPtr;
00222   Agent_List *cur;
00223   PrvCurPtr  RetVal;
00224   nsaddr_t   from_nodeID, forward_nodeID;
00225 
00226   int i;
00227 
00228   switch (msg_type) {
00229     case INTEREST : 
00230 
00231       hashPtr = PktTable.GetHash(dfh->sender_id, dfh->pk_num);
00232 
00233       // Check if it comes from sink agent of this node
00234       // If so we have to keep it in sink list 
00235 
00236       from_nodeID = (dfh->sender_id).addr_;
00237       forward_nodeID = (dfh->forward_agent_id).addr_;
00238 
00239 
00240       if (THIS_NODE == from_nodeID) {       
00241 
00242     // It's from a sink on this node.
00243     // Is it already in list ?
00244 
00245     RetVal = INTF_FIND(routing_table[dtype].sink, dfh->sender_id);
00246 
00247     if (RetVal.cur == NULL) {            
00248       // No, it's not.
00249       agentPtr = new Agent_List;
00250       AGT_ADDR(agentPtr) = dfh->sender_id;
00251       INTF_INSERT(routing_table[dtype].sink, agentPtr);
00252 
00253       God::instance()->AddSink(dtype, THIS_NODE);
00254     }   
00255 
00256       }
00257       else {                             
00258     
00259     // It's not from a sink on this node.
00260 
00261     fromPtr = new From_List;
00262     hashPtr->from_agent = fromPtr;
00263     hashPtr->num_from = 1;
00264     AGT_ADDR(fromPtr) = dfh->forward_agent_id;
00265     fromPtr->rank = 1;
00266     fromPtr->next = NULL;    
00267 
00268     // Is the forwarder node is a sink node ? 
00269     // This information is useful when we do negative reinforcement.
00270 
00271     if ( from_nodeID == forward_nodeID )
00272       fromPtr->is_sink = true;
00273 
00274       }
00275 
00276 
00277       // Do we have to request data ?
00278 
00279       if (routing_table[dtype].source == NULL) {     
00280 
00281     // No, we don't. Better forward the interest.
00282 
00283     hashPtr->timer = new InterestTimer(this, hashPtr, pkt);
00284     (hashPtr->timer)->sched(INTEREST_DELAY*Random::uniform(1.0));
00285       } 
00286       else {
00287     
00288     // Since this node has sources,it won't propagate the interest.
00289     // We need to create Out_List and In_List in routing table [dtype] now.
00290 
00291     CreateIOList(hashPtr, dtype);
00292         data_request_all(dtype);
00293 
00294     Packet::free(pkt);
00295       }
00296       break;
00297 
00298 
00299     case POS_REINFORCE :
00300 
00301       if ( POS_REINF_ == false ) {
00302     printf("Hey, we are not in pos_reinf mode.\n");
00303     Packet::free(pkt);
00304     exit(-1);
00305       }
00306 
00307       IncGradient(dtype, dfh->forward_agent_id);
00308       CAL_RANGE(routing_table[dtype].active);
00309 
00310       if (routing_table[dtype].source == NULL) {
00311     if (is_low_power == false) {
00312       FwdPosReinf(dtype, pkt);
00313       return;
00314     }
00315       } 
00316 
00317       Packet::free(pkt);
00318       break;
00319 
00320 
00321     case NEG_REINFORCE :  
00322 
00323       if (NEG_REINF_ == false) {
00324     printf("Hey, we are not in neg_reinf mode.\n");
00325     Packet::free(pkt);
00326     exit(-1);
00327       }
00328 
00329       // Negative Reinforcement won't be forwarded.
00330 
00331       num_neg_bcast_rcv++;
00332 
00333       for (i=0; i<MAX_DATA_TYPE; i++) {
00334     RetVal = INTF_FIND(routing_table[i].active, dfh->sender_id);
00335     if (RetVal.cur == NULL ) {
00336       continue;
00337     }
00338 
00339     // If it is not a sink, we decrease the gradient.
00340 
00341     if ( IS_SINK(RetVal.cur) == false) {
00342       DecGradient(i, dfh->sender_id);
00343       CAL_RANGE(routing_table[i].active);
00344     }
00345       }
00346 
00347       Packet::free(pkt);
00348       break;
00349 
00350 
00351     case DATA_READY :
00352 
00353       // put source_agent in source list of routing table
00354 
00355       agentPtr = new Agent_List;
00356       AGT_ADDR(agentPtr) = dfh->sender_id;
00357       agentPtr->next = routing_table[dtype].source;
00358       routing_table[dtype].source = agentPtr;
00359 
00360       if (routing_table[dtype].active != NULL ||
00361       routing_table[dtype].sink != NULL) {
00362     SEND_MESSAGE(dtype, dfh->sender_id, DATA_REQUEST);
00363       }
00364 
00365       Packet::free(pkt);
00366       break;
00367 
00368 
00369     case DATA :
00370 
00371       DataForSink(pkt);
00372 
00373       routing_table[dtype].IncRecvCnt(dfh->forward_agent_id);
00374       ForwardData(pkt);
00375 
00376       if (routing_table[dtype].counter >= MAX_REINFORCE_COUNTER) {
00377     if (is_low_power == false) {
00378       if (POS_REINF_ == true)
00379         GenPosReinf(dtype);
00380       return;
00381     }
00382     if (routing_table[dtype].sink != NULL) {
00383       if (POS_REINF_ == true)
00384         GenPosReinf(dtype);
00385       return;
00386     }
00387       }
00388       break;
00389 
00390 
00391     case INHIBIT :
00392 
00393       if (routing_table[dtype].active == NULL) {
00394         Packet::free(pkt);
00395         return;
00396       }
00397 
00398       RetVal=INTF_FIND(routing_table[dtype].active, dfh->sender_id);
00399       if (RetVal.cur == NULL){
00400     Packet::free(pkt);
00401     return;
00402       }
00403 
00404       INTF_REMOVE(RetVal.prv, RetVal.cur);
00405       INTF_INSERT(routing_table[dtype].inactive, RetVal.cur);
00406       routing_table[dtype].num_active --;
00407       NORMALIZE(routing_table[dtype].active);
00408       CAL_RANGE(routing_table[dtype].active);
00409 
00410       if (routing_table[dtype].num_active < 1) {
00411 
00412     // *** You need to stop the source if you have one. *****
00413 
00414     if (routing_table[dtype].source != NULL ) {
00415       for (cur=routing_table[dtype].source; cur != NULL; 
00416            cur=AGENT_NEXT(cur)) {
00417         SEND_MESSAGE(dtype, AGT_ADDR(cur), DATA_STOP);
00418       }
00419       Packet::free(pkt);
00420       return;
00421     }
00422 
00423     // If not, send inhibit signal upstream
00424 
00425     SendInhibit(dtype);
00426       }
00427       
00428       Packet::free(pkt);
00429       return;
00430 
00431 
00432     case TX_FAILED :
00433 
00434       if (BACKTRACK_ == false) {
00435     printf("We are not in backtracking mode.\n");
00436     Packet::free(pkt);
00437     exit(-1);
00438       }
00439 
00440       if (routing_table[dtype].active == NULL) {
00441         ForwardTxFailed(pkt);
00442         return;
00443       }
00444 
00445       //      RetVal=INTF_FIND(routing_table[dtype].active, dfh->sender_id);
00446 
00447       RetVal=INTF_FIND(routing_table[dtype].active, dfh->forward_agent_id);
00448 
00449       if (RetVal.cur != NULL){
00450     INTF_REMOVE(RetVal.prv, RetVal.cur);
00451     INTF_INSERT(routing_table[dtype].inactive, RetVal.cur);
00452     routing_table[dtype].num_active --;
00453     NORMALIZE(routing_table[dtype].active);
00454     CAL_RANGE(routing_table[dtype].active);
00455       }
00456 
00457       if (routing_table[dtype].num_active < 1) {
00458     ForwardTxFailed(pkt);
00459     return;
00460       }
00461       
00462       ReTxData(pkt);
00463 
00464       Packet::free(pkt);
00465       return;
00466 
00467 
00468     default : 
00469       
00470       Packet::free(pkt);        
00471       break;
00472   }
00473 }
00474 
00475 
00476 void DiffusionProb::InterestPropagate(Packet *pkt, 
00477                            Pkt_Hash_Entry *hashPtr)
00478 {
00479   hdr_cdiff *dfh = HDR_CDIFF(pkt);
00480   unsigned int dtype=dfh->data_type;
00481 
00482   CreateIOList(hashPtr, dtype);
00483 
00484   if ( routing_table[dtype].source != NULL ) { 
00485     data_request_all(dtype);
00486     Packet::free(pkt);
00487     return;
00488   }
00489 
00490   MACprepare(pkt, MAC_BROADCAST, NS_AF_ILINK, 0);
00491   MACsend(pkt, 0);
00492   overhead++;
00493   hashPtr->is_forwarded = true;
00494 }
00495 
00496 
00497 void DiffusionProb::ForwardData(Packet *pkt)
00498 {
00499   hdr_cdiff     *dfh  = HDR_CDIFF(pkt);
00500   unsigned int dtype =dfh->data_type;
00501   Out_List     *cur_out;
00502   Packet       *cur_pkt;
00503   hdr_cdiff     *cur_dfh;
00504   hdr_ip       *cur_iph;
00505 
00506   cur_out = WHERE_TO_GO(routing_table[dtype].active);
00507 
00508   if (cur_out !=NULL) {
00509 
00510     // Got somewhere to go.
00511 
00512       cur_pkt = pkt;
00513       cur_iph = HDR_IP(cur_pkt);
00514 
00515       cur_iph->dst_ = AGT_ADDR(cur_out);
00516 
00517       cur_dfh = HDR_CDIFF(cur_pkt);
00518       cur_dfh->forward_agent_id = here_;
00519       cur_dfh->num_next = 1;
00520       cur_dfh->next_nodes[0] = NODE_ADDR(cur_out);
00521 
00522       cur_out->num_data_send++;
00523 
00524 #ifdef DEBUG_PROB
00525       printf("DF node %x will send data (%x, %x, %d) to %x\n",
00526            THIS_NODE, (cur_dfh->sender_id).addr_,
00527            (cur_dfh->sender_id).port_, cur_dfh->pk_num,
00528            AGT_ADDR(cur_out));
00529 #endif
00530 
00531       MACprepare(cur_pkt, NODE_ADDR(cur_out), NS_AF_INET, 1);
00532       MACsend(cur_pkt, 0);
00533 
00534       return;
00535   }
00536 
00537   if (routing_table[dtype].sink != NULL) {
00538 
00539     // No where to go but have sinks.
00540 
00541     Packet::free(pkt);
00542     return;
00543   }
00544 
00545   // No where to go and no sink.    
00546   // Check if we have sources on this node.
00547   // If so, we stop the sources. Otherwise, we generate the transmission
00548   // failure packet. 
00549 
00550   Agent_List *cur;
00551 
00552   if (routing_table[dtype].source != NULL ) {
00553     for (cur=routing_table[dtype].source; cur != NULL; cur=AGENT_NEXT(cur)) {
00554 
00555       // DATA_STOP never go out of the node, so don't care if wireless.
00556 
00557       SEND_MESSAGE(dtype, AGT_ADDR(cur), DATA_STOP);
00558     }
00559     Packet::free(pkt);
00560     return;
00561   }
00562 
00563   // No source, generate the transmission failure packet.
00564 
00565   if (BACKTRACK_ == false) {
00566     Packet::free(pkt);
00567     return;
00568   }
00569 
00570   // YES, we are in backtracking mode so send TX_FAILED to the forwarder.
00571 
00572   cur_pkt = prepare_message(dtype, dfh->forward_agent_id, TX_FAILED);
00573   cur_dfh = HDR_CDIFF(cur_pkt);
00574   cur_dfh->info.sender = dfh->sender_id;
00575   cur_dfh->info.seq = dfh->pk_num;
00576 
00577   hdr_cmn *cmh = HDR_CMN(pkt);
00578   cur_dfh->info.size = cmh->size_;
00579 
00580   MACprepare(cur_pkt, (dfh->forward_agent_id).addr_, NS_AF_INET, 0);
00581   MACsend(cur_pkt, 0);
00582 
00583   Packet::free(pkt);
00584 }
00585 
00586 
00587 void DiffusionProb::ForwardTxFailed(Packet *pkt)
00588 {
00589   hdr_cdiff *dfh = HDR_CDIFF(pkt);
00590   hdr_ip   *iph = HDR_IP(pkt);
00591 
00592   dfh->forward_agent_id = here_;
00593 
00594   Pkt_Hash_Entry *hashPtr=PktTable.GetHash(dfh->info.sender, dfh->info.seq);
00595 
00596   if (hashPtr == NULL) {
00597     Packet::free(pkt);
00598     return;
00599   }
00600 
00601   iph->dst_ = hashPtr->forwarder_id;
00602   dfh->num_next = 1;
00603   dfh->next_nodes[0] = (hashPtr->forwarder_id).addr_;
00604 
00605   MACprepare(pkt, (hashPtr->forwarder_id).addr_, NS_AF_INET, 0);
00606   MACsend(pkt, 0);
00607 
00608   overhead++;
00609 }
00610 
00611 
00612 void DiffusionProb::ReTxData(Packet *pkt)
00613 {
00614   hdr_cdiff *dfh = HDR_CDIFF(pkt);  
00615   Pkt_Hash_Entry *hashPtr=PktTable.GetHash(dfh->info.sender, dfh->info.seq);
00616 
00617   // Make sure it has data on its cache.
00618 
00619   if (hashPtr == NULL) {
00620     printf("No hash for (%x, %x, %d)\n", (dfh->info.sender).addr_, 
00621        (dfh->info.sender).port_, dfh->info.seq);
00622     return;
00623   }
00624 
00625   int dtype = dfh->data_type;
00626   Out_List *to_out = WHERE_TO_GO(routing_table[dtype].active);
00627 
00628   if (to_out == NULL) return;
00629 
00630   Packet *rtxPkt = prepare_message(dtype, AGT_ADDR(to_out), DATA);
00631   hdr_cdiff *rtx_dfh = HDR_CDIFF(rtxPkt);
00632   hdr_cmn  *rtx_cmh = HDR_CMN(rtxPkt);
00633 
00634   rtx_dfh->sender_id = dfh->info.sender;
00635   rtx_dfh->pk_num = dfh->info.seq;
00636   rtx_cmh->size_ = dfh->info.size;
00637   
00638   MACprepare(rtxPkt, NODE_ADDR(to_out), NS_AF_INET, 1);
00639   MACsend(rtxPkt, 0);
00640 
00641   printf("Retransmit (%d,%d,%d)\n",(rtx_dfh->sender_id).addr_, 
00642      (rtx_dfh->sender_id).port_, rtx_dfh->pk_num);
00643 }
00644 
00645 
00646 void DiffusionProb::data_request_all(unsigned int dtype)
00647 {
00648   Agent_List *cur_agent;
00649 
00650   for (cur_agent=routing_table[dtype].source; cur_agent != NULL; 
00651        cur_agent = AGENT_NEXT(cur_agent) ) {
00652     SEND_MESSAGE(dtype, AGT_ADDR(cur_agent), DATA_REQUEST);
00653   }
00654 }
00655 
00656 
00657 void DiffusionProb::CreateIOList(Pkt_Hash_Entry *hashPtr, 
00658                       unsigned int dtype)
00659 {
00660   From_List *fromPtr;
00661 
00662   // Better clear out all existing IO lists first.
00663 
00664   INTF_FREEALL(routing_table[dtype].active);
00665   INTF_FREEALL(routing_table[dtype].inactive);
00666   INTF_FREEALL(routing_table[dtype].iif);
00667   INTF_FREEALL(routing_table[dtype].down_iif);
00668   routing_table[dtype].num_active=0;
00669   routing_table[dtype].counter=0;
00670 
00671   for (fromPtr = hashPtr->from_agent; fromPtr != NULL;
00672        fromPtr = FROM_NEXT(fromPtr) ) {
00673     add_outlist(dtype, fromPtr);
00674   }
00675 
00676   hashPtr->has_list = true;
00677 
00678   CalGradient(dtype);
00679   CAL_RANGE(routing_table[dtype].active);
00680 }
00681 
00682 
00683 void DiffusionProb::UpdateIOList(From_List *fromPtr, 
00684                       unsigned int dtype)
00685 {
00686   add_outlist(dtype, fromPtr);
00687   CalGradient(dtype);
00688   CAL_RANGE(routing_table[dtype].active);
00689 }
00690 
00691 
00692 void DiffusionProb::add_outlist(unsigned int dtype, From_List *foundPtr)
00693 {
00694   Out_List *outPtr = new Out_List;
00695 
00696   AGT_ADDR(outPtr) = AGT_ADDR(foundPtr);
00697   outPtr->rank = foundPtr->rank;
00698   outPtr->is_sink = foundPtr->is_sink;
00699 
00700   INTF_INSERT(routing_table[dtype].active, outPtr);
00701   routing_table[dtype].num_active ++;
00702 }
00703 
00704 
00705 void DiffusionProb::Print_IOlist()
00706 {
00707   Out_List *cur_out;
00708   In_List *cur_in;
00709   int     i;
00710 
00711   for (i=0; i<1; i++) {
00712     printf("Node %d neg bcast send %d, neg bcast rcv %d\n",
00713        THIS_NODE, num_neg_bcast_send, num_neg_bcast_rcv);
00714     for (cur_out = routing_table[i].active; cur_out != NULL; 
00715      cur_out = OUT_NEXT(cur_out) ) {
00716       printf("DF node %d has oif %d (%f,%d) send data %d recv neg %d pos %d\n", 
00717            THIS_NODE, NODE_ADDR(cur_out), GRADIENT(cur_out),
00718            routing_table[i].num_active, NUM_DATA_SEND(cur_out), 
00719        NUM_NEG_RECV(cur_out), NUM_POS_RECV(cur_out));
00720     }
00721 
00722     for (cur_in = routing_table[i].iif; cur_in != NULL;
00723      cur_in = IN_NEXT(cur_in) ) {
00724       printf("Diffusion node %d has iif for %d\n", 
00725          THIS_NODE, NODE_ADDR(cur_in));
00726     }
00727 
00728     for (cur_out = routing_table[i].inactive; cur_out != NULL; 
00729      cur_out = OUT_NEXT(cur_out) ) {
00730       printf("Diffusion node %d has down oif %d (%f, %d) send %d\n", 
00731            THIS_NODE, NODE_ADDR(cur_out), cur_out->gradient,
00732            routing_table[i].num_active, cur_out->num_data_send);
00733 
00734     }
00735 
00736     for (cur_in = routing_table[i].down_iif; cur_in != NULL;
00737      cur_in = IN_NEXT(cur_in) ) {
00738       printf("Diffusion node %d has down_iif for %d (recv %d)\n", THIS_NODE, 
00739          NODE_ADDR(cur_in), cur_in->total_received);
00740     }
00741 
00742   }
00743   
00744 }
00745 
00746 
00747 void DiffusionProb::CalGradient(unsigned int dtype)
00748 {
00749   Out_List *cur_out;
00750   
00751   for (cur_out = routing_table[dtype].active; cur_out != NULL;
00752        cur_out = OUT_NEXT(cur_out) ) {
00753     cur_out->gradient = pow(2, routing_table[dtype].num_active - 
00754                 cur_out->rank) / 
00755                        ( pow(2, routing_table[dtype].num_active) - 1);
00756   }
00757 }
00758 
00759 
00760 
00761 void DiffusionProb::IncGradient(unsigned int dtype, ns_addr_t addr)
00762 {
00763   Out_List *cur_out;
00764   PrvCurPtr RetVal;
00765 
00766   RetVal=INTF_FIND(routing_table[dtype].active, addr);
00767 
00768   if (RetVal.cur != NULL) {
00769     cur_out = (Out_List *)(RetVal.cur);
00770     GRADIENT(cur_out) = GRADIENT(cur_out) + 0.99;
00771     NORMALIZE(routing_table[dtype].active);
00772   }
00773 
00774 }
00775 
00776 
00777 void DiffusionProb::DecGradient(unsigned int dtype, ns_addr_t addr)
00778 {
00779   Out_List *cur_out;
00780   PrvCurPtr RetVal;
00781 
00782   RetVal=INTF_FIND(routing_table[dtype].active, addr);
00783 
00784   if (RetVal.cur != NULL) {
00785 
00786     for (cur_out = routing_table[dtype].active; cur_out != NULL;
00787      cur_out = OUT_NEXT(cur_out) ) 
00788       GRADIENT(cur_out) = GRADIENT(cur_out) + 1.0;
00789 
00790     cur_out = (Out_List *)(RetVal.cur);
00791     GRADIENT(cur_out) = GRADIENT(cur_out) - 1.99;
00792     if (GRADIENT(cur_out)< 0.0) {
00793        GRADIENT(cur_out) = 0.0;
00794     }
00795     NORMALIZE(routing_table[dtype].active);
00796   }
00797 }
00798 
00799 
00800 
00801 void DiffusionProb::GenPosReinf(unsigned int dtype)
00802 {
00803   In_List *cur_in, *max_in;
00804   Packet *pkt;
00805 
00806   max_in = FIND_MAX_IN(routing_table[dtype].iif);
00807 
00808   if (max_in != NULL) {
00809    if ( (max_in->total_received - max_in->prev_received) < 
00810          routing_table[dtype].counter) {
00811 
00812       pkt=prepare_message(dtype, AGT_ADDR(max_in), POS_REINFORCE);
00813 
00814       MACprepare(pkt, NODE_ADDR(max_in), NS_AF_INET, 0);
00815       MACsend(pkt, 0);
00816 
00817       overhead++;
00818 
00819     }
00820   }
00821 
00822   routing_table[dtype].counter = 0;
00823   for (cur_in = routing_table[dtype].iif; cur_in != NULL;
00824        cur_in = IN_NEXT(cur_in) ) {
00825     cur_in->prev_received = cur_in->total_received;
00826   }
00827 
00828 }
00829 
00830 
00831 void DiffusionProb::FwdPosReinf(unsigned int dtype, Packet *pkt)
00832 {
00833   In_List  *cur_in, *max_in=NULL;
00834   hdr_ip   *iph = HDR_IP(pkt);
00835   hdr_cdiff *dfh = HDR_CDIFF(pkt);
00836 
00837   max_in = FIND_MAX_IN(routing_table[dtype].iif);
00838   if (max_in != NULL) {
00839 
00840     iph->dst_ = AGT_ADDR(max_in);
00841 
00842     dfh->num_next = 1;
00843     dfh->next_nodes[0] = NODE_ADDR(max_in);
00844     dfh->forward_agent_id = here_;
00845 
00846     MACprepare(pkt, NODE_ADDR(max_in), NS_AF_INET, 0);
00847     MACsend(pkt, 0);
00848 
00849     overhead++;
00850   }
00851   else {
00852     Packet::free(pkt);
00853   }
00854 
00855   routing_table[dtype].counter = 0;
00856   for (cur_in = routing_table[dtype].iif; cur_in != NULL;
00857        cur_in = IN_NEXT(cur_in) ) {
00858     cur_in->prev_received = cur_in->total_received;
00859   }
00860 }
00861 
00862 
00863 void DiffusionProb::Start()
00864 {
00865   DiffusionAgent::Start();
00866 
00867   energy_timer = new EnergyTimer(this, node);
00868   energy_timer->resched(ENERGY_CHECK + ENERGY_CHECK * Random::uniform(1.0));
00869 }
00870 
00871 
00872 void DiffusionProb::InterfaceDown(int dtype, ns_addr_t DownDiff)
00873 {
00874   PrvCurPtr RetVal;
00875 
00876   RetVal = INTF_FIND(routing_table[dtype].iif, DownDiff);
00877 
00878   if (RetVal.cur != NULL) {
00879     INTF_REMOVE(RetVal.prv, RetVal.cur);
00880     INTF_INSERT(routing_table[dtype].down_iif, RetVal.cur);
00881     return;
00882   }
00883 
00884   RetVal = INTF_FIND(routing_table[dtype].active, DownDiff);
00885   if (RetVal.cur == NULL)
00886     return;
00887 
00888   INTF_REMOVE(RetVal.prv, RetVal.cur);
00889   INTF_INSERT(routing_table[dtype].inactive, RetVal.cur);
00890   routing_table[dtype].num_active --;
00891   NORMALIZE(routing_table[dtype].active);
00892   CAL_RANGE(routing_table[dtype].active);
00893 
00894   if (routing_table[dtype].num_active < 1) {
00895 
00896     // ** If we have a source, stop the source.
00897     // If not, send inhibit signal upstream. **
00898 
00899     Agent_List *cur;
00900 
00901     if (routing_table[dtype].source != NULL ) {
00902       for (cur=routing_table[dtype].source; cur != NULL; cur=AGENT_NEXT(cur)) {
00903          SEND_MESSAGE(dtype, AGT_ADDR(cur), DATA_STOP);
00904       }
00905     }
00906     else {
00907       SendInhibit(dtype);
00908     }
00909   }
00910 }
00911 
00912 
00913 void DiffusionProb::SendInhibit(int dtype)
00914 {
00915   // Wireless. Just use one MAC broadcast.
00916 
00917     ns_addr_t bcast_addr;
00918     bcast_addr.addr_ = MAC_BROADCAST;
00919     bcast_addr.port_ = ROUTING_PORT;
00920 
00921     Packet *pkt = prepare_message(dtype, bcast_addr, INHIBIT);
00922     MACprepare(pkt, MAC_BROADCAST, NS_AF_ILINK, 0);
00923     MACsend(pkt, 0);
00924     overhead++;
00925     return;
00926 }
00927 
00928 
00929 // For negative reinforcement, we don't care the data type.
00930 // Any neighbor upstream of any data type should be informed.
00931 
00932 void DiffusionProb::SendNegReinf()
00933 {
00934     ns_addr_t bcast_addr;
00935     bcast_addr.addr_ = MAC_BROADCAST;
00936     bcast_addr.port_ = ROUTING_PORT;
00937 
00938     Packet *pkt = prepare_message(0, bcast_addr, NEG_REINFORCE);
00939     MACprepare(pkt, MAC_BROADCAST, NS_AF_ILINK, 0);
00940     MACsend(pkt, 0);
00941     overhead++;
00942     return;
00943 }
00944 

Generated on Tue Mar 6 16:47:44 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6