Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

flood-agent.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) 1997,2000 Regents of the University of California.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *      This product includes software developed by the Computer Systems
00017  *      Engineering Group at Lawrence Berkeley Laboratory.
00018  * 4. Neither the name of the University nor of the Laboratory may be used
00019  *    to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  * @(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/sensor-nets/flood-agent.cc,v 1.4 2000/09/01 03:04:11 haoboy Exp $
00035  */
00036 
00037 // Author: Satish Kumar, kkumar@isi.edu
00038 
00039 #include <stdarg.h>
00040 #include <float.h>
00041 
00042 #include "flood-agent.h"
00043 #include <random.h>
00044 #include <cmu-trace.h>
00045 #include <address.h>
00046 
00047 #define OLD_QRY_ENTRY 0
00048 #define OLD_SHORTER_ENTRY 1
00049 #define NEW_QRY_ENTRY 2
00050 
00051 #define MAX_CACHE_ITEMS 200
00052 
00053 void FloodAgent::
00054 trace (char *fmt,...)
00055 {
00056   va_list ap; // Define a variable ap that will refer to each argument in turn
00057 
00058   if (!tracetarget_)
00059     return;
00060 
00061   // Initializes ap to first argument
00062   va_start (ap, fmt); 
00063   // Prints the elements in turn
00064   vsprintf (tracetarget_->buffer (), fmt, ap); 
00065   tracetarget_->dump ();
00066   // Does the necessary clean-up before returning
00067   va_end (ap); 
00068 }
00069 
00070 
00071 
00072 static class FloodAgentClass:public TclClass
00073 {
00074   public:
00075   FloodAgentClass ():TclClass ("Agent/flood")
00076   {
00077   }
00078   TclObject *create (int, const char *const *)
00079   {
00080     return (new FloodAgent ());
00081   }
00082 } class_flood_agent;
00083 
00084 
00085 
00086 FloodAgent::FloodAgent() : Agent(PT_MESSAGE)
00087 {
00088   node_ = NULL;
00089   tag_list_ = NULL;
00090   query_list_ = NULL;
00091 
00092   cache_ = 0; // Disable caching by default
00093   tag_cache_ = new TagCache[MAX_CACHE_ITEMS];
00094   num_cached_items_ = 0;
00095 }
00096 
00097 
00098 
00099 
00100 int 
00101 FloodAgent::command (int argc, const char *const *argv)
00102 {
00103   if (argc == 2)
00104     {
00105       if (strcmp (argv[1], "start-floodagent") == 0)
00106         {
00107           startUp();
00108           return (TCL_OK);
00109         }
00110       if (strcmp (argv[1], "enable-caching") == 0)
00111         {
00112           cache_ = 1;
00113           return (TCL_OK);
00114         }
00115       else if (strcasecmp (argv[1], "ll-queue") == 0)
00116         {
00117           if (!(ll_queue = (PriQueue *) TclObject::lookup (argv[2])))
00118             {
00119               fprintf (stderr, "Flood_Agent: ll-queue lookup of %s failed\n", argv[2]);
00120               return TCL_ERROR;
00121             }
00122           return TCL_OK;
00123         }
00124     }
00125   else if (argc == 3)
00126     {
00127       if (strcasecmp (argv[1], "tracetarget") == 0)
00128         {
00129           TclObject *obj;
00130           if ((obj = TclObject::lookup (argv[2])) == 0)
00131             {
00132               fprintf (stderr, "%s: %s lookup of %s failed\n", __FILE__, argv[1],
00133                        argv[2]);
00134               return TCL_ERROR;
00135             }
00136           tracetarget_ = (Trace *) obj;
00137           return TCL_OK;
00138         }
00139       else if (strcasecmp (argv[1], "addr") == 0) {
00140         int temp;
00141         temp = Address::instance().str2addr(argv[2]);
00142         myaddr_ = temp;
00143         return TCL_OK;
00144       }
00145       else if (strcasecmp (argv[1], "attach-tag-dbase") == 0)
00146         {
00147           TclObject *obj;
00148           if ((obj = TclObject::lookup (argv[2])) == 0)
00149             {
00150               fprintf (stderr, "%s: %s lookup of %s failed\n", __FILE__, argv[1],
00151                        argv[2]);
00152               return TCL_ERROR;
00153             }
00154           tag_dbase_ = (tags_database *) obj;
00155           return TCL_OK;
00156         }
00157       else if (strcasecmp (argv[1], "node") == 0)
00158         {
00159           assert(node_ == NULL);
00160           TclObject *obj;
00161           if ((obj = TclObject::lookup (argv[2])) == 0)
00162             {
00163               fprintf (stderr, "%s: %s lookup of %s failed\n", __FILE__, argv[1],
00164                        argv[2]);
00165               return TCL_ERROR;
00166             }
00167           node_ = (MobileNode *) obj;
00168           return TCL_OK;
00169         }
00170     }
00171   
00172   return (Agent::command (argc, argv));
00173 }
00174 
00175 
00176 
00177 
00178 
00179 void
00180 FloodAgent::startUp()
00181 {
00182   compr_taglist *local_tags0, *t_ptr;
00183   int ntags = 0;
00184   double x,y,z;
00185 
00186   node_->getLoc(&x,&y,&z);
00187   //  printf("Node %d position: (%f,%f,%f)\n",myaddr_,x,y,z);
00188 
00189   // Detection range smaller than transmission range. This is because, if 
00190   // the tags are passive, they may not have sufficient energy to re-radiate
00191   // information to the sensor
00192   double r = 60;
00193 
00194   local_tags0 = tag_dbase_->Gettags(x,y,r);
00195   trace("Node %d's at (%f,%f,%f) senses tags:",myaddr_,x,y,z);
00196   t_ptr = local_tags0;
00197   ntags = 0;
00198   while(t_ptr) {
00199     trace("tag name: %d.%d.%d",(t_ptr->obj_name_ >> 24) & 0xFF,(t_ptr->obj_name_ >> 16) & 0xFF,(t_ptr->obj_name_) & 0xFFFF);
00200     ++ntags;
00201     t_ptr = t_ptr->next_;
00202   }
00203   trace("Number of tags: %d",ntags);
00204 
00205   tag_list_ = local_tags0;
00206 
00207 }
00208 
00209 void
00210 FloodAgent::recv(Packet *p, Handler *)
00211 {
00212   hdr_ip *iph = HDR_IP(p);
00213   hdr_cmn *cmh = HDR_CMN(p);
00214   unsigned char *walk, *X_ptr, *Y_ptr;
00215   compr_taglist *tag_ptr;
00216   int found = FALSE, action, X, Y, obj_name, origin_time, next_hop_level;
00217   int cached = FALSE, cache_index = -1;
00218   int num_src_hops;
00219   double local_x, local_y, local_z;
00220   nsaddr_t last_hop_id;
00221   Scheduler &s = Scheduler::instance();
00222   double now = s.clock();
00223 
00224   walk = p->accessdata();
00225 
00226   // Type of advertisement
00227   action = *walk++;
00228 
00229   X_ptr = walk;
00230   X = *walk++;
00231   X = (X << 8) | *walk++;
00232 
00233   Y_ptr = walk;
00234   Y = *walk++;
00235   Y = (Y << 8) | *walk++;
00236 
00237   // Used in LM
00238   next_hop_level = *walk++;
00239 
00240   obj_name = *walk++;
00241   obj_name = (obj_name << 8) | *walk++;
00242   obj_name = (obj_name << 8) | *walk++;
00243   obj_name = (obj_name << 8) | *walk++;
00244 
00245     // origin time of advertisement
00246   origin_time = *walk++;
00247   origin_time = (origin_time << 8) | *walk++;
00248   origin_time = (origin_time << 8) | *walk++;
00249   origin_time = (origin_time << 8) | *walk++;
00250 
00251   num_src_hops = *walk++;
00252   num_src_hops = (num_src_hops << 8) | *walk++;
00253 
00254   // Query from an agent at our node
00255   if(iph->saddr() == myaddr_ && iph->sport() == 0 && action == QUERY_PKT) {
00256     // Increase the number of source hops to 1
00257     // Add IP header length
00258     cmh->size_ += 20;
00259   }
00260   else {
00261     ++num_src_hops;
00262     walk = walk - 2;
00263     (*walk++) = (num_src_hops >> 8) & 0xFF;
00264     (*walk++) = (num_src_hops) & 0XFF;
00265   }
00266     
00267   if(num_src_hops) {
00268     last_hop_id = *walk++;
00269     last_hop_id = (last_hop_id << 8) | *walk++;
00270   }
00271   else {
00272     last_hop_id = myaddr_;
00273     walk = walk + 2;
00274   }
00275 
00276   if(action == QUERY_PKT) {
00277     walk = walk - 2;
00278     *walk++ = (myaddr_ >> 8) & 0xFF;
00279     *walk++ = myaddr_ & 0xFF;
00280   }
00281 
00282   // Packet will be send down the stack
00283   cmh->direction() = hdr_cmn::DOWN;
00284 
00285 
00286   // Query pkt if X and Y are 65000
00287   if(X == 65000 && Y == 65000) {
00288 
00289     // Method returns 1 if query seen before. Otherwise returns 0
00290     // and adds query info to the list
00291     int query_type = search_queries_list(iph->saddr(),obj_name,origin_time,num_src_hops,last_hop_id);
00292     if(query_type == OLD_QRY_ENTRY) {
00293       Packet::free(p);
00294       return;
00295     }
00296 
00297     // Check if info is in cache if caching is enabled
00298     if(cache_) {
00299             // If this is a query pkt; check if we have the relevant information 
00300       // cached. TTL = 600 seconds for the cache entries
00301       cached = FALSE;
00302       for(int i = 0; i < num_cached_items_; ++i) {
00303         if(tag_cache_[i].obj_name_ == obj_name && tag_cache_[i].origin_time_ > origin_time - 600) {
00304           cached = TRUE;
00305           cache_index = i;
00306           break;
00307         }
00308       }
00309     }
00310 
00311 
00312     // check if our node has the requested information
00313     tag_ptr = tag_list_;
00314     while(tag_ptr) {
00315       if(tag_ptr->obj_name_ == obj_name) {
00316         found = TRUE;
00317         break;
00318       }
00319       tag_ptr = tag_ptr->next_;
00320     }
00321     
00322     if(query_type == OLD_SHORTER_ENTRY && found) {
00323       trace("Node %d: Query received along shorter path",myaddr_);
00324       Packet::free(p);
00325       return;
00326     }
00327     
00328     if(found || cached) {
00329       // generate response
00330       //      trace("Node %d: Generating response",myaddr_);
00331       if(cached) {
00332           (*X_ptr++) = ((int)tag_cache_[cache_index].X_ >> 8) & 0xFF;
00333           (*X_ptr) = ((int)tag_cache_[cache_index].X_) & 0xFF;
00334           (*Y_ptr++) = ((int)tag_cache_[cache_index].Y_ >> 8) & 0xFF;
00335           (*Y_ptr) = ((int)tag_cache_[cache_index].Y_) & 0xFF;
00336       }
00337       else {
00338         node_->getLoc(&local_x, &local_y, &local_z);
00339         (*X_ptr++) = ((int)local_x >> 8) & 0xFF;
00340         (*X_ptr) = ((int)local_x) & 0xFF;
00341         (*Y_ptr++) = ((int)local_y >> 8) & 0xFF;
00342         (*Y_ptr) = ((int)local_y) & 0xFF;
00343       }
00344 
00345       iph->ttl_ = 1000;
00346       iph->daddr() = iph->saddr();
00347       iph->dport() = QUERY_PORT;
00348       cmh->next_hop() = last_hop_id;
00349       cmh->addr_type_ = NS_AF_INET;
00350       // Add 50 bytes to response 
00351       cmh->size() += 50;
00352 
00353       if(last_hop_id == myaddr_) {
00354         // TEMPORARY HACK! Cant forward from routing agent to some other
00355         // agent on our node!
00356         Packet::free(p);
00357         trace("FloodAgent Found object %d.%d.%d at (%d,%d) at time %f", (obj_name >> 24) & 0xFF, (obj_name >> 16) & 0xFF, obj_name & 0xFFFF,X,Y,now);
00358         return;
00359       }
00360 
00361       s.schedule(target_,p,0);
00362     }
00363     else {
00364       // flood pkt 
00365       //      trace("Node %d: Flooding packet; query type %d",myaddr_,query_type);
00366       if(--iph->ttl_ == 0) {
00367         drop(p, DROP_RTR_TTL);
00368         return;
00369       }
00370 
00371       cmh->next_hop_ = IP_BROADCAST; // need to broadcast packet
00372       cmh->addr_type_ = NS_AF_INET;
00373       iph->daddr() = IP_BROADCAST;  // packet needs to be broadcast
00374       iph->dport() = ROUTER_PORT;
00375 
00376       s.schedule(target_,p,0);
00377     }
00378   }
00379   else {
00380     // Forward response
00381     //    trace("Node %d: Forwarding response",myaddr_);
00382     if(--iph->ttl_ == 0) {
00383       drop(p, DROP_RTR_TTL);
00384       return;
00385     }
00386     
00387     if(cache_) {
00388       if(num_cached_items_ < MAX_CACHE_ITEMS) {
00389         
00390         int replace_index = num_cached_items_;
00391         // If object already exists in cache, update info if necessary
00392         for(int i = 0; i < num_cached_items_; ++i) {
00393           if(tag_cache_[i].obj_name_ == obj_name && tag_cache_[i].origin_time_ < origin_time) {
00394             replace_index = i;
00395             break;
00396           }
00397         }
00398         
00399         tag_cache_[replace_index].obj_name_ = obj_name;
00400         tag_cache_[replace_index].origin_time_ = origin_time;
00401         tag_cache_[replace_index].X_ = X;
00402         tag_cache_[replace_index].Y_ = Y;
00403         ++num_cached_items_;
00404       }
00405       else {
00406         // Use LRU cache replacement
00407         int replace_index = 0;
00408         int least_time = tag_cache_[replace_index].origin_time_;
00409         for(int i = 0; i < MAX_CACHE_ITEMS; ++i) {
00410           if(tag_cache_[i].origin_time_ < least_time)
00411             replace_index = i;
00412         }
00413         tag_cache_[replace_index].obj_name_ = obj_name;
00414         tag_cache_[replace_index].origin_time_ = origin_time;
00415         tag_cache_[replace_index].X_ = X;
00416         tag_cache_[replace_index].Y_ = Y;
00417       }
00418     }
00419     
00420     cmh->next_hop_ = get_next_hop(iph->saddr(),obj_name,origin_time);
00421     assert(cmh->next_hop_ != NO_NEXT_HOP);
00422     s.schedule(target_,p,0);
00423   }
00424 }
00425 
00426 
00427 
00428 
00429 int
00430 FloodAgent::search_queries_list(nsaddr_t src, int obj_name, int origin_time, int num_hops, nsaddr_t last_hop_id)
00431 {
00432   QueryList *ql, *newql = NULL, *replql = NULL;
00433 
00434   ql = query_list_;
00435 
00436   while(ql) {
00437     if(ql->src_ == src && ql->obj_name_ == obj_name && ql->origin_time_ == origin_time) {
00438       if(ql->num_hops_ > num_hops) {
00439         ql->num_hops_ = num_hops;
00440         ql->last_hop_id_ = last_hop_id;
00441       return(OLD_SHORTER_ENTRY);
00442       }
00443       return(OLD_QRY_ENTRY);
00444     }
00445     // Replace very old entries
00446     if(ql->origin_time_ + 100 < origin_time && !replql)
00447       replql = ql;
00448     else if(!replql)
00449       newql = ql;
00450     ql = ql->next_;
00451   }    
00452 
00453   if(!query_list_) {
00454     query_list_ = new QueryList;
00455     query_list_->src_ = src;
00456     query_list_->obj_name_ = obj_name;
00457     query_list_->origin_time_ = origin_time;
00458     query_list_->num_hops_ = num_hops;
00459     query_list_->last_hop_id_ = last_hop_id;
00460     return(NEW_QRY_ENTRY);
00461   }
00462 
00463   if(replql) {
00464     replql->src_ = src;
00465     replql->obj_name_ = obj_name;
00466     replql->origin_time_ = origin_time;
00467     replql->num_hops_ = num_hops;
00468     replql->last_hop_id_ = last_hop_id;
00469   }
00470   else {
00471     newql->next_ = new QueryList;
00472     newql = newql->next_;
00473     newql->src_ = src;
00474     newql->obj_name_ = obj_name;
00475     newql->origin_time_ = origin_time;
00476     newql->num_hops_ = num_hops;
00477     newql->last_hop_id_ = last_hop_id;
00478   }
00479   return(NEW_QRY_ENTRY);
00480 }
00481   
00482 
00483 
00484 nsaddr_t
00485 FloodAgent::get_next_hop(nsaddr_t src, int obj_name, int origin_time)
00486 {
00487  QueryList *ql;
00488 
00489  ql = query_list_;
00490 
00491  while(ql) {
00492    if(ql->src_ == src && ql->obj_name_ == obj_name && ql->origin_time_ == origin_time) {
00493      return(ql->last_hop_id_);
00494    }
00495    ql = ql->next_;
00496  }
00497  
00498  return(NO_NEXT_HOP);
00499 }
00500 
00501  

Generated on Tue Apr 20 12:14:16 2004 for NS2.26SourcesOriginal by doxygen 1.3.3