flooding.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * flooding.cc
00004  * Copyright (C) 2000 by the University of Southern California
00005  * $Id: flooding.cc,v 1.9 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 /* flooding.cc : Chalermek Intanagonwiwat (USC/ISI)  05/18/99   */
00049 /****************************************************************/
00050 
00051 // Share api with diffusion and omnicient multicast
00052 // Using diffusion packet header 
00053 
00054 #include <assert.h>
00055 #include <math.h>
00056 #include <stdio.h>
00057 #include <signal.h>
00058 #include <float.h>
00059 #include <stdlib.h>
00060 
00061 #include <tcl.h>
00062 
00063 
00064 #include "diff_header.h"
00065 #include "agent.h"
00066 #include "tclcl.h"
00067 #include "ip.h"
00068 #include "config.h"
00069 #include "packet.h"
00070 #include "trace.h"
00071 #include "random.h"
00072 #include "classifier.h"
00073 #include "node.h"
00074 #include "flooding.h"
00075 #include "iflist.h"
00076 #include "hash_table.h"
00077 #include "arp.h"
00078 #include "mac.h"
00079 #include "ll.h"
00080 #include "dsr/path.h"
00081 #include "god.h"
00082 
00083 static class FloodingClass : public TclClass {
00084 public:
00085   FloodingClass() : TclClass("Agent/Flooding") {}
00086   TclObject* create(int argc, const char*const* argv) {
00087     return(new FloodingAgent());
00088   }
00089 } class_flooding;
00090 
00091 
00092 
00093 FloodingAgent::FloodingAgent() : Agent(PT_DIFF)
00094 {
00095   // Initialize variables.
00096 
00097   pk_count = 0;
00098   target_ = 0;
00099   node = NULL;
00100   tracetarget = NULL;
00101 }
00102 
00103 
00104 void FloodingAgent::recv(Packet* packet, Handler*)
00105 {
00106   hdr_cdiff* dfh = HDR_CDIFF(packet);
00107 
00108   // Packet Hash Table is used to keep info about experienced pkts.
00109 
00110   Pkt_Hash_Entry *hashPtr= PktTable.GetHash(dfh->sender_id, dfh->pk_num);
00111 
00112      // Received this packet before ?
00113 
00114      if (hashPtr != NULL) {
00115        Packet::free(packet);        
00116        return;
00117      }
00118 
00119      // Never receive it before ? Put in hash table.
00120 
00121      PktTable.put_in_hash(dfh);
00122 
00123      // Take action for a new pkt.
00124        
00125      ConsiderNew(packet);     
00126 }
00127 
00128 
00129 void FloodingAgent::ConsiderNew(Packet *pkt)
00130 {
00131   hdr_cdiff* dfh = HDR_CDIFF(pkt);
00132   unsigned char msg_type = dfh->mess_type;
00133   unsigned int dtype = dfh->data_type;
00134 
00135   Pkt_Hash_Entry *hashPtr;
00136   Agent_List *agentPtr;
00137   PrvCurPtr  RetVal;
00138   nsaddr_t   from_nodeID, forward_nodeID;
00139 
00140   Packet *gen_pkt;
00141   hdr_cdiff *gen_dfh;
00142 
00143   switch (msg_type) {
00144     case INTEREST : 
00145 
00146       hashPtr = PktTable.GetHash(dfh->sender_id, dfh->pk_num);
00147 
00148       // Check if it comes from sink agent of this node
00149       // If so we have to keep it in sink list 
00150 
00151       from_nodeID = (dfh->sender_id).addr_;
00152       forward_nodeID = (dfh->forward_agent_id).addr_;
00153 
00154 
00155       if (THIS_NODE == from_nodeID) {       
00156 
00157     // It's from a sink on this node.
00158     // Is it already in list ?
00159 
00160     RetVal = INTF_FIND(routing_table[dtype].sink, dfh->sender_id);
00161     if (RetVal.cur == NULL) {            
00162       // No, it's not.
00163       agentPtr = new Agent_List;
00164       AGT_ADDR(agentPtr) = dfh->sender_id;
00165       INTF_INSERT(routing_table[dtype].sink, agentPtr);
00166 
00167       God::instance()->AddSink(dtype, THIS_NODE);
00168     }   
00169       }
00170       
00171       Packet::free(pkt);
00172       return;
00173 
00174 
00175     case DATA_READY :
00176 
00177       // put source_agent in source list of routing table
00178 
00179       agentPtr = new Agent_List;
00180       AGT_ADDR(agentPtr) = dfh->sender_id;
00181       agentPtr->next = routing_table[dtype].source;
00182       routing_table[dtype].source = agentPtr;
00183 
00184       God::instance()->AddSource(dtype, (dfh->sender_id).addr_);
00185     
00186       gen_pkt = prepare_message(dtype, dfh->sender_id, DATA_REQUEST);
00187       gen_dfh = HDR_CDIFF(gen_pkt);
00188       gen_dfh->report_rate = ORIGINAL;
00189       send_to_dmux(gen_pkt, 0);
00190       Packet::free(pkt);
00191       return;
00192 
00193  
00194     case DATA :
00195 
00196       DataForSink(pkt);
00197 
00198       MACprepare(pkt);
00199       MACsend(pkt, JITTER*Random::uniform(1.0));
00200       return;
00201 
00202 
00203     default : 
00204       
00205       Packet::free(pkt);        
00206       break;
00207   }
00208 }
00209 
00210 
00211 void FloodingAgent::reset()
00212 {
00213   PktTable.reset();
00214 
00215   for (int i=0; i<MAX_DATA_TYPE; i++) {
00216     routing_table[i].reset();
00217   }
00218 }
00219 
00220 
00221 void FloodingAgent::Terminate() 
00222 {
00223 #ifdef DEBUG_OUTPUT
00224     printf("node %d: remaining energy %f, initial energy %f\n", THIS_NODE, 
00225            node->energy_model()->energy(), 
00226            node->energy_model()->initialenergy() );
00227 #endif
00228 }
00229 
00230 
00231 void FloodingAgent::StopSource()
00232 {
00233   Agent_List *cur;
00234 
00235   for (int i=0; i<MAX_DATA_TYPE; i++) {
00236     for (cur=routing_table[i].source; cur!=NULL; cur=AGENT_NEXT(cur) ) {
00237       SEND_MESSAGE(i, AGT_ADDR(cur), DATA_STOP);
00238     }
00239   }
00240 }
00241 
00242 
00243 Packet * FloodingAgent:: create_packet()
00244 {
00245   Packet *pkt = allocpkt();
00246 
00247   if (pkt==NULL) return NULL;
00248 
00249   hdr_cmn*  cmh = HDR_CMN(pkt);
00250   cmh->size() = 36;
00251 
00252   hdr_cdiff* dfh = HDR_CDIFF(pkt);
00253   dfh->ts_ = NOW;
00254   return pkt;
00255 }
00256 
00257 
00258 Packet *FloodingAgent::prepare_message(unsigned int dtype, ns_addr_t to_addr, 
00259                   int msg_type)
00260 {
00261   Packet *pkt;
00262   hdr_cdiff *dfh;
00263   hdr_ip *iph;
00264 
00265     pkt = create_packet();
00266     dfh = HDR_CDIFF(pkt);
00267     iph = HDR_IP(pkt);
00268     
00269     dfh->mess_type = msg_type;
00270     dfh->pk_num = pk_count;
00271     pk_count++;
00272     dfh->sender_id = here_;
00273     dfh->data_type = dtype;
00274     dfh->forward_agent_id = here_;
00275 
00276     dfh->ts_ = NOW;
00277     dfh->num_next = 1;
00278     dfh->next_nodes[0] = to_addr.addr_;
00279     
00280     iph->src_ = here_;
00281     iph->dst_ = to_addr;
00282 
00283     return pkt;
00284 }
00285 
00286 
00287 void FloodingAgent::MACprepare(Packet *pkt)
00288 {
00289   hdr_cdiff* dfh = HDR_CDIFF(pkt);
00290   hdr_cmn* cmh = HDR_CMN(pkt);
00291   hdr_ip*  iph = HDR_IP(pkt);
00292 
00293   dfh->forward_agent_id = here_; 
00294 
00295   cmh->xmit_failure_ = 0;
00296   cmh->next_hop() = MAC_BROADCAST;
00297   cmh->addr_type() = NS_AF_ILINK;
00298   cmh->direction() = hdr_cmn::DOWN;
00299 
00300   iph->src_ = here_;
00301   iph->dst_.addr_ = MAC_BROADCAST;
00302   iph->dst_.port_ = ROUTING_PORT;
00303 
00304   dfh->num_next = 1;
00305   dfh->next_nodes[0] = MAC_BROADCAST;
00306 }
00307 
00308 
00309 void FloodingAgent::MACsend(Packet *pkt, Time delay)
00310 {
00311   hdr_cmn*  cmh = HDR_CMN(pkt);
00312   hdr_cdiff* dfh = HDR_CDIFF(pkt);
00313 
00314   if (dfh->mess_type == DATA)
00315     cmh->size() = (God::instance()->data_pkt_size) + 4*(dfh->num_next - 1);
00316   else
00317     cmh->size() = 36 + 4*(dfh->num_next -1);
00318 
00319   Scheduler::instance().schedule(ll, pkt, delay);
00320 }
00321 
00322 
00323 void FloodingAgent::DataForSink(Packet *pkt)
00324 {
00325   hdr_cdiff     *dfh  = HDR_CDIFF(pkt);
00326   unsigned int dtype = dfh->data_type;
00327   Agent_List   *cur_agent;
00328   Packet       *cur_pkt;
00329   hdr_cdiff     *cur_dfh;
00330   hdr_ip       *cur_iph;
00331 
00332 
00333   for (cur_agent= (routing_table[dtype]).sink; cur_agent != NULL; 
00334        cur_agent= AGENT_NEXT(cur_agent) ) {
00335 
00336       cur_pkt       = pkt->copy();
00337       cur_iph       = HDR_IP(cur_pkt);
00338       cur_iph->dst_ = AGT_ADDR(cur_agent);
00339 
00340       cur_dfh       = HDR_CDIFF(cur_pkt);
00341       cur_dfh->forward_agent_id = here_;
00342       cur_dfh->num_next = 1;
00343       cur_dfh->next_nodes[0] = NODE_ADDR(cur_agent);
00344 
00345       send_to_dmux(cur_pkt, 0);
00346   }
00347 }
00348 
00349 
00350 void FloodingAgent::trace (char *fmt,...)
00351 {
00352   va_list ap;
00353 
00354   if (!tracetarget)
00355     return;
00356 
00357   va_start (ap, fmt);
00358   vsprintf (tracetarget->pt_->buffer(), fmt, ap);
00359   tracetarget->pt_->dump ();
00360   va_end (ap);
00361 }
00362 
00363 
00364 
00365 int FloodingAgent::command(int argc, const char*const* argv)
00366 {  
00367   Tcl& tcl =  Tcl::instance();
00368 
00369   if (argc == 2) {
00370 
00371     if (strcasecmp(argv[1], "reset-state")==0) {
00372       
00373       reset();
00374       return TCL_OK;
00375     }
00376 
00377     if (strcasecmp(argv[1], "reset")==0) {
00378       
00379       return Agent::command(argc, argv);
00380     }
00381 
00382     if (strcasecmp(argv[1], "start")==0) {
00383       return TCL_OK;
00384     }
00385 
00386     if (strcasecmp(argv[1], "stop")==0) {
00387       return TCL_OK;
00388     }
00389 
00390     if (strcasecmp(argv[1], "terminate")==0) {
00391       Terminate();
00392       return TCL_OK;
00393     }
00394 
00395     if (strcasecmp(argv[1], "stop-source")==0) {
00396       StopSource();
00397       return TCL_OK;
00398     }
00399 
00400   } else if (argc == 3) {
00401 
00402     if (strcasecmp(argv[1], "on-node")==0) {
00403       node = (Node *)tcl.lookup(argv[2]);
00404       return TCL_OK;
00405     }
00406 
00407     if (strcasecmp(argv[1], "add-ll") == 0) {
00408 
00409       TclObject *obj;
00410 
00411       if ( (obj = TclObject::lookup(argv[2])) == 0) {
00412     fprintf(stderr, "Flooding Node: %d lookup of %s failed\n", THIS_NODE,
00413         argv[2]);
00414     return TCL_ERROR;
00415       }
00416       ll = (NsObject *) obj;
00417 
00418      return TCL_OK;
00419     }
00420 
00421     if (strcasecmp (argv[1], "tracetarget") == 0) {
00422       TclObject *obj;
00423       if ((obj = TclObject::lookup (argv[2])) == 0) {
00424       fprintf (stderr, "%s: %s lookup of %s failed\n", __FILE__, argv[1],
00425            argv[2]);
00426       return TCL_ERROR;
00427       }
00428 
00429       tracetarget = (Trace *) obj;
00430       return TCL_OK;
00431     }
00432 
00433     if (strcasecmp(argv[1], "port-dmux") == 0) {
00434 
00435       TclObject *obj;
00436 
00437       if ( (obj = TclObject::lookup(argv[2])) == 0) {
00438     fprintf(stderr, "Flooding Node: %d lookup of %s failed\n", THIS_NODE,
00439         argv[2]);
00440     return TCL_ERROR;
00441       }
00442       port_dmux = (NsObject *) obj;
00443       return TCL_OK;
00444     }
00445 
00446   } 
00447 
00448   return Agent::command(argc, argv);
00449 }
00450 
00451 
00452 // Some methods for Flooding Entry
00453 
00454 void Flooding_Entry::reset()
00455 {
00456     clear_agentlist(source);
00457     clear_agentlist(sink);
00458     source = NULL;
00459     sink = NULL;
00460 }
00461 
00462 void Flooding_Entry::clear_agentlist(Agent_List *list)
00463 {
00464   Agent_List *cur=list;
00465   Agent_List *temp = NULL;
00466 
00467   while (cur != NULL) {
00468     temp = AGENT_NEXT(cur);
00469     delete cur;
00470     cur = temp;
00471   }
00472 }
00473 
00474 
00475 
00476 
00477 

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