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
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 #include <template.h>
00080 #include <mip.h>
00081 #include <random.h>
00082 #include <address.h>
00083 #include <mobilenode.h>
00084
00085 #define AGENT_ADS_SIZE 48
00086 #define REG_REQUEST_SIZE 52
00087
00088 int hdr_mip::offset_;
00089 static class MIPHeaderClass : public PacketHeaderClass {
00090 public:
00091 MIPHeaderClass() : PacketHeaderClass("PacketHeader/MIP",
00092 sizeof(hdr_mip)) {
00093 bind_offset(&hdr_mip::offset_);
00094 }
00095 } class_miphdr;
00096
00097 static class MIPBSAgentClass : public TclClass {
00098 public:
00099 MIPBSAgentClass() : TclClass("Agent/MIPBS") {}
00100 TclObject* create(int, const char*const*) {
00101 return (new MIPBSAgent());
00102 }
00103 } class_mipbsagent;
00104
00105 MIPBSAgent::MIPBSAgent() : Agent(PT_UDP), beacon_(1.0),
00106 bcast_target_(0), ragent_(0), timer_(this), adlftm_(~0)
00107 {
00108 bind("adSize_", &size_);
00109
00110
00111 bind("ad_lifetime_", &adlftm_);
00112 size_ = AGENT_ADS_SIZE;
00113 seqno_ = -1;
00114 }
00115
00116 void MIPBSAgent::recv(Packet* p, Handler *)
00117 {
00118 Tcl& tcl = Tcl::instance();
00119 const char *objname = NULL;
00120 NsObject *obj = NULL;
00121 hdr_mip *miph = hdr_mip::access(p);
00122 hdr_ip *iph = hdr_ip::access(p);
00123 hdr_cmn *ch = hdr_cmn::access(p);
00124 int nodeaddr = Address::instance().get_nodeaddr(addr());
00125
00126 switch (miph->type_) {
00127 case MIPT_REG_REQUEST:
00128
00129 if (miph->ha_ == (Address::instance().get_nodeaddr(addr()))){
00130 if (miph->ha_ == miph->coa_) {
00131 tcl.evalf("%s clear-reg %d", name_,
00132 miph->haddr_);
00133 }
00134 else {
00135 tcl.evalf("%s encap-route %d %d %lf", name_,
00136 miph->haddr_, miph->coa_,
00137 miph->lifetime_);
00138 }
00139 iph->dst() = iph->src();
00140 miph->type_ = MIPT_REG_REPLY;
00141 }
00142 else {
00143
00144 iph->daddr() = miph->ha_;
00145 iph->dport() = 0;
00146 }
00147 iph->saddr() = addr();
00148 iph->sport() = port();
00149
00150
00151
00152
00153 ch->num_forwards() = 0;
00154
00155 send(p, 0);
00156 break;
00157 case MIPT_REG_REPLY:
00158
00159
00160 assert(miph->coa_ == nodeaddr);
00161 tcl.evalf("%s get-link %d %d", name_, nodeaddr, miph->haddr_);
00162
00163
00164
00165
00166 obj = (NsObject*)tcl.lookup(objname = tcl.result());
00167 if (strlen(objname) == 0)
00168 objname = "XXX";
00169 tcl.evalf("%s decap-route %d %s %lf", name_, miph->haddr_,
00170 objname, miph->lifetime_);
00171
00172 iph->src() = iph->dst();
00173
00174 iph->daddr() = miph->haddr_;
00175 iph->dport() = 0;
00176 if (obj == NULL)
00177 obj = ragent_;
00178 obj->recv(p, (Handler*)0);
00179 break;
00180 case MIPT_SOL:
00181
00182 tcl.evalf("%s get-link %d %d",name_,nodeaddr,miph->haddr_);
00183 send_ads(miph->haddr_, (NsObject*)tcl.lookup(tcl.result()));
00184 Packet::free(p);
00185 break;
00186 default:
00187 Packet::free(p);
00188 break;
00189 }
00190 }
00191
00192 void MIPBSAgent::timeout(int )
00193 {
00194 send_ads();
00195 timer_.resched(beacon_);
00196 }
00197
00198 int MIPBSAgent::command(int argc, const char*const* argv)
00199 {
00200 if (argc == 3) {
00201 if (strcmp(argv[1], "beacon-period") == 0) {
00202 beacon_ = atof(argv[2]);
00203 timer_.resched(Random::uniform(0, beacon_));
00204 return TCL_OK;
00205 }
00206 if (strcmp(argv[1], "bcast-target") == 0) {
00207 bcast_target_ = (NsObject *)TclObject::lookup(argv[2]);
00208 return TCL_OK;
00209 }
00210 if (strcmp(argv[1], "ragent") == 0) {
00211 ragent_ = (NsObject *)TclObject::lookup(argv[2]);
00212 return TCL_OK;
00213 }
00214 }
00215 return (Agent::command(argc, argv));
00216 }
00217
00218 void MIPBSAgent::send_ads(int dst, NsObject *target)
00219 {
00220 Packet *p = allocpkt();
00221 hdr_mip *h = hdr_mip::access(p);
00222 hdr_ip *iph = hdr_ip::access(p);
00223 h->haddr_ = h->ha_ = -1;
00224
00225 h->coa_ = Address::instance().get_nodeaddr(addr());
00226 h->type_ = MIPT_ADS;
00227 h->lifetime_ = adlftm_;
00228 h->seqno_ = ++seqno_;
00229 if (dst != -1) {
00230 iph->daddr() = dst;
00231 iph->dport() = 0;
00232 }
00233 else {
00234
00235 sendOutBCastPkt(p);
00236 }
00237 if (target == NULL) {
00238 if (bcast_target_) bcast_target_->recv(p, (Handler*) 0);
00239 else if (target_) target_->recv(p, (Handler*) 0);
00240 else Packet::free(p);
00241 }
00242 else target->recv(p, (Handler*)0);
00243 }
00244
00245 void
00246 MIPBSAgent::sendOutBCastPkt(Packet *p)
00247 {
00248 hdr_ip *iph = hdr_ip::access(p);
00249 hdr_cmn *hdrc = hdr_cmn::access(p);
00250 hdrc->next_hop_ = IP_BROADCAST;
00251 hdrc->addr_type_ = NS_AF_INET;
00252 iph->daddr() = IP_BROADCAST;
00253 iph->dport() = 0;
00254 }
00255
00256 void AgtListTimer::expire(Event *) {
00257 a_->timeout(MIP_TIMER_AGTLIST);
00258 }
00259
00260 static class MIPMHAgentClass : public TclClass {
00261 public:
00262 MIPMHAgentClass() : TclClass("Agent/MIPMH") {}
00263 TclObject* create(int, const char*const*) {
00264 return (new MIPMHAgent());
00265 }
00266 } class_mipmhagent;
00267
00268 MIPMHAgent::MIPMHAgent() : Agent(PT_UDP), ha_(-1), coa_(-1),
00269 beacon_(1.0),bcast_target_(0),agts_(0),rtx_timer_(this),
00270 agtlist_timer_(this),reglftm_(~0),adlftm_(0.0), node_ (0)
00271 {
00272 bind("home_agent_", &ha_);
00273 bind("rreqSize_", &size_);
00274 bind("reg_rtx_", ®_rtx_);
00275 bind("reg_lifetime_", ®lftm_);
00276 size_ = REG_REQUEST_SIZE;
00277 seqno_ = -1;
00278 }
00279
00280 void MIPMHAgent::recv(Packet* p, Handler *)
00281 {
00282 Tcl& tcl = Tcl::instance();
00283 hdr_mip *miph = hdr_mip::access(p);
00284 switch (miph->type_) {
00285 case MIPT_REG_REPLY:
00286 if (miph->coa_ != coa_) break;
00287 tcl.evalf("%s update-reg %d", name_, coa_);
00288 if (rtx_timer_.status() == TIMER_PENDING)
00289 rtx_timer_.cancel();
00290 break;
00291 case MIPT_ADS:
00292 {
00293 AgentList **ppagts = &agts_, *ptr;
00294 while (*ppagts) {
00295 if ((*ppagts)->node_ == miph->coa_) break;
00296 ppagts = &(*ppagts)->next_;
00297 }
00298 if (*ppagts) {
00299 ptr = *ppagts;
00300 *ppagts = ptr->next_;
00301 ptr->expire_time_ = beacon_ +
00302 Scheduler::instance().clock();
00303 ptr->lifetime_ = miph->lifetime_;
00304 ptr->next_ = agts_;
00305 agts_ = ptr;
00306 if (coa_ == miph->coa_) {
00307 seqno_++;
00308 reg();
00309 }
00310 }
00311 else {
00312 ptr = new AgentList;
00313 ptr->node_ = miph->coa_;
00314 ptr->expire_time_ = beacon_ +
00315 Scheduler::instance().clock();
00316 ptr->lifetime_ = miph->lifetime_;
00317 ptr->next_ = agts_;
00318 agts_ = ptr;
00319 coa_ = miph->coa_;
00320
00321
00322
00323
00324 if(node_)
00325 node_->set_base_stn(coa_);
00326
00327 adlftm_ = miph->lifetime_;
00328 seqno_++;
00329 reg();
00330 }
00331 }
00332 break;
00333 default:
00334 break;
00335 }
00336 Packet::free(p);
00337 }
00338
00339 void MIPMHAgent::timeout(int tno)
00340 {
00341 switch (tno) {
00342 case MIP_TIMER_SIMPLE:
00343 reg();
00344 break;
00345 case MIP_TIMER_AGTLIST:
00346 {
00347 double now = Scheduler::instance().clock();
00348 AgentList **ppagts = &agts_, *ptr;
00349 int coalost = 0;
00350 while (*ppagts) {
00351 if ((*ppagts)->expire_time_ < now) {
00352 ptr = *ppagts;
00353 *ppagts = ptr->next_;
00354 if (ptr->node_ == coa_) {
00355 coa_ = -1;
00356 coalost = 1;
00357 }
00358 delete ptr;
00359 }
00360 else ppagts = &(*ppagts)->next_;
00361 }
00362 agtlist_timer_.resched(beacon_);
00363 if (coalost) {
00364 seqno_++;
00365 reg();
00366 }
00367 }
00368 break;
00369 default:
00370 break;
00371 }
00372 }
00373
00374 int MIPMHAgent::command(int argc, const char*const* argv)
00375 {
00376 if (argc == 3) {
00377 if (strcmp(argv[1], "beacon-period") == 0) {
00378 beacon_ = atof(argv[2]);
00379 timeout(MIP_TIMER_AGTLIST);
00380 agtlist_timer_.resched(beacon_);
00381 rtx_timer_.resched(Random::uniform(0, beacon_));
00382 return TCL_OK;
00383 }
00384 else if (strcmp(argv[1], "bcast-target") == 0) {
00385 bcast_target_ = (NsObject *)TclObject::lookup(argv[2]);
00386 return TCL_OK;
00387 }
00388 else if (strcmp (argv[1], "node") == 0) {
00389 node_ = (MobileNode*)TclObject::lookup(argv[2]);
00390 if (node_ == 0) {
00391 fprintf (stderr, "%s: %s lookup of %s failed\n", __FILE__, argv[1], argv[2]);
00392 return TCL_ERROR;
00393 }
00394 return TCL_OK;
00395 }
00396 }
00397
00398 return (Agent::command(argc, argv));
00399 }
00400
00401 void MIPMHAgent::reg()
00402 {
00403 rtx_timer_.resched(reg_rtx_);
00404 if (agts_ == 0) {
00405 send_sols();
00406 return;
00407 }
00408 if (coa_ < 0) {
00409 coa_ = agts_->node_;
00410 adlftm_ = agts_->lifetime_;
00411 }
00412 Tcl& tcl = Tcl::instance();
00413 Packet *p = allocpkt();
00414 hdr_ip *iph = hdr_ip::access(p);
00415
00416 iph->daddr() = coa_;
00417 iph->dport() = 0;
00418 hdr_mip *h = hdr_mip::access(p);
00419
00420 h->haddr_ = Address::instance().get_nodeaddr(addr());
00421 h->ha_ = ha_;
00422 h->coa_ = coa_;
00423 h->type_ = MIPT_REG_REQUEST;
00424 h->lifetime_ = MIN(reglftm_, adlftm_);
00425 h->seqno_ = seqno_;
00426 tcl.evalf("%s get-link %d %d", name_, h->haddr_, coa_);
00427 NsObject *target = (NsObject *)tcl.lookup(tcl.result());
00428 if (target != NULL)
00429 ((NsObject *)tcl.lookup(tcl.result()))->recv(p, (Handler*) 0);
00430 else
00431 send(p, 0);
00432 }
00433
00434 void MIPMHAgent::send_sols()
00435 {
00436 Packet *p = allocpkt();
00437 hdr_mip *h = hdr_mip::access(p);
00438 h->coa_ = -1;
00439
00440 h->haddr_ = Address::instance().get_nodeaddr(addr());
00441 h->ha_ = ha_;
00442 h->type_ = MIPT_SOL;
00443 h->lifetime_ = reglftm_;
00444 h->seqno_ = seqno_;
00445 sendOutBCastPkt(p);
00446 if (bcast_target_)
00447 bcast_target_->recv(p, (Handler*) 0);
00448 else if (target_)
00449 target_->recv(p, (Handler*) 0);
00450 else
00451 Packet::free(p);
00452 }
00453
00454
00455 void MIPMHAgent::sendOutBCastPkt(Packet *p)
00456 {
00457 hdr_ip *iph = hdr_ip::access(p);
00458 hdr_cmn *hdrc = hdr_cmn::access(p);
00459 hdrc->next_hop_ = IP_BROADCAST;
00460 hdrc->addr_type_ = NS_AF_INET;
00461 iph->daddr() = IP_BROADCAST;
00462 iph->dport() = 0;
00463 }