📄 channel.cc
字号:
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* * Copyright (c) 1996 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory and the Daedalus * research group at UC Berkeley. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Contributed by Giao Nguyen, http://daedalus.cs.berkeley.edu/~gnguyen */#ifndef lintstatic const char rcsid[] = "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/mac/channel.cc,v 1.45 2005/02/03 20:15:00 haldar Exp $ (UCB)";#endif// Time interval for updating a position of a node in the X-List// (can be adjusted by the user, depending on the nodes mobility). /* VAL NAUMOV */#define XLIST_POSITION_UPDATE_INTERVAL 1.0 //seconds//#include "template.h"#include <float.h>#include "trace.h"#include "delay.h"#include "object.h"#include "packet.h"#include "mac.h"#include "channel.h"#include "lib/bsd-list.h"#include "phy.h"#include "wireless-phy.h"// #include "fso-wireless-phy.h" // RPI FSO Extensions#include "mobilenode.h"#include "ip.h"#include "dsr/hdr_sr.h"#include "gridkeeper.h"#include "tworayground.h"static class ChannelClass : public TclClass {public: ChannelClass() : TclClass("Channel") {} TclObject* create(int, const char*const*) { return (new Channel); }} class_channel;static class WirelessChannelClass : public TclClass {public: WirelessChannelClass() : TclClass("Channel/WirelessChannel") {} TclObject* create(int, const char*const*) { return (new WirelessChannel); }} class_Wireless_channel;// begin RPI FSO Extensionsstatic class FSOWirelessChannelClass : public TclClass {public: FSOWirelessChannelClass() : TclClass("Channel/FSOWirelessChannel") {} TclObject* create(int, const char*const*) { return (new FSOWirelessChannel); }} class_FSOWireless_channel;// end RPI FSO Extensions/* ================================================================== NS Initialization Functions =================================================================*/static int ChannelIndex = 0;Channel::Channel() : TclObject(){ index_ = ChannelIndex++; LIST_INIT(&ifhead_); bind_time("delay_", &delay_);}int Channel::command(int argc, const char*const* argv){ if (argc == 3) { TclObject *obj; if( (obj = TclObject::lookup(argv[2])) == 0) { fprintf(stderr, "%s lookup failed\n", argv[1]); return TCL_ERROR; } if (strcmp(argv[1], "trace-target") == 0) { trace_ = (Trace*) obj; return (TCL_OK); } else if(strcmp(argv[1], "addif") == 0) { ((Phy*) obj)->insertchnl(&ifhead_); ((Phy*) obj)->setchnl(this); return TCL_OK; } // add interface for grid_keeper_ /*else if(strncasecmp(argv[1], "grid_keeper", 5) == 0) { grid_keeper_ = (GridKeeper*)obj; return TCL_OK; }*/ } else if (argc == 2) { Tcl& tcl = Tcl::instance(); if (strcmp(argv[1], "trace-target") == 0) { tcl.resultf("%s", trace_->name()); return (TCL_OK); } else if(strcmp(argv[1], "id") == 0) { tcl.resultf("%d", index_); return TCL_OK; } } return TclObject::command(argc, argv);}void Channel::recv(Packet* p, Handler* h){ sendUp(p, (Phy*)h);}voidChannel::sendUp(Packet* p, Phy *tifp){ Scheduler &s = Scheduler::instance(); Phy *rifp = ifhead_.lh_first; Node *tnode = tifp->node(); Node *rnode = 0; Packet *newp; double propdelay = 0.0; struct hdr_cmn *hdr = HDR_CMN(p); hdr->direction() = hdr_cmn::UP; for( ; rifp; rifp = rifp->nextchnl()) { rnode = rifp->node(); if(rnode == tnode) continue; /* * Each node needs to get their own copy of this packet. * Since collisions occur at the receiver, we can have * two nodes canceling and freeing the *same* simulation * event. * */ newp = p->copy(); propdelay = get_pdelay(tnode, rnode); /* * Each node on the channel receives a copy of the * packet. The propagation delay determines exactly * when the receiver's interface detects the first * bit of this packet. */ s.schedule(rifp, newp, propdelay); } Packet::free(p);}double Channel::get_pdelay(Node* /*tnode*/, Node* /*rnode*/){ // Dummy function return delay_;}voidChannel::dump(void){ Phy *n; fprintf(stdout, "Network Interface List\n"); for(n = ifhead_.lh_first; n; n = n->nextchnl() ) n->dump(); fprintf(stdout, "--------------------------------------------------\n");}/* NoDupChannel------------------------------------------------------------ * NoDupChannel is currently acting the same as Channel but with one * important difference: it uses reference-copying of the packet, * thus, a lot of time is saved (e.g. for 49 senders and 1 receiver * overflowing mac802.3 and running for 10 seconds sim time, factors * of 60 and more of savings in actual running time have been * observed). * * DRAWBACKS: * * - No propagation model supported (uses constant prop delay for * all nodes), although it should be easy to change that. * - Macs should be EXTREMELY careful handling these reference * copies: essentially they all are expected not to modify them * in any way (including scheduling!) while reference counter is * positive. 802.3 seems to work with it, other macs may need * some changes. */struct ChannelDelayEvent : public Event {public: ChannelDelayEvent(Packet *p, Phy *txphy) : p_(p), txphy_(txphy) {}; Packet *p_; Phy *txphy_;};class NoDupChannel : public Channel, public Handler {public: void recv(Packet* p, Handler*); void handle(Event*);protected: int phy_counter_;private: void sendUp(Packet *p, Phy *txif);};void NoDupChannel::recv(Packet* p, Handler* h) { assert(hdr_cmn::access(p)->direction() == hdr_cmn::DOWN); // Delay this packet Scheduler &s = Scheduler::instance(); ChannelDelayEvent *de = new ChannelDelayEvent(p, (Phy *)h); s.schedule(this, de, delay_);}void NoDupChannel::handle(Event *e) { ChannelDelayEvent *cde = (ChannelDelayEvent *)e; sendUp(cde->p_, cde->txphy_); delete cde;}void NoDupChannel::sendUp(Packet *p, Phy *txif) { struct hdr_cmn *hdr = HDR_CMN(p); hdr->direction() = hdr_cmn::UP; for(Phy *rifp = ifhead_.lh_first; rifp; rifp = rifp->nextchnl()) { if(rifp == txif) continue; rifp->recv(p->refcopy(), 0); } Packet::free(p);}static class NoDupChannelClass : public TclClass {public: NoDupChannelClass() : TclClass("Channel/NoDup") {} TclObject* create(int, const char*const*) { return (new NoDupChannel); }} class_nodupchannel;// Wireless extensionsclass MobileNode;double WirelessChannel::highestAntennaZ_ = -1; // i.e., uninitializeddouble WirelessChannel::distCST_ = -1;WirelessChannel::WirelessChannel(void) : Channel(), numNodes_(0), xListHead_(NULL), sorted_(0) {}int WirelessChannel::command(int argc, const char*const* argv){ if (argc == 3) { TclObject *obj; if( (obj = TclObject::lookup(argv[2])) == 0) { fprintf(stderr, "%s lookup failed\n", argv[1]); return TCL_ERROR; } if (strcmp(argv[1], "add-node") == 0) { addNodeToList((MobileNode*) obj); return TCL_OK; } else if (strcmp(argv[1], "remove-node") == 0) { removeNodeFromList((MobileNode*) obj); return TCL_OK; } } return Channel::command(argc, argv);}voidWirelessChannel::sendUp(Packet* p, Phy *tifp){ Scheduler &s = Scheduler::instance(); Phy *rifp = ifhead_.lh_first; Node *tnode = tifp->node(); Node *rnode = 0; Packet *newp; double propdelay = 0.0; struct hdr_cmn *hdr = HDR_CMN(p); /* list-based improvement */ if(highestAntennaZ_ == -1) { fprintf(stdout, "channel.cc:sendUp - Calc highestAntennaZ_ and distCST_\n"); calcHighestAntennaZ(tifp); fprintf(stdout, "highestAntennaZ_ = %0.1f, distCST_ = %0.1f\n", highestAntennaZ_, distCST_); } hdr->direction() = hdr_cmn::UP; // still keep grid-keeper around ?? if (GridKeeper::instance()) { int i; GridKeeper* gk = GridKeeper::instance(); int size = gk->size_; MobileNode **outlist = new MobileNode *[size]; int out_index = gk->get_neighbors((MobileNode*)tnode, outlist); for (i=0; i < out_index; i ++) { newp = p->copy(); rnode = outlist[i]; propdelay = get_pdelay(tnode, rnode); rifp = (rnode->ifhead()).lh_first; for(; rifp; rifp = rifp->nextnode()){ if (rifp->channel() == this){ s.schedule(rifp, newp, propdelay); break; } } } delete [] outlist; } else { // use list-based improvement MobileNode *mtnode = (MobileNode *) tnode; MobileNode **affectedNodes;// **aN; int numAffectedNodes = -1, i; if(!sorted_){ sortLists(); } affectedNodes = getAffectedNodes(mtnode, distCST_ + /* safety */ 5, &numAffectedNodes); for (i=0; i < numAffectedNodes; i++) { rnode = affectedNodes[i]; if(rnode == tnode) continue; newp = p->copy(); propdelay = get_pdelay(tnode, rnode); rifp = (rnode->ifhead()).lh_first; for(; rifp; rifp = rifp->nextnode()){ s.schedule(rifp, newp, propdelay); } } delete [] affectedNodes; } Packet::free(p);}voidWirelessChannel::addNodeToList(MobileNode *mn){ MobileNode *tmp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -