mip-reg.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * Copyright (C) 2000 by the University of Southern California
00004  * $Id: mip-reg.cc,v 1.10 2005/08/25 18:58:08 johnh Exp $
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License,
00008  * version 2, as published by the Free Software Foundation.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License along
00016  * with this program; if not, write to the Free Software Foundation, Inc.,
00017  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00018  *
00019  *
00020  * The copyright of this module includes the following
00021  * linking-with-specific-other-licenses addition:
00022  *
00023  * In addition, as a special exception, the copyright holders of
00024  * this module give you permission to combine (via static or
00025  * dynamic linking) this module with free software programs or
00026  * libraries that are released under the GNU LGPL and with code
00027  * included in the standard release of ns-2 under the Apache 2.0
00028  * license or under otherwise-compatible licenses with advertising
00029  * requirements (or modified versions of such code, with unchanged
00030  * license).  You may copy and distribute such a system following the
00031  * terms of the GNU GPL for this module and the licenses of the
00032  * other code concerned, provided that you include the source code of
00033  * that other code when and as the GNU GPL requires distribution of
00034  * source code.
00035  *
00036  * Note that people who make modified versions of this module
00037  * are not obligated to grant this special exception for their
00038  * modified versions; it is their choice whether to do so.  The GNU
00039  * General Public License gives permission to release a modified
00040  * version without this exception; this exception also makes it
00041  * possible to release a modified version which carries forward this
00042  * exception.
00043  *
00044  */
00045 
00046 // $Header: /nfs/jade/vint/CVSROOT/ns-2/mobile/mip-reg.cc,v 1.10 2005/08/25 18:58:08 johnh Exp $
00047 
00048 /*
00049  * Copyright (c) Sun Microsystems, Inc. 1998 All rights reserved.
00050  *
00051  * Redistribution and use in source and binary forms, with or without
00052  * modification, are permitted provided that the following conditions
00053  * are met:
00054  *
00055  * 1. Redistributions of source code must retain the above copyright
00056  *    notice, this list of conditions and the following disclaimer.
00057  *
00058  * 2. Redistributions in binary form must reproduce the above copyright
00059  *    notice, this list of conditions and the following disclaimer in the
00060  *    documentation and/or other materials provided with the distribution.
00061  *
00062  * 3. All advertising materials mentioning features or use of this software
00063  *    must display the following acknowledgement:
00064  *      This product includes software developed by Sun Microsystems, Inc.
00065  *
00066  * 4. The name of the Sun Microsystems, Inc nor may not be used to endorse or
00067  *      promote products derived from this software without specific prior
00068  *      written permission.
00069  *
00070  * SUN MICROSYSTEMS MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS
00071  * SOFTWARE FOR ANY PARTICULAR PURPOSE.  The software is provided "as is"
00072  * without express or implied warranty of any kind.
00073  *
00074  * These notices must be retained in any copies of any part of this software.
00075  */
00076 
00077 // #ident "@(#)mip-reg.cc  1.4     98/08/30 SMI"
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     //bind("shift_", &shift_);
00110     //bind("mask_", &mask_);
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       //if (miph->ha_ == (addr_ >> shift_ & mask_)) {
00129       if (miph->ha_ == (Address::instance().get_nodeaddr(addr()))){
00130         if (miph->ha_ == miph->coa_) { // back home
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         //iph->dst() = iph->dst() & ~(~(nsaddr_t)0 << shift_) | (miph->ha_ & mask_) << shift_;
00144         iph->daddr() = miph->ha_;
00145         iph->dport() = 0;
00146       }
00147       iph->saddr() = addr();
00148       iph->sport() = port();
00149       // by now should be back to normal route
00150       // if dst is the mobile
00151       // also initialise forward counter to 0. otherwise routing
00152       // agent is going to think pkt is looping and drop it!!
00153       ch->num_forwards() = 0;
00154       
00155       send(p, 0);
00156       break;
00157     case MIPT_REG_REPLY:
00158       //assert(miph->coa_ == (addr_ >> shift_ & mask_));
00159 
00160       assert(miph->coa_ == nodeaddr);
00161       tcl.evalf("%s get-link %d %d", name_, nodeaddr, miph->haddr_);
00162       //
00163       // XXX hacking mobileip. all this should go away
00164       // when mobileIP for sun-wired model is no longer reqd.
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       //iph->dst() = iph->dst() & ~(~(nsaddr_t)0 << shift_) |(miph->haddr_ & mask_) << shift_;
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       //tcl.evalf("%s get-link %d %d", name_, addr_ >> shift_ & mask_,miph->haddr_);
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     //h->coa_ = addr_ >> shift_ & mask_;
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       // if bcast pkt
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); // drop; may log in future code
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_", &reg_rtx_);
00275     bind("reg_lifetime_", &reglftm_);
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; // not pending
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 { // new ads
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           // The MHagent now should update the Mobilenode
00322           // about the changed coa_ : node updates its 
00323           // base-station to new coa_ accordingly.
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     // later: agent solicitation (now done!), start of simulation, ...
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     //iph->dst() = iph->dst() & ~(~(nsaddr_t)0 << shift_) | (coa_ & mask_) << shift_;
00416     iph->daddr() = coa_;
00417     iph->dport() = 0;
00418     hdr_mip *h = hdr_mip::access(p);
00419     //h->haddr_ = addr_ >> shift_ & mask_;
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     //h->haddr_ = addr_ >> shift_ & mask_;
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); // drop; may log in future code
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 }

Generated on Tue Mar 6 16:47:47 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6