00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
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;
00057
00058 if (!tracetarget_)
00059 return;
00060
00061
00062 va_start (ap, fmt);
00063
00064 vsprintf (tracetarget_->buffer (), fmt, ap);
00065 tracetarget_->dump ();
00066
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;
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
00188
00189
00190
00191
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
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
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
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
00255 if(iph->saddr() == myaddr_ && iph->sport() == 0 && action == QUERY_PKT) {
00256
00257
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
00283 cmh->direction() = hdr_cmn::DOWN;
00284
00285
00286
00287 if(X == 65000 && Y == 65000) {
00288
00289
00290
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
00298 if(cache_) {
00299
00300
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
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
00330
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
00351 cmh->size() += 50;
00352
00353 if(last_hop_id == myaddr_) {
00354
00355
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
00365
00366 if(--iph->ttl_ == 0) {
00367 drop(p, DROP_RTR_TTL);
00368 return;
00369 }
00370
00371 cmh->next_hop_ = IP_BROADCAST;
00372 cmh->addr_type_ = NS_AF_INET;
00373 iph->daddr() = IP_BROADCAST;
00374 iph->dport() = ROUTER_PORT;
00375
00376 s.schedule(target_,p,0);
00377 }
00378 }
00379 else {
00380
00381
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
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
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
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