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
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #include <assert.h>
00059
00060 #include "agent.h"
00061 #include "tclcl.h"
00062 #include "packet.h"
00063 #include "random.h"
00064 #include "lms.h"
00065 #include "ip.h"
00066
00067 static int lms_agent_uid_ = 0;
00068
00069 class LmsAgent : public Agent {
00070 public:
00071 LmsAgent ();
00072 int command (int argc, const char*const* argv);
00073 void recv (Packet*, Handler*);
00074 protected:
00075
00076 NsObject* iface2link (int iface);
00077 NsObject* pkt2agent (Packet *pkt);
00078 void send_upstream (Packet *p);
00079 void send_downstream (Packet *p);
00080
00081 inline void
00082 send2replier (Packet *p)
00083 {
00084 hdr_ip* piph = HDR_IP(p);
00085
00086 #ifdef LMS_DEBUG
00087 printf("%s send2replier: Got piph->saddr: %d, downstream_addr: %d. Replier: %d\n", uname_, piph->saddr(), downstream_lms_.addr_, replier_ );
00088 #endif
00089 if (replier_ != NULL)
00090 replier_->recv (p);
00091 else if ((downstream_lms_.addr_ != LMS_NOADDR) &&
00092 (piph->saddr() != downstream_lms_.addr_) )
00093 send_downstream(p);
00094 else send_upstream (p);
00095 };
00096
00097 char uname_[16];
00098 int lms_enabled_;
00099 NsObject* replier_;
00100 int replier_iface_;
00101 int replier_cost_;
00102 int replier_dist_;
00103 nsaddr_t upstream_lms_;
00104 ns_addr_t downstream_lms_;
00105
00106 int upstream_iface_;
00107 int have_rcvr_;
00108
00109
00110
00111
00112 };
00113
00114
00115
00116
00117 static class LmsClass : public TclClass {
00118 public:
00119 LmsClass() : TclClass("Agent/LMS") {}
00120 TclObject* create(int, const char*const*) {
00121 return (new LmsAgent());
00122 }
00123 } class_lms_agent;
00124
00125
00126
00127
00128
00129
00130 int hdr_lms::offset_;
00131
00132 static class LmsHeaderClass : public PacketHeaderClass {
00133 public:
00134 LmsHeaderClass() : PacketHeaderClass("PacketHeader/Lms",
00135 sizeof(hdr_lms)) {
00136 bind_offset(&hdr_lms::offset_);
00137 }
00138 } class_lmshdr;
00139
00140
00141
00142
00143
00144 LmsAgent::LmsAgent() : Agent(PT_LMS)
00145 {
00146 sprintf (uname_, "lms%d", lms_agent_uid_++);
00147 replier_ = NULL;
00148 replier_iface_ = LMS_NOIFACE;
00149 replier_cost_ = LMS_INFINITY;
00150 replier_dist_ = 0;
00151 upstream_lms_ = LMS_NOADDR;
00152 downstream_lms_.addr_ = LMS_NOADDR;
00153 downstream_lms_.port_ = LMS_NOPORT;
00154 have_rcvr_ = 0;
00155
00156 bind("lms_enabled_", &lms_enabled_);
00157 bind("packetSize_", &size_);
00158
00159
00160 }
00161
00162
00163
00164
00165 void LmsAgent::recv (Packet* pkt, Handler*)
00166 {
00167 hdr_cmn* h = HDR_CMN(pkt);
00168 hdr_lms* lh = HDR_LMS(pkt);
00169
00170
00171 #ifdef LMS_DEBUG
00172 int a1 = lh->from_; int a2 = lh->src_;
00173 printf ("at %f %s received packet type %d from %d:%d src %d:%d group %x iface %d\n\n", now,uname_, lh->type(), a1>>8, a1&0xff, a2>>8, a2&0xff, lh->group_,h->iface());
00174 #endif
00175
00176
00177 if (!lms_enabled_)
00178 {
00179 target_->recv (pkt);
00180 return;
00181 }
00182
00183 switch (lh->type())
00184 {
00185 case LMS_SRC_REFRESH:
00186 {
00187
00188
00189
00190
00191 struct lms_ctl *c = (struct lms_ctl *)pkt->accessdata ();
00192 c->hop_cnt_++;
00193 #ifdef LMS_DEBUG
00194 printf ("%s LMS_SRC_REFRESH from iface %d, cost %d, ttl %d\n\n",
00195 uname_, h->iface(), c->cost_, lh->ttl_);
00196 #endif
00197 assert (upstream_iface_ == h->iface());
00198
00199 if (replier_iface_ == h->iface())
00200 {
00201 if (replier_cost_ != c->cost_)
00202 replier_cost_ = c->cost_;
00203 if (replier_dist_ != c->hop_cnt_)
00204 replier_dist_ = c->hop_cnt_;
00205 }
00206 else if (replier_cost_ >= c->cost_ && replier_dist_ > c->hop_cnt_)
00207 {
00208 #ifdef LMS_DEBUG
00209 printf ("%s chose upstream replier\n\n", uname_);
00210 #endif
00211 replier_cost_ = c->cost_;
00212 replier_dist_ = c->hop_cnt_;
00213 replier_iface_ = h->iface();
00214 if (h->iface() < 0)
00215 {
00216 replier_ = pkt2agent (pkt);
00217 downstream_lms_.addr_ = LMS_NOADDR;
00218 downstream_lms_.port_ = LMS_NOPORT;
00219 }
00220 else {
00221 replier_ = iface2link (h->iface());
00222 downstream_lms_.addr_ = LMS_NOADDR;
00223 downstream_lms_.port_ = LMS_NOPORT;
00224 }
00225 if (--lh->ttl_ > 0)
00226 target_->recv (pkt);
00227 else Packet::free(pkt);
00228 return;
00229 }
00230 break;
00231 }
00232
00233 case LMS_REFRESH:
00234 {
00235 struct lms_ctl *c = (struct lms_ctl *)pkt->accessdata ();
00236 c->hop_cnt_++;
00237 #ifdef LMS_DEBUG
00238 printf("%s replier iface %d, h->iface %d, replier cost %d, c cost %d\n",
00239 uname_, replier_iface_, h->iface(), replier_cost_, c->cost_);
00240 printf("replier_= %d, down_addr_= %d, down_port_ = %d\n\n",
00241 replier_, downstream_lms_.addr_, downstream_lms_.port_);
00242 #endif
00243
00244
00245
00246 if (replier_iface_ == h->iface())
00247 {
00248 if (replier_cost_ != c->cost_)
00249 replier_cost_ = c->cost_;
00250 if (replier_dist_ != c->hop_cnt_)
00251 replier_dist_ = c->hop_cnt_;
00252 #ifdef LMS_DEBUG
00253 printf ("%s REPLIER_UPDATE iface %d, cost %d, hops %d\n\n",
00254 uname_, replier_iface_, replier_cost_, replier_dist_);
00255 #endif
00256
00257
00258 if (h->iface() < 0)
00259 {
00260 replier_ = pkt2agent (pkt);
00261 have_rcvr_ = 1;
00262 downstream_lms_.addr_ = LMS_NOADDR;
00263 downstream_lms_.port_ = LMS_NOPORT;
00264 }
00265 else
00266 {
00267
00268 downstream_lms_ = c->downstream_lms_;
00269
00270
00271 c->downstream_lms_.addr_ = addr();
00272 c->downstream_lms_.port_ = port();
00273
00274 replier_ = NULL;
00275 }
00276 send_upstream (pkt);
00277 }
00278
00279
00280 else if (replier_cost_ > c->cost_)
00281 {
00282 replier_cost_ = c->cost_;
00283 replier_dist_ = c->hop_cnt_;
00284 replier_iface_ = h->iface();
00285
00286 if (h->iface() < 0)
00287 {
00288 replier_ = pkt2agent (pkt);
00289 have_rcvr_ = 1;
00290 downstream_lms_.addr_ = LMS_NOADDR;
00291 downstream_lms_.port_ = LMS_NOPORT;
00292 }
00293 else
00294 {
00295
00296 downstream_lms_ = c->downstream_lms_;
00297
00298
00299 c->downstream_lms_.addr_ = addr();
00300 c->downstream_lms_.port_ = port();
00301
00302 replier_ = NULL;
00303 }
00304 #ifdef LMS_DEBUG
00305 printf ("%s REPLIER iface %d, cost %d, hops %d\n\n",
00306 uname_, replier_iface_, replier_cost_, replier_dist_);
00307 #endif
00308 send_upstream (pkt);
00309 }
00310 else
00311 Packet::free(pkt);
00312 return;
00313 }
00314
00315 case LMS_REQ:
00316 if (replier_iface_ == h->iface())
00317 send_upstream (pkt);
00318 else {
00319
00320
00321 if (lh->tp_addr_ == LMS_NOADDR)
00322 {
00323 lh->tp_addr_ = addr();
00324 lh->tp_port_ = port();
00325 lh->tp_iface_ = h->iface_;
00326 }
00327 send2replier (pkt);
00328 }
00329 break;
00330
00331 case LMS_DMCAST:
00332 {
00333 #ifdef LMS_DEBUG
00334 a2 = lh->src_;
00335 printf ("LMS-DMCAST at agent %s, iface %d src %d:%d group %d\n\n",
00336 uname_, lh->tp_iface_, a2>>8, a2&0xff, lh->group_);
00337 #endif
00338 hdr_ip* iph = HDR_IP(pkt);
00339 NsObject* tgt = iface2link (lh->tp_iface_);
00340
00341 if (tgt)
00342 {
00343
00344 iph->saddr() = lh->src_;
00345 iph->daddr() = lh->group_;
00346 tgt->recv (pkt);
00347 }
00348 else {
00349 printf ("FATAL: %s no such iface %d\n", uname_, lh->tp_iface_);
00350 abort ();
00351 }
00352 }
00353 break;
00354
00355 case LMS_LEAVE:
00356 {
00357
00358 if (replier_iface_ == h->iface())
00359 {
00360 downstream_lms_.addr_ = LMS_NOADDR;
00361 downstream_lms_.port_ = LMS_NOPORT;
00362
00363 replier_ = NULL;
00364 replier_cost_ = 1000000;
00365 replier_iface_ = LMS_NOIFACE;
00366 send_upstream (pkt);
00367 }
00368 else
00369 Packet::free(pkt);
00370
00371 return;
00372 }
00373
00374 case LMS_SETUP:
00375 {
00376
00377 if (h->iface() < 0)
00378 {
00379
00380 replier_ = pkt2agent (pkt);
00381 replier_iface_ = h->iface();
00382 downstream_lms_.addr_ = LMS_NOADDR;
00383 downstream_lms_.port_ = LMS_NOPORT;
00384
00385 replier_cost_ = 0;
00386
00387 #ifdef LMS_DEBUG
00388 printf ("%s REPLIER iface %d, cost %d\n\n", uname_, replier_iface_, replier_cost_);
00389 #endif
00390
00391 }
00392 upstream_lms_ = lh->from_;
00393 upstream_iface_ = h->iface();
00394
00395 #ifdef LMS_DEBUG
00396 printf ("%s upstream %d\n\n", uname_, upstream_lms_);
00397 #endif
00398
00399 lh->from_ = addr();
00400 Tcl::instance().evalf("[%s set node_] agent %d", name(), port());
00401 target_->recv (pkt);
00402 return;
00403 }
00404
00405 case LMS_SPM:
00406 {
00407 if (upstream_lms_ < 0)
00408 {
00409 struct lms_spm *spm = (struct lms_spm *)pkt->accessdata ();
00410
00411 #ifdef LMS_DEBUG
00412 printf ("%s LMS_SPM seqno %d, upstream %d:%d\n\n",
00413 uname_, spm->spm_seqno_, adr>>8, adr&0xff);
00414 #endif
00415
00416 if (upstream_lms_ != spm->spm_path_)
00417 upstream_lms_ = spm->spm_path_;
00418
00419 spm->spm_path_ = addr();
00420 }
00421 break;
00422 }
00423
00424 case LMS_LINKS:
00425 {
00426 Tcl& tcl = Tcl::instance();
00427 char wrk[64];
00428 int n1 = lh->from();
00429 int n2 = addr();
00430
00431 if (n1 != n2 && !have_rcvr_)
00432 {
00433 sprintf (wrk, "lappend tree_links {%d %d}", n1, n2);
00434 tcl.eval (wrk);
00435 }
00436
00437 lh->from_ = addr();
00438 target_->recv (pkt);
00439 return;
00440 }
00441 default:
00442 printf ("FATAL: %s uknown LMS packet type: %d\n", uname_, lh->type());
00443 abort ();
00444 }
00445 }
00446
00447
00448
00449 int LmsAgent::command (int argc, const char*const* argv)
00450 {
00451
00452
00453 if (argc == 6) {
00454 if (strcmp(argv[1], "send-lms") == 0) {
00455 Packet* pkt = allocpkt();
00456 hdr_lms* ph = HDR_LMS(pkt);
00457
00458 ph->type() = atoi (argv[2]);
00459 ph->from() = atoi(argv[3]);
00460 ph->src() = atoi(argv[4]);
00461 ph->group() = atoi(argv[5]);
00462
00463 send(pkt, 0);
00464 return (TCL_OK);
00465 }
00466 }
00467
00468 return (Agent::command(argc, argv));
00469 }
00470
00471
00472
00473
00474
00475
00476 NsObject* LmsAgent::iface2link (int iface)
00477 {
00478 Tcl& tcl = Tcl::instance();
00479 char wrk[64];
00480
00481 sprintf (wrk, "[%s set node_] ifaceGetOutLink %d", name (), iface);
00482 tcl.evalc (wrk);
00483 const char* result = tcl.result ();
00484
00485 #ifdef LMS_DEBUG
00486 printf ("[iface2link] agent %s\n", result);
00487 #endif
00488
00489 NsObject* obj = (NsObject*)TclObject::lookup(result);
00490 return (obj);
00491 }
00492
00493
00494
00495
00496
00497 NsObject* LmsAgent::pkt2agent (Packet *pkt)
00498 {
00499 Tcl& tcl = Tcl::instance();
00500 char wrk[64];
00501 const char *result;
00502 int port;
00503 NsObject* agent;
00504 hdr_ip* ih = HDR_IP(pkt);
00505
00506
00507 port = ih->sport();
00508
00509 sprintf (wrk, "[%s set node_] agent %d", name (), port);
00510 tcl.evalc (wrk);
00511 result = tcl.result ();
00512
00513 #ifdef LMS_DEBUG
00514 printf ("[pkt2agent] port %d, agent %s\n", port, result);
00515 #endif
00516
00517 agent = (NsObject*)TclObject::lookup (result);
00518 return (agent);
00519 }
00520
00521 void LmsAgent::send_upstream (Packet *p)
00522 {
00523 if (upstream_lms_ < 0)
00524 {
00525 printf ("FATAL: %s upstream_lms_ not set!\n", uname_);
00526 abort ();
00527 }
00528 hdr_ip* ih = HDR_IP(p);
00529 hdr_lms* lh = HDR_LMS(p);
00530
00531 lh->from_ = addr();
00532 ih->daddr() = upstream_lms_;
00533 target_->recv(p);
00534 }
00535
00536
00537 void LmsAgent::send_downstream (Packet *p)
00538 {
00539 if (downstream_lms_.addr_ < 0)
00540 {
00541 printf ("FATAL: %s downstream_lms_ not set!\n", uname_);
00542 abort ();
00543 }
00544 hdr_ip* ih = HDR_IP(p);
00545 hdr_lms* lh = HDR_LMS(p);
00546
00547 lh->from_ = addr();
00548 ih->daddr() = downstream_lms_.addr_;
00549 ih->dport() = downstream_lms_.port_;
00550
00551 target_->recv(p);
00552 }