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

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1997,2000 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  * This product includes software developed by the Computer Systems
  17.  * Engineering Group at Lawrence Berkeley Laboratory.
  18.  * 4. Neither the name of the University nor of the Laboratory may be used
  19.  *    to endorse or promote products derived from this software without
  20.  *    specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  *
  34.  * @(#) $Header: /cvsroot/nsnam/ns-2/sensor-nets/flood-agent.cc,v 1.4 2000/09/01 03:04:11 haoboy Exp $
  35.  */
  36. // Author: Satish Kumar, kkumar@isi.edu
  37. #include <stdarg.h>
  38. #include <float.h>
  39. #include "flood-agent.h"
  40. #include <random.h>
  41. #include <cmu-trace.h>
  42. #include <address.h>
  43. #define OLD_QRY_ENTRY 0
  44. #define OLD_SHORTER_ENTRY 1
  45. #define NEW_QRY_ENTRY 2
  46. #define MAX_CACHE_ITEMS 200
  47. void FloodAgent::
  48. trace (char *fmt,...)
  49. {
  50.   va_list ap; // Define a variable ap that will refer to each argument in turn
  51.   if (!tracetarget_)
  52.     return;
  53.   // Initializes ap to first argument
  54.   va_start (ap, fmt); 
  55.   // Prints the elements in turn
  56.   vsprintf (tracetarget_->buffer (), fmt, ap); 
  57.   tracetarget_->dump ();
  58.   // Does the necessary clean-up before returning
  59.   va_end (ap); 
  60. }
  61. static class FloodAgentClass:public TclClass
  62. {
  63.   public:
  64.   FloodAgentClass ():TclClass ("Agent/flood")
  65.   {
  66.   }
  67.   TclObject *create (int, const char *const *)
  68.   {
  69.     return (new FloodAgent ());
  70.   }
  71. } class_flood_agent;
  72. FloodAgent::FloodAgent() : Agent(PT_MESSAGE)
  73. {
  74.   node_ = NULL;
  75.   tag_list_ = NULL;
  76.   query_list_ = NULL;
  77.   cache_ = 0; // Disable caching by default
  78.   tag_cache_ = new TagCache[MAX_CACHE_ITEMS];
  79.   num_cached_items_ = 0;
  80. }
  81. int 
  82. FloodAgent::command (int argc, const char *const *argv)
  83. {
  84.   if (argc == 2)
  85.     {
  86.       if (strcmp (argv[1], "start-floodagent") == 0)
  87.         {
  88.           startUp();
  89.           return (TCL_OK);
  90.         }
  91.       if (strcmp (argv[1], "enable-caching") == 0)
  92.         {
  93.           cache_ = 1;
  94.           return (TCL_OK);
  95.         }
  96.       else if (strcasecmp (argv[1], "ll-queue") == 0)
  97.         {
  98.   if (!(ll_queue = (PriQueue *) TclObject::lookup (argv[2])))
  99.             {
  100.               fprintf (stderr, "Flood_Agent: ll-queue lookup of %s failedn", argv[2]);
  101.               return TCL_ERROR;
  102.             }
  103.   return TCL_OK;
  104.         }
  105.     }
  106.   else if (argc == 3)
  107.     {
  108.       if (strcasecmp (argv[1], "tracetarget") == 0)
  109.         {
  110.           TclObject *obj;
  111.   if ((obj = TclObject::lookup (argv[2])) == 0)
  112.             {
  113.               fprintf (stderr, "%s: %s lookup of %s failedn", __FILE__, argv[1],
  114.                        argv[2]);
  115.               return TCL_ERROR;
  116.             }
  117.           tracetarget_ = (Trace *) obj;
  118.           return TCL_OK;
  119.         }
  120.       else if (strcasecmp (argv[1], "addr") == 0) {
  121.         int temp;
  122.         temp = Address::instance().str2addr(argv[2]);
  123.         myaddr_ = temp;
  124.         return TCL_OK;
  125.       }
  126.       else if (strcasecmp (argv[1], "attach-tag-dbase") == 0)
  127.         {
  128.           TclObject *obj;
  129.   if ((obj = TclObject::lookup (argv[2])) == 0)
  130.             {
  131.               fprintf (stderr, "%s: %s lookup of %s failedn", __FILE__, argv[1],
  132.                        argv[2]);
  133.               return TCL_ERROR;
  134.             }
  135.           tag_dbase_ = (tags_database *) obj;
  136.           return TCL_OK;
  137.         }
  138.       else if (strcasecmp (argv[1], "node") == 0)
  139.         {
  140.           assert(node_ == NULL);
  141.           TclObject *obj;
  142.   if ((obj = TclObject::lookup (argv[2])) == 0)
  143.             {
  144.               fprintf (stderr, "%s: %s lookup of %s failedn", __FILE__, argv[1],
  145.                        argv[2]);
  146.               return TCL_ERROR;
  147.             }
  148.           node_ = (MobileNode *) obj;
  149.           return TCL_OK;
  150.         }
  151.     }
  152.   
  153.   return (Agent::command (argc, argv));
  154. }
  155. void
  156. FloodAgent::startUp()
  157. {
  158.   compr_taglist *local_tags0, *t_ptr;
  159.   int ntags = 0;
  160.   double x,y,z;
  161.   node_->getLoc(&x,&y,&z);
  162.   //  printf("Node %d position: (%f,%f,%f)n",myaddr_,x,y,z);
  163.   // Detection range smaller than transmission range. This is because, if 
  164.   // the tags are passive, they may not have sufficient energy to re-radiate
  165.   // information to the sensor
  166.   double r = 60;
  167.   local_tags0 = tag_dbase_->Gettags(x,y,r);
  168.   trace("Node %d's at (%f,%f,%f) senses tags:",myaddr_,x,y,z);
  169.   t_ptr = local_tags0;
  170.   ntags = 0;
  171.   while(t_ptr) {
  172.     trace("tag name: %d.%d.%d",(t_ptr->obj_name_ >> 24) & 0xFF,(t_ptr->obj_name_ >> 16) & 0xFF,(t_ptr->obj_name_) & 0xFFFF);
  173.     ++ntags;
  174.     t_ptr = t_ptr->next_;
  175.   }
  176.   trace("Number of tags: %d",ntags);
  177.   tag_list_ = local_tags0;
  178. }
  179. void
  180. FloodAgent::recv(Packet *p, Handler *)
  181. {
  182.   hdr_ip *iph = HDR_IP(p);
  183.   hdr_cmn *cmh = HDR_CMN(p);
  184.   unsigned char *walk, *X_ptr, *Y_ptr;
  185.   compr_taglist *tag_ptr;
  186.   int found = FALSE, action, X, Y, obj_name, origin_time, next_hop_level;
  187.   int cached = FALSE, cache_index = -1;
  188.   int num_src_hops;
  189.   double local_x, local_y, local_z;
  190.   nsaddr_t last_hop_id;
  191.   Scheduler &s = Scheduler::instance();
  192.   double now = s.clock();
  193.   walk = p->accessdata();
  194.   // Type of advertisement
  195.   action = *walk++;
  196.   X_ptr = walk;
  197.   X = *walk++;
  198.   X = (X << 8) | *walk++;
  199.   Y_ptr = walk;
  200.   Y = *walk++;
  201.   Y = (Y << 8) | *walk++;
  202.   // Used in LM
  203.   next_hop_level = *walk++;
  204.   obj_name = *walk++;
  205.   obj_name = (obj_name << 8) | *walk++;
  206.   obj_name = (obj_name << 8) | *walk++;
  207.   obj_name = (obj_name << 8) | *walk++;
  208.     // origin time of advertisement
  209.   origin_time = *walk++;
  210.   origin_time = (origin_time << 8) | *walk++;
  211.   origin_time = (origin_time << 8) | *walk++;
  212.   origin_time = (origin_time << 8) | *walk++;
  213.   num_src_hops = *walk++;
  214.   num_src_hops = (num_src_hops << 8) | *walk++;
  215.   // Query from an agent at our node
  216.   if(iph->saddr() == myaddr_ && iph->sport() == 0 && action == QUERY_PKT) {
  217.     // Increase the number of source hops to 1
  218.     // Add IP header length
  219.     cmh->size_ += 20;
  220.   }
  221.   else {
  222.     ++num_src_hops;
  223.     walk = walk - 2;
  224.     (*walk++) = (num_src_hops >> 8) & 0xFF;
  225.     (*walk++) = (num_src_hops) & 0XFF;
  226.   }
  227.     
  228.   if(num_src_hops) {
  229.     last_hop_id = *walk++;
  230.     last_hop_id = (last_hop_id << 8) | *walk++;
  231.   }
  232.   else {
  233.     last_hop_id = myaddr_;
  234.     walk = walk + 2;
  235.   }
  236.   if(action == QUERY_PKT) {
  237.     walk = walk - 2;
  238.     *walk++ = (myaddr_ >> 8) & 0xFF;
  239.     *walk++ = myaddr_ & 0xFF;
  240.   }
  241.   // Packet will be send down the stack
  242.   cmh->direction() = hdr_cmn::DOWN;
  243.   // Query pkt if X and Y are 65000
  244.   if(X == 65000 && Y == 65000) {
  245.     // Method returns 1 if query seen before. Otherwise returns 0
  246.     // and adds query info to the list
  247.     int query_type = search_queries_list(iph->saddr(),obj_name,origin_time,num_src_hops,last_hop_id);
  248.     if(query_type == OLD_QRY_ENTRY) {
  249.       Packet::free(p);
  250.       return;
  251.     }
  252.     // Check if info is in cache if caching is enabled
  253.     if(cache_) {
  254.             // If this is a query pkt; check if we have the relevant information 
  255.       // cached. TTL = 600 seconds for the cache entries
  256.       cached = FALSE;
  257.       for(int i = 0; i < num_cached_items_; ++i) {
  258.         if(tag_cache_[i].obj_name_ == obj_name && tag_cache_[i].origin_time_ > origin_time - 600) {
  259.           cached = TRUE;
  260.           cache_index = i;
  261.           break;
  262.         }
  263.       }
  264.     }
  265.     // check if our node has the requested information
  266.     tag_ptr = tag_list_;
  267.     while(tag_ptr) {
  268.       if(tag_ptr->obj_name_ == obj_name) {
  269. found = TRUE;
  270. break;
  271.       }
  272.       tag_ptr = tag_ptr->next_;
  273.     }
  274.     
  275.     if(query_type == OLD_SHORTER_ENTRY && found) {
  276.       trace("Node %d: Query received along shorter path",myaddr_);
  277.       Packet::free(p);
  278.       return;
  279.     }
  280.     
  281.     if(found || cached) {
  282.       // generate response
  283.       //      trace("Node %d: Generating response",myaddr_);
  284.       if(cached) {
  285.           (*X_ptr++) = ((int)tag_cache_[cache_index].X_ >> 8) & 0xFF;
  286.           (*X_ptr) = ((int)tag_cache_[cache_index].X_) & 0xFF;
  287.           (*Y_ptr++) = ((int)tag_cache_[cache_index].Y_ >> 8) & 0xFF;
  288.           (*Y_ptr) = ((int)tag_cache_[cache_index].Y_) & 0xFF;
  289.       }
  290.       else {
  291. node_->getLoc(&local_x, &local_y, &local_z);
  292. (*X_ptr++) = ((int)local_x >> 8) & 0xFF;
  293. (*X_ptr) = ((int)local_x) & 0xFF;
  294. (*Y_ptr++) = ((int)local_y >> 8) & 0xFF;
  295. (*Y_ptr) = ((int)local_y) & 0xFF;
  296.       }
  297.       iph->ttl_ = 1000;
  298.       iph->daddr() = iph->saddr();
  299.       iph->dport() = QUERY_PORT;
  300.       cmh->next_hop() = last_hop_id;
  301.       cmh->addr_type_ = NS_AF_INET;
  302.       // Add 50 bytes to response 
  303.       cmh->size() += 50;
  304.       if(last_hop_id == myaddr_) {
  305. // TEMPORARY HACK! Cant forward from routing agent to some other
  306. // agent on our node!
  307. Packet::free(p);
  308. 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);
  309. return;
  310.       }
  311.       s.schedule(target_,p,0);
  312.     }
  313.     else {
  314.       // flood pkt 
  315.       //      trace("Node %d: Flooding packet; query type %d",myaddr_,query_type);
  316.       if(--iph->ttl_ == 0) {
  317. drop(p, DROP_RTR_TTL);
  318. return;
  319.       }
  320.       cmh->next_hop_ = IP_BROADCAST; // need to broadcast packet
  321.       cmh->addr_type_ = NS_AF_INET;
  322.       iph->daddr() = IP_BROADCAST;  // packet needs to be broadcast
  323.       iph->dport() = ROUTER_PORT;
  324.       s.schedule(target_,p,0);
  325.     }
  326.   }
  327.   else {
  328.     // Forward response
  329.     //    trace("Node %d: Forwarding response",myaddr_);
  330.     if(--iph->ttl_ == 0) {
  331.       drop(p, DROP_RTR_TTL);
  332.       return;
  333.     }
  334.     
  335.     if(cache_) {
  336.       if(num_cached_items_ < MAX_CACHE_ITEMS) {
  337. int replace_index = num_cached_items_;
  338. // If object already exists in cache, update info if necessary
  339. for(int i = 0; i < num_cached_items_; ++i) {
  340.   if(tag_cache_[i].obj_name_ == obj_name && tag_cache_[i].origin_time_ < origin_time) {
  341.     replace_index = i;
  342.     break;
  343.   }
  344. }
  345. tag_cache_[replace_index].obj_name_ = obj_name;
  346. tag_cache_[replace_index].origin_time_ = origin_time;
  347. tag_cache_[replace_index].X_ = X;
  348. tag_cache_[replace_index].Y_ = Y;
  349. ++num_cached_items_;
  350.       }
  351.       else {
  352. // Use LRU cache replacement
  353. int replace_index = 0;
  354. int least_time = tag_cache_[replace_index].origin_time_;
  355. for(int i = 0; i < MAX_CACHE_ITEMS; ++i) {
  356.   if(tag_cache_[i].origin_time_ < least_time)
  357.     replace_index = i;
  358. }
  359. tag_cache_[replace_index].obj_name_ = obj_name;
  360. tag_cache_[replace_index].origin_time_ = origin_time;
  361. tag_cache_[replace_index].X_ = X;
  362. tag_cache_[replace_index].Y_ = Y;
  363.       }
  364.     }
  365.     
  366.     cmh->next_hop_ = get_next_hop(iph->saddr(),obj_name,origin_time);
  367.     assert(cmh->next_hop_ != NO_NEXT_HOP);
  368.     s.schedule(target_,p,0);
  369.   }
  370. }
  371. int
  372. FloodAgent::search_queries_list(nsaddr_t src, int obj_name, int origin_time, int num_hops, nsaddr_t last_hop_id)
  373. {
  374.   QueryList *ql, *newql = NULL, *replql = NULL;
  375.   ql = query_list_;
  376.   while(ql) {
  377.     if(ql->src_ == src && ql->obj_name_ == obj_name && ql->origin_time_ == origin_time) {
  378.       if(ql->num_hops_ > num_hops) {
  379. ql->num_hops_ = num_hops;
  380. ql->last_hop_id_ = last_hop_id;
  381.       return(OLD_SHORTER_ENTRY);
  382.       }
  383.       return(OLD_QRY_ENTRY);
  384.     }
  385.     // Replace very old entries
  386.     if(ql->origin_time_ + 100 < origin_time && !replql)
  387.       replql = ql;
  388.     else if(!replql)
  389.       newql = ql;
  390.     ql = ql->next_;
  391.   }    
  392.   if(!query_list_) {
  393.     query_list_ = new QueryList;
  394.     query_list_->src_ = src;
  395.     query_list_->obj_name_ = obj_name;
  396.     query_list_->origin_time_ = origin_time;
  397.     query_list_->num_hops_ = num_hops;
  398.     query_list_->last_hop_id_ = last_hop_id;
  399.     return(NEW_QRY_ENTRY);
  400.   }
  401.   if(replql) {
  402.     replql->src_ = src;
  403.     replql->obj_name_ = obj_name;
  404.     replql->origin_time_ = origin_time;
  405.     replql->num_hops_ = num_hops;
  406.     replql->last_hop_id_ = last_hop_id;
  407.   }
  408.   else {
  409.     newql->next_ = new QueryList;
  410.     newql = newql->next_;
  411.     newql->src_ = src;
  412.     newql->obj_name_ = obj_name;
  413.     newql->origin_time_ = origin_time;
  414.     newql->num_hops_ = num_hops;
  415.     newql->last_hop_id_ = last_hop_id;
  416.   }
  417.   return(NEW_QRY_ENTRY);
  418. }
  419.   
  420. nsaddr_t
  421. FloodAgent::get_next_hop(nsaddr_t src, int obj_name, int origin_time)
  422. {
  423.  QueryList *ql;
  424.  ql = query_list_;
  425.  while(ql) {
  426.    if(ql->src_ == src && ql->obj_name_ == obj_name && ql->origin_time_ == origin_time) {
  427.      return(ql->last_hop_id_);
  428.    }
  429.    ql = ql->next_;
  430.  }
  431.  
  432.  return(NO_NEXT_HOP);
  433. }
  434.