diff -Naur ns-2.30/mac/mac-802_11.cc ns-modified-2.30/mac/mac-802_11.cc --- ns-2.30/mac/mac-802_11.cc 2006-09-24 23:01:21.000000000 -0700 +++ ns-modified-2.30/mac/mac-802_11.cc 2007-05-14 13:09:12.000000000 -0700 @@ -1,1615 +1,2265 @@ -/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- - * - * Copyright (c) 1997 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. - * 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. - * - * $Header: /cvsroot/nsnam/ns-2/mac/mac-802_11.cc,v 1.51 2006/01/30 21:27:51 mweigle Exp $ - * - * Ported from CMU/Monarch's code, nov'98 -Padma. - * Contributions by: - * - Mike Holland - * - Sushmita - */ - -#include "delay.h" -#include "connector.h" -#include "packet.h" -#include "random.h" -#include "mobilenode.h" - -// #define DEBUG 99 - -#include "arp.h" -#include "ll.h" -#include "mac.h" -#include "mac-timers.h" -#include "mac-802_11.h" -#include "cmu-trace.h" - -// Added by Sushmita to support event tracing -#include "agent.h" -#include "basetrace.h" - - -/* our backoff timer doesn't count down in idle times during a - * frame-exchange sequence as the mac tx state isn't idle; genreally - * these idle times are less than DIFS and won't contribute to - * counting down the backoff period, but this could be a real - * problem if the frame exchange ends up in a timeout! in that case, - * i.e. if a timeout happens we've not been counting down for the - * duration of the timeout, and in fact begin counting down only - * DIFS after the timeout!! we lose the timeout interval - which - * will is not the REAL case! also, the backoff timer could be NULL - * and we could have a pending transmission which we could have - * sent! one could argue this is an implementation artifact which - * doesn't violate the spec.. and the timeout interval is expected - * to be less than DIFS .. which means its not a lot of time we - * lose.. anyway if everyone hears everyone the only reason a ack will - * be delayed will be due to a collision => the medium won't really be - * idle for a DIFS for this to really matter!! - */ - -inline void -Mac802_11::checkBackoffTimer() -{ - if(is_idle() && mhBackoff_.paused()) - mhBackoff_.resume(phymib_.getDIFS()); - if(! is_idle() && mhBackoff_.busy() && ! mhBackoff_.paused()) - mhBackoff_.pause(); -} - -inline void -Mac802_11::transmit(Packet *p, double timeout) -{ - tx_active_ = 1; - - if (EOTtarget_) { - assert (eotPacket_ == NULL); - eotPacket_ = p->copy(); - } - - /* - * If I'm transmitting without doing CS, such as when - * sending an ACK, any incoming packet will be "missed" - * and hence, must be discarded. - */ - if(rx_state_ != MAC_IDLE) { - //assert(dh->dh_fc.fc_type == MAC_Type_Control); - //assert(dh->dh_fc.fc_subtype == MAC_Subtype_ACK); - assert(pktRx_); - struct hdr_cmn *ch = HDR_CMN(pktRx_); - ch->error() = 1; /* force packet discard */ - } - - /* - * pass the packet on the "interface" which will in turn - * place the packet on the channel. - * - * NOTE: a handler is passed along so that the Network - * Interface can distinguish between incoming and - * outgoing packets. - */ - downtarget_->recv(p->copy(), this); - mhSend_.start(timeout); - mhIF_.start(txtime(p)); -} -inline void -Mac802_11::setRxState(MacState newState) -{ - rx_state_ = newState; - checkBackoffTimer(); -} - -inline void -Mac802_11::setTxState(MacState newState) -{ - tx_state_ = newState; - checkBackoffTimer(); -} - - -/* ====================================================================== - TCL Hooks for the simulator - ====================================================================== */ -static class Mac802_11Class : public TclClass { -public: - Mac802_11Class() : TclClass("Mac/802_11") {} - TclObject* create(int, const char*const*) { - return (new Mac802_11()); - -} -} class_mac802_11; - - -/* ====================================================================== - Mac and Phy MIB Class Functions - ====================================================================== */ - -PHY_MIB::PHY_MIB(Mac802_11 *parent) -{ - /* - * Bind the phy mib objects. Note that these will be bound - * to Mac/802_11 variables - */ - - parent->bind("CWMin_", &CWMin); - parent->bind("CWMax_", &CWMax); - parent->bind("SlotTime_", &SlotTime); - parent->bind("SIFS_", &SIFSTime); - parent->bind("PreambleLength_", &PreambleLength); - parent->bind("PLCPHeaderLength_", &PLCPHeaderLength); - parent->bind_bw("PLCPDataRate_", &PLCPDataRate); -} - -MAC_MIB::MAC_MIB(Mac802_11 *parent) -{ - /* - * Bind the phy mib objects. Note that these will be bound - * to Mac/802_11 variables - */ - - parent->bind("RTSThreshold_", &RTSThreshold); - parent->bind("ShortRetryLimit_", &ShortRetryLimit); - parent->bind("LongRetryLimit_", &LongRetryLimit); -} - -/* ====================================================================== - Mac Class Functions - ====================================================================== */ -Mac802_11::Mac802_11() : - Mac(), phymib_(this), macmib_(this), mhIF_(this), mhNav_(this), - mhRecv_(this), mhSend_(this), - mhDefer_(this), mhBackoff_(this) -{ - - nav_ = 0.0; - tx_state_ = rx_state_ = MAC_IDLE; - tx_active_ = 0; - eotPacket_ = NULL; - pktRTS_ = 0; - pktCTRL_ = 0; - cw_ = phymib_.getCWMin(); - ssrc_ = slrc_ = 0; - // Added by Sushmita - et_ = new EventTrace(); - - sta_seqno_ = 1; - cache_ = 0; - cache_node_count_ = 0; - - // chk if basic/data rates are set - // otherwise use bandwidth_ as default; - - Tcl& tcl = Tcl::instance(); - tcl.evalf("Mac/802_11 set basicRate_"); - if (strcmp(tcl.result(), "0") != 0) - bind_bw("basicRate_", &basicRate_); - else - basicRate_ = bandwidth_; - - tcl.evalf("Mac/802_11 set dataRate_"); - if (strcmp(tcl.result(), "0") != 0) - bind_bw("dataRate_", &dataRate_); - else - dataRate_ = bandwidth_; - - bind_bool("bugFix_timer_", &bugFix_timer_); - - EOTtarget_ = 0; - bss_id_ = IBSS_ID; - //printf("bssid in constructor %d\n",bss_id_); -} - - -int -Mac802_11::command(int argc, const char*const* argv) -{ - if (argc == 3) { - if (strcmp(argv[1], "eot-target") == 0) { - EOTtarget_ = (NsObject*) TclObject::lookup(argv[2]); - if (EOTtarget_ == 0) - return TCL_ERROR; - return TCL_OK; - } else if (strcmp(argv[1], "bss_id") == 0) { - bss_id_ = atoi(argv[2]); - return TCL_OK; - } else if (strcmp(argv[1], "log-target") == 0) { - logtarget_ = (NsObject*) TclObject::lookup(argv[2]); - if(logtarget_ == 0) - return TCL_ERROR; - return TCL_OK; - } else if(strcmp(argv[1], "nodes") == 0) { - if(cache_) return TCL_ERROR; - cache_node_count_ = atoi(argv[2]); - cache_ = new Host[cache_node_count_ + 1]; - assert(cache_); - bzero(cache_, sizeof(Host) * (cache_node_count_+1 )); - return TCL_OK; - } else if(strcmp(argv[1], "eventtrace") == 0) { - // command added to support event tracing by Sushmita - et_ = (EventTrace *)TclObject::lookup(argv[2]); - return (TCL_OK); - } - } - return Mac::command(argc, argv); -} - -// Added by Sushmita to support event tracing -void Mac802_11::trace_event(char *eventtype, Packet *p) -{ - if (et_ == NULL) return; - char *wrk = et_->buffer(); - char *nwrk = et_->nbuffer(); - - //char *src_nodeaddr = - // Address::instance().print_nodeaddr(iph->saddr()); - //char *dst_nodeaddr = - // Address::instance().print_nodeaddr(iph->daddr()); - - struct hdr_mac802_11* dh = HDR_MAC802_11(p); - - //struct hdr_cmn *ch = HDR_CMN(p); - - if(wrk != 0) { - sprintf(wrk, "E -t "TIME_FORMAT" %s %2x ", - et_->round(Scheduler::instance().clock()), - eventtype, - //ETHER_ADDR(dh->dh_sa) - ETHER_ADDR(dh->dh_ta) - ); - } - if(nwrk != 0) { - sprintf(nwrk, "E -t "TIME_FORMAT" %s %2x ", - et_->round(Scheduler::instance().clock()), - eventtype, - //ETHER_ADDR(dh->dh_sa) - ETHER_ADDR(dh->dh_ta) - ); - } - et_->dump(); -} - -/* ====================================================================== - Debugging Routines - ====================================================================== */ -void -Mac802_11::trace_pkt(Packet *p) -{ - struct hdr_cmn *ch = HDR_CMN(p); - struct hdr_mac802_11* dh = HDR_MAC802_11(p); - u_int16_t *t = (u_int16_t*) &dh->dh_fc; - - fprintf(stderr, "\t[ %2x %2x %2x %2x ] %x %s %d\n", - *t, dh->dh_duration, - ETHER_ADDR(dh->dh_ra), ETHER_ADDR(dh->dh_ta), - index_, packet_info.name(ch->ptype()), ch->size()); -} - -void -Mac802_11::dump(char *fname) -{ - fprintf(stderr, - "\n%s --- (INDEX: %d, time: %2.9f)\n", - fname, index_, Scheduler::instance().clock()); - - fprintf(stderr, - "\ttx_state_: %x, rx_state_: %x, nav: %2.9f, idle: %d\n", - tx_state_, rx_state_, nav_, is_idle()); - - fprintf(stderr, - "\tpktTx_: %lx, pktRx_: %lx, pktRTS_: %lx, pktCTRL_: %lx, callback: %lx\n", - (long) pktTx_, (long) pktRx_, (long) pktRTS_, - (long) pktCTRL_, (long) callback_); - - fprintf(stderr, - "\tDefer: %d, Backoff: %d (%d), Recv: %d, Timer: %d Nav: %d\n", - mhDefer_.busy(), mhBackoff_.busy(), mhBackoff_.paused(), - mhRecv_.busy(), mhSend_.busy(), mhNav_.busy()); - fprintf(stderr, - "\tBackoff Expire: %f\n", - mhBackoff_.expire()); -} - - -/* ====================================================================== - Packet Headers Routines - ====================================================================== */ -inline int -Mac802_11::hdr_dst(char* hdr, int dst ) -{ - struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr; - - if (dst > -2) { - if ((bss_id() == ((int)IBSS_ID)) || (addr() == bss_id())) { - /* if I'm AP (2nd condition above!), the dh_3a - * is already set by the MAC whilst fwding; if - * locally originated pkt, it might make sense - * to set the dh_3a to myself here! don't know - * how to distinguish between the two here - and - * the info is not critical to the dst station - * anyway! - */ - STORE4BYTE(&dst, (dh->dh_ra)); - } else { - /* in BSS mode, the AP forwards everything; - * therefore, the real dest goes in the 3rd - * address, and the AP address goes in the - * destination address - */ - STORE4BYTE(&bss_id_, (dh->dh_ra)); - STORE4BYTE(&dst, (dh->dh_3a)); - } - } - - - return (u_int32_t)ETHER_ADDR(dh->dh_ra); -} - -inline int -Mac802_11::hdr_src(char* hdr, int src ) -{ - struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr; - if(src > -2) - STORE4BYTE(&src, (dh->dh_ta)); - return ETHER_ADDR(dh->dh_ta); -} - -inline int -Mac802_11::hdr_type(char* hdr, u_int16_t type) -{ - struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr; - if(type) - STORE2BYTE(&type,(dh->dh_body)); - return GET2BYTE(dh->dh_body); -} - - -/* ====================================================================== - Misc Routines - ====================================================================== */ -inline int -Mac802_11::is_idle() -{ - if(rx_state_ != MAC_IDLE) - return 0; - if(tx_state_ != MAC_IDLE) - return 0; - if(nav_ > Scheduler::instance().clock()) - return 0; - - return 1; -} - -void -Mac802_11::discard(Packet *p, const char* why) -{ - hdr_mac802_11* mh = HDR_MAC802_11(p); - hdr_cmn *ch = HDR_CMN(p); - - /* if the rcvd pkt contains errors, a real MAC layer couldn't - necessarily read any data from it, so we just toss it now */ - if(ch->error() != 0) { - Packet::free(p); - return; - } - - switch(mh->dh_fc.fc_type) { - case MAC_Type_Management: - drop(p, why); - return; - case MAC_Type_Control: - switch(mh->dh_fc.fc_subtype) { - case MAC_Subtype_RTS: - if((u_int32_t)ETHER_ADDR(mh->dh_ta) == (u_int32_t)index_) { - drop(p, why); - return; - } - /* fall through - if necessary */ - case MAC_Subtype_CTS: - case MAC_Subtype_ACK: - if((u_int32_t)ETHER_ADDR(mh->dh_ra) == (u_int32_t)index_) { - drop(p, why); - return; - } - break; - default: - fprintf(stderr, "invalid MAC Control subtype\n"); - exit(1); - } - break; - case MAC_Type_Data: - switch(mh->dh_fc.fc_subtype) { - case MAC_Subtype_Data: - if((u_int32_t)ETHER_ADDR(mh->dh_ra) == \ - (u_int32_t)index_ || - (u_int32_t)ETHER_ADDR(mh->dh_ta) == \ - (u_int32_t)index_ || - (u_int32_t)ETHER_ADDR(mh->dh_ra) == MAC_BROADCAST) { - drop(p,why); - return; - } - break; - default: - fprintf(stderr, "invalid MAC Data subtype\n"); - exit(1); - } - break; - default: - fprintf(stderr, "invalid MAC type (%x)\n", mh->dh_fc.fc_type); - trace_pkt(p); - exit(1); - } - Packet::free(p); -} - -void -Mac802_11::capture(Packet *p) -{ - /* - * Update the NAV so that this does not screw - * up carrier sense. - */ - set_nav(usec(phymib_.getEIFS() + txtime(p))); - Packet::free(p); -} - -void -Mac802_11::collision(Packet *p) -{ - switch(rx_state_) { - case MAC_RECV: - setRxState(MAC_COLL); - /* fall through */ - case MAC_COLL: - assert(pktRx_); - assert(mhRecv_.busy()); - /* - * Since a collision has occurred, figure out - * which packet that caused the collision will - * "last" the longest. Make this packet, - * pktRx_ and reset the Recv Timer if necessary. - */ - if(txtime(p) > mhRecv_.expire()) { - mhRecv_.stop(); - discard(pktRx_, DROP_MAC_COLLISION); - pktRx_ = p; - mhRecv_.start(txtime(pktRx_)); - } - else { - discard(p, DROP_MAC_COLLISION); - } - break; - default: - assert(0); - } -} - -void -Mac802_11::tx_resume() -{ - double rTime; - assert(mhSend_.busy() == 0); - assert(mhDefer_.busy() == 0); - - if(pktCTRL_) { - /* - * Need to send a CTS or ACK. - */ - mhDefer_.start(phymib_.getSIFS()); - } else if(pktRTS_) { - if (mhBackoff_.busy() == 0) { - if (bugFix_timer_) { - mhBackoff_.start(cw_, is_idle(), - phymib_.getDIFS()); - } - else { - rTime = (Random::random() % cw_) * - phymib_.getSlotTime(); - mhDefer_.start( phymib_.getDIFS() + rTime); - } - } - } else if(pktTx_) { - if (mhBackoff_.busy() == 0) { - hdr_cmn *ch = HDR_CMN(pktTx_); - struct hdr_mac802_11 *mh = HDR_MAC802_11(pktTx_); - - if ((u_int32_t) ch->size() < macmib_.getRTSThreshold() - || (u_int32_t) ETHER_ADDR(mh->dh_ra) == MAC_BROADCAST) { - if (bugFix_timer_) { - mhBackoff_.start(cw_, is_idle(), - phymib_.getDIFS()); - } - else { - rTime = (Random::random() % cw_) - * phymib_.getSlotTime(); - mhDefer_.start(phymib_.getDIFS() + - rTime); - } - } else { - mhDefer_.start(phymib_.getSIFS()); - } - } - } else if(callback_) { - Handler *h = callback_; - callback_ = 0; - h->handle((Event*) 0); - } - setTxState(MAC_IDLE); -} - -void -Mac802_11::rx_resume() -{ - assert(pktRx_ == 0); - assert(mhRecv_.busy() == 0); - setRxState(MAC_IDLE); -} - - -/* ====================================================================== - Timer Handler Routines - ====================================================================== */ -void -Mac802_11::backoffHandler() -{ - if(pktCTRL_) { - assert(mhSend_.busy() || mhDefer_.busy()); - return; - } - - if(check_pktRTS() == 0) - return; - - if(check_pktTx() == 0) - return; -} - -void -Mac802_11::deferHandler() -{ - assert(pktCTRL_ || pktRTS_ || pktTx_); - - if(check_pktCTRL() == 0) - return; - assert(mhBackoff_.busy() == 0); - if(check_pktRTS() == 0) - return; - if(check_pktTx() == 0) - return; -} - -void -Mac802_11::navHandler() -{ - if(is_idle() && mhBackoff_.paused()) - mhBackoff_.resume(phymib_.getDIFS()); -} - -void -Mac802_11::recvHandler() -{ - recv_timer(); -} - -void -Mac802_11::sendHandler() -{ - send_timer(); -} - - -void -Mac802_11::txHandler() -{ - if (EOTtarget_) { - assert(eotPacket_); - EOTtarget_->recv(eotPacket_, (Handler *) 0); - eotPacket_ = NULL; - } - tx_active_ = 0; -} - - -/* ====================================================================== - The "real" Timer Handler Routines - ====================================================================== */ -void -Mac802_11::send_timer() -{ - switch(tx_state_) { - /* - * Sent a RTS, but did not receive a CTS. - */ - case MAC_RTS: - RetransmitRTS(); - break; - /* - * Sent a CTS, but did not receive a DATA packet. - */ - case MAC_CTS: - assert(pktCTRL_); - Packet::free(pktCTRL_); - pktCTRL_ = 0; - break; - /* - * Sent DATA, but did not receive an ACK packet. - */ - case MAC_SEND: - RetransmitDATA(); - break; - /* - * Sent an ACK, and now ready to resume transmission. - */ - case MAC_ACK: - assert(pktCTRL_); - Packet::free(pktCTRL_); - pktCTRL_ = 0; - break; - case MAC_IDLE: - break; - default: - assert(0); - } - tx_resume(); -} - - -/* ====================================================================== - Outgoing Packet Routines - ====================================================================== */ -int -Mac802_11::check_pktCTRL() -{ - struct hdr_mac802_11 *mh; - double timeout; - - if(pktCTRL_ == 0) - return -1; - if(tx_state_ == MAC_CTS || tx_state_ == MAC_ACK) - return -1; - - mh = HDR_MAC802_11(pktCTRL_); - - switch(mh->dh_fc.fc_subtype) { - /* - * If the medium is not IDLE, don't send the CTS. - */ - case MAC_Subtype_CTS: - if(!is_idle()) { - discard(pktCTRL_, DROP_MAC_BUSY); pktCTRL_ = 0; - return 0; - } - setTxState(MAC_CTS); - /* - * timeout: cts + data tx time calculated by - * adding cts tx time to the cts duration - * minus ack tx time -- this timeout is - * a guess since it is unspecified - * (note: mh->dh_duration == cf->cf_duration) - */ - timeout = txtime(phymib_.getCTSlen(), basicRate_) - + DSSS_MaxPropagationDelay // XXX - + sec(mh->dh_duration) - + DSSS_MaxPropagationDelay // XXX - - phymib_.getSIFS() - - txtime(phymib_.getACKlen(), basicRate_); - break; - /* - * IEEE 802.11 specs, section 9.2.8 - * Acknowledments are sent after an SIFS, without regard to - * the busy/idle state of the medium. - */ - case MAC_Subtype_ACK: - setTxState(MAC_ACK); - timeout = txtime(phymib_.getACKlen(), basicRate_); - break; - default: - fprintf(stderr, "check_pktCTRL:Invalid MAC Control subtype\n"); - exit(1); - } - transmit(pktCTRL_, timeout); - return 0; -} - -int -Mac802_11::check_pktRTS() -{ - struct hdr_mac802_11 *mh; - double timeout; - - assert(mhBackoff_.busy() == 0); - - if(pktRTS_ == 0) - return -1; - mh = HDR_MAC802_11(pktRTS_); - - switch(mh->dh_fc.fc_subtype) { - case MAC_Subtype_RTS: - if(! is_idle()) { - inc_cw(); - mhBackoff_.start(cw_, is_idle()); - return 0; - } - setTxState(MAC_RTS); - timeout = txtime(phymib_.getRTSlen(), basicRate_) - + DSSS_MaxPropagationDelay // XXX - + phymib_.getSIFS() - + txtime(phymib_.getCTSlen(), basicRate_) - + DSSS_MaxPropagationDelay; - break; - default: - fprintf(stderr, "check_pktRTS:Invalid MAC Control subtype\n"); - exit(1); - } - transmit(pktRTS_, timeout); - - - return 0; -} - -int -Mac802_11::check_pktTx() -{ - struct hdr_mac802_11 *mh; - double timeout; - - assert(mhBackoff_.busy() == 0); - - if(pktTx_ == 0) - return -1; - - mh = HDR_MAC802_11(pktTx_); - - switch(mh->dh_fc.fc_subtype) { - case MAC_Subtype_Data: - if(! is_idle()) { - sendRTS(ETHER_ADDR(mh->dh_ra)); - inc_cw(); - mhBackoff_.start(cw_, is_idle()); - return 0; - } - setTxState(MAC_SEND); - if((u_int32_t)ETHER_ADDR(mh->dh_ra) != MAC_BROADCAST) - timeout = txtime(pktTx_) - + DSSS_MaxPropagationDelay // XXX - + phymib_.getSIFS() - + txtime(phymib_.getACKlen(), basicRate_) - + DSSS_MaxPropagationDelay; // XXX - else - timeout = txtime(pktTx_); - break; - default: - fprintf(stderr, "check_pktTx:Invalid MAC Control subtype\n"); - exit(1); - } - transmit(pktTx_, timeout); - return 0; -} -/* - * Low-level transmit functions that actually place the packet onto - * the channel. - */ -void -Mac802_11::sendRTS(int dst) -{ - Packet *p = Packet::alloc(); - hdr_cmn* ch = HDR_CMN(p); - struct rts_frame *rf = (struct rts_frame*)p->access(hdr_mac::offset_); - - assert(pktTx_); - assert(pktRTS_ == 0); - - /* - * If the size of the packet is larger than the - * RTSThreshold, then perform the RTS/CTS exchange. - */ - if( (u_int32_t) HDR_CMN(pktTx_)->size() < macmib_.getRTSThreshold() || - (u_int32_t) dst == MAC_BROADCAST) { - Packet::free(p); - return; - } - - ch->uid() = 0; - ch->ptype() = PT_MAC; - ch->size() = phymib_.getRTSlen(); - ch->iface() = -2; - ch->error() = 0; - - bzero(rf, MAC_HDR_LEN); - - rf->rf_fc.fc_protocol_version = MAC_ProtocolVersion; - rf->rf_fc.fc_type = MAC_Type_Control; - rf->rf_fc.fc_subtype = MAC_Subtype_RTS; - rf->rf_fc.fc_to_ds = 0; - rf->rf_fc.fc_from_ds = 0; - rf->rf_fc.fc_more_frag = 0; - rf->rf_fc.fc_retry = 0; - rf->rf_fc.fc_pwr_mgt = 0; - rf->rf_fc.fc_more_data = 0; - rf->rf_fc.fc_wep = 0; - rf->rf_fc.fc_order = 0; - - //rf->rf_duration = RTS_DURATION(pktTx_); - STORE4BYTE(&dst, (rf->rf_ra)); - - /* store rts tx time */ - ch->txtime() = txtime(ch->size(), basicRate_); - - STORE4BYTE(&index_, (rf->rf_ta)); - - /* calculate rts duration field */ - rf->rf_duration = usec(phymib_.getSIFS() - + txtime(phymib_.getCTSlen(), basicRate_) - + phymib_.getSIFS() - + txtime(pktTx_) - + phymib_.getSIFS() - + txtime(phymib_.getACKlen(), basicRate_)); - pktRTS_ = p; -} - -void -Mac802_11::sendCTS(int dst, double rts_duration) -{ - Packet *p = Packet::alloc(); - hdr_cmn* ch = HDR_CMN(p); - struct cts_frame *cf = (struct cts_frame*)p->access(hdr_mac::offset_); - - assert(pktCTRL_ == 0); - - ch->uid() = 0; - ch->ptype() = PT_MAC; - ch->size() = phymib_.getCTSlen(); - - - ch->iface() = -2; - ch->error() = 0; - //ch->direction() = hdr_cmn::DOWN; - bzero(cf, MAC_HDR_LEN); - - cf->cf_fc.fc_protocol_version = MAC_ProtocolVersion; - cf->cf_fc.fc_type = MAC_Type_Control; - cf->cf_fc.fc_subtype = MAC_Subtype_CTS; - cf->cf_fc.fc_to_ds = 0; - cf->cf_fc.fc_from_ds = 0; - cf->cf_fc.fc_more_frag = 0; - cf->cf_fc.fc_retry = 0; - cf->cf_fc.fc_pwr_mgt = 0; - cf->cf_fc.fc_more_data = 0; - cf->cf_fc.fc_wep = 0; - cf->cf_fc.fc_order = 0; - - //cf->cf_duration = CTS_DURATION(rts_duration); - STORE4BYTE(&dst, (cf->cf_ra)); - - /* store cts tx time */ - ch->txtime() = txtime(ch->size(), basicRate_); - - /* calculate cts duration */ - cf->cf_duration = usec(sec(rts_duration) - - phymib_.getSIFS() - - txtime(phymib_.getCTSlen(), basicRate_)); - - - - pktCTRL_ = p; - -} - -void -Mac802_11::sendACK(int dst) -{ - Packet *p = Packet::alloc(); - hdr_cmn* ch = HDR_CMN(p); - struct ack_frame *af = (struct ack_frame*)p->access(hdr_mac::offset_); - - assert(pktCTRL_ == 0); - - ch->uid() = 0; - ch->ptype() = PT_MAC; - // CHANGE WRT Mike's code - ch->size() = phymib_.getACKlen(); - ch->iface() = -2; - ch->error() = 0; - - bzero(af, MAC_HDR_LEN); - - af->af_fc.fc_protocol_version = MAC_ProtocolVersion; - af->af_fc.fc_type = MAC_Type_Control; - af->af_fc.fc_subtype = MAC_Subtype_ACK; - af->af_fc.fc_to_ds = 0; - af->af_fc.fc_from_ds = 0; - af->af_fc.fc_more_frag = 0; - af->af_fc.fc_retry = 0; - af->af_fc.fc_pwr_mgt = 0; - af->af_fc.fc_more_data = 0; - af->af_fc.fc_wep = 0; - af->af_fc.fc_order = 0; - - //af->af_duration = ACK_DURATION(); - STORE4BYTE(&dst, (af->af_ra)); - - /* store ack tx time */ - ch->txtime() = txtime(ch->size(), basicRate_); - - /* calculate ack duration */ - af->af_duration = 0; - - pktCTRL_ = p; -} - -void -Mac802_11::sendDATA(Packet *p) -{ - hdr_cmn* ch = HDR_CMN(p); - struct hdr_mac802_11* dh = HDR_MAC802_11(p); - - assert(pktTx_ == 0); - - /* - * Update the MAC header - */ - ch->size() += phymib_.getHdrLen11(); - - dh->dh_fc.fc_protocol_version = MAC_ProtocolVersion; - dh->dh_fc.fc_type = MAC_Type_Data; - dh->dh_fc.fc_subtype = MAC_Subtype_Data; - - dh->dh_fc.fc_to_ds = 0; - dh->dh_fc.fc_from_ds = 0; - dh->dh_fc.fc_more_frag = 0; - dh->dh_fc.fc_retry = 0; - dh->dh_fc.fc_pwr_mgt = 0; - dh->dh_fc.fc_more_data = 0; - dh->dh_fc.fc_wep = 0; - dh->dh_fc.fc_order = 0; - - /* store data tx time */ - ch->txtime() = txtime(ch->size(), dataRate_); - - if((u_int32_t)ETHER_ADDR(dh->dh_ra) != MAC_BROADCAST) { - /* store data tx time for unicast packets */ - ch->txtime() = txtime(ch->size(), dataRate_); - - dh->dh_duration = usec(txtime(phymib_.getACKlen(), basicRate_) - + phymib_.getSIFS()); - - - - } else { - /* store data tx time for broadcast packets (see 9.6) */ - ch->txtime() = txtime(ch->size(), basicRate_); - - dh->dh_duration = 0; - } - pktTx_ = p; -} - -/* ====================================================================== - Retransmission Routines - ====================================================================== */ -void -Mac802_11::RetransmitRTS() -{ - assert(pktTx_); - assert(pktRTS_); - assert(mhBackoff_.busy() == 0); - macmib_.RTSFailureCount++; - - - ssrc_ += 1; // STA Short Retry Count - - if(ssrc_ >= macmib_.getShortRetryLimit()) { - discard(pktRTS_, DROP_MAC_RETRY_COUNT_EXCEEDED); pktRTS_ = 0; - /* tell the callback the send operation failed - before discarding the packet */ - hdr_cmn *ch = HDR_CMN(pktTx_); - if (ch->xmit_failure_) { - /* - * Need to remove the MAC header so that - * re-cycled packets don't keep getting - * bigger. - */ - ch->size() -= phymib_.getHdrLen11(); - ch->xmit_reason_ = XMIT_REASON_RTS; - ch->xmit_failure_(pktTx_->copy(), - ch->xmit_failure_data_); - } - discard(pktTx_, DROP_MAC_RETRY_COUNT_EXCEEDED); - pktTx_ = 0; - ssrc_ = 0; - rst_cw(); - } else { - struct rts_frame *rf; - rf = (struct rts_frame*)pktRTS_->access(hdr_mac::offset_); - rf->rf_fc.fc_retry = 1; - - inc_cw(); - mhBackoff_.start(cw_, is_idle()); - } -} - -void -Mac802_11::RetransmitDATA() -{ - struct hdr_cmn *ch; - struct hdr_mac802_11 *mh; - u_int32_t *rcount, thresh; - assert(mhBackoff_.busy() == 0); - - assert(pktTx_); - assert(pktRTS_ == 0); - - ch = HDR_CMN(pktTx_); - mh = HDR_MAC802_11(pktTx_); - - /* - * Broadcast packets don't get ACKed and therefore - * are never retransmitted. - */ - if((u_int32_t)ETHER_ADDR(mh->dh_ra) == MAC_BROADCAST) { - Packet::free(pktTx_); - pktTx_ = 0; - - /* - * Backoff at end of TX. - */ - rst_cw(); - mhBackoff_.start(cw_, is_idle()); - - return; - } - - macmib_.ACKFailureCount++; - - if((u_int32_t) ch->size() <= macmib_.getRTSThreshold()) { - rcount = &ssrc_; - thresh = macmib_.getShortRetryLimit(); - } else { - rcount = &slrc_; - thresh = macmib_.getLongRetryLimit(); - } - - (*rcount)++; - - if(*rcount >= thresh) { - /* IEEE Spec section 9.2.3.5 says this should be greater than - or equal */ - macmib_.FailedCount++; - /* tell the callback the send operation failed - before discarding the packet */ - hdr_cmn *ch = HDR_CMN(pktTx_); - if (ch->xmit_failure_) { - ch->size() -= phymib_.getHdrLen11(); - ch->xmit_reason_ = XMIT_REASON_ACK; - ch->xmit_failure_(pktTx_->copy(), - ch->xmit_failure_data_); - } - - discard(pktTx_, DROP_MAC_RETRY_COUNT_EXCEEDED); - pktTx_ = 0; - *rcount = 0; - rst_cw(); - } - else { - struct hdr_mac802_11 *dh; - dh = HDR_MAC802_11(pktTx_); - dh->dh_fc.fc_retry = 1; - - - sendRTS(ETHER_ADDR(mh->dh_ra)); - inc_cw(); - mhBackoff_.start(cw_, is_idle()); - } -} - -/* ====================================================================== - Incoming Packet Routines - ====================================================================== */ -void -Mac802_11::send(Packet *p, Handler *h) -{ - double rTime; - struct hdr_mac802_11* dh = HDR_MAC802_11(p); - - EnergyModel *em = netif_->node()->energy_model(); - if (em && em->sleep()) { - em->set_node_sleep(0); - em->set_node_state(EnergyModel::INROUTE); - } - - callback_ = h; - sendDATA(p); - sendRTS(ETHER_ADDR(dh->dh_ra)); - - /* - * Assign the data packet a sequence number. - */ - dh->dh_scontrol = sta_seqno_++; - - /* - * If the medium is IDLE, we must wait for a DIFS - * Space before transmitting. - */ - if(mhBackoff_.busy() == 0) { - if(is_idle()) { - if (mhDefer_.busy() == 0) { - /* - * If we are already deferring, there is no - * need to reset the Defer timer. - */ - if (bugFix_timer_) { - mhBackoff_.start(cw_, is_idle(), - phymib_.getDIFS()); - } - else { - rTime = (Random::random() % cw_) - * (phymib_.getSlotTime()); - mhDefer_.start(phymib_.getDIFS() + - rTime); - } - } - } else { - /* - * If the medium is NOT IDLE, then we start - * the backoff timer. - */ - mhBackoff_.start(cw_, is_idle()); - } - } -} - -void -Mac802_11::recv(Packet *p, Handler *h) -{ - struct hdr_cmn *hdr = HDR_CMN(p); - /* - * Sanity Check - */ - assert(initialized()); - - /* - * Handle outgoing packets. - */ - if(hdr->direction() == hdr_cmn::DOWN) { - send(p, h); - return; - } - /* - * Handle incoming packets. - * - * We just received the 1st bit of a packet on the network - * interface. - * - */ - - /* - * If the interface is currently in transmit mode, then - * it probably won't even see this packet. However, the - * "air" around me is BUSY so I need to let the packet - * proceed. Just set the error flag in the common header - * to that the packet gets thrown away. - */ - if(tx_active_ && hdr->error() == 0) { - hdr->error() = 1; - } - - if(rx_state_ == MAC_IDLE) { - setRxState(MAC_RECV); - pktRx_ = p; - /* - * Schedule the reception of this packet, in - * txtime seconds. - */ - mhRecv_.start(txtime(p)); - } else { - /* - * If the power of the incoming packet is smaller than the - * power of the packet currently being received by at least - * the capture threshold, then we ignore the new packet. - */ - if(pktRx_->txinfo_.RxPr / p->txinfo_.RxPr >= p->txinfo_.CPThresh) { - capture(p); - } else { - collision(p); - } - } -} - -void -Mac802_11::recv_timer() -{ - u_int32_t src; - hdr_cmn *ch = HDR_CMN(pktRx_); - hdr_mac802_11 *mh = HDR_MAC802_11(pktRx_); - u_int32_t dst = ETHER_ADDR(mh->dh_ra); - - u_int8_t type = mh->dh_fc.fc_type; - u_int8_t subtype = mh->dh_fc.fc_subtype; - - assert(pktRx_); - assert(rx_state_ == MAC_RECV || rx_state_ == MAC_COLL); - - /* - * If the interface is in TRANSMIT mode when this packet - * "arrives", then I would never have seen it and should - * do a silent discard without adjusting the NAV. - */ - if(tx_active_) { - Packet::free(pktRx_); - goto done; - } - - /* - * Handle collisions. - */ - if(rx_state_ == MAC_COLL) { - discard(pktRx_, DROP_MAC_COLLISION); - set_nav(usec(phymib_.getEIFS())); - goto done; - } - - /* - * Check to see if this packet was received with enough - * bit errors that the current level of FEC still could not - * fix all of the problems - ie; after FEC, the checksum still - * failed. - */ - if( ch->error() ) { - Packet::free(pktRx_); - set_nav(usec(phymib_.getEIFS())); - goto done; - } - - /* - * IEEE 802.11 specs, section 9.2.5.6 - * - update the NAV (Network Allocation Vector) - */ - if(dst != (u_int32_t)index_) { - set_nav(mh->dh_duration); - } - - /* tap out - */ - if (tap_ && type == MAC_Type_Data && - MAC_Subtype_Data == subtype ) - tap_->tap(pktRx_); - /* - * Adaptive Fidelity Algorithm Support - neighborhood infomation - * collection - * - * Hacking: Before filter the packet, log the neighbor node - * I can hear the packet, the src is my neighbor - */ - if (netif_->node()->energy_model() && - netif_->node()->energy_model()->adaptivefidelity()) { - src = ETHER_ADDR(mh->dh_ta); - netif_->node()->energy_model()->add_neighbor(src); - } - /* - * Address Filtering - */ - if(dst != (u_int32_t)index_ && dst != MAC_BROADCAST) { - /* - * We don't want to log this event, so we just free - * the packet instead of calling the drop routine. - */ - discard(pktRx_, "---"); - goto done; - } - - switch(type) { - - case MAC_Type_Management: - discard(pktRx_, DROP_MAC_PACKET_ERROR); - goto done; - case MAC_Type_Control: - switch(subtype) { - case MAC_Subtype_RTS: - recvRTS(pktRx_); - break; - case MAC_Subtype_CTS: - recvCTS(pktRx_); - break; - case MAC_Subtype_ACK: - recvACK(pktRx_); - break; - default: - fprintf(stderr,"recvTimer1:Invalid MAC Control Subtype %x\n", - subtype); - exit(1); - } - break; - case MAC_Type_Data: - switch(subtype) { - case MAC_Subtype_Data: - recvDATA(pktRx_); - break; - default: - fprintf(stderr, "recv_timer2:Invalid MAC Data Subtype %x\n", - subtype); - exit(1); - } - break; - default: - fprintf(stderr, "recv_timer3:Invalid MAC Type %x\n", subtype); - exit(1); - } - done: - pktRx_ = 0; - rx_resume(); -} - - -void -Mac802_11::recvRTS(Packet *p) -{ - struct rts_frame *rf = (struct rts_frame*)p->access(hdr_mac::offset_); - - if(tx_state_ != MAC_IDLE) { - discard(p, DROP_MAC_BUSY); - return; - } - - /* - * If I'm responding to someone else, discard this RTS. - */ - if(pktCTRL_) { - discard(p, DROP_MAC_BUSY); - return; - } - - sendCTS(ETHER_ADDR(rf->rf_ta), rf->rf_duration); - - /* - * Stop deferring - will be reset in tx_resume(). - */ - if(mhDefer_.busy()) mhDefer_.stop(); - - tx_resume(); - - mac_log(p); -} - -/* - * txtime() - pluck the precomputed tx time from the packet header - */ -double -Mac802_11::txtime(Packet *p) -{ - struct hdr_cmn *ch = HDR_CMN(p); - double t = ch->txtime(); - if (t < 0.0) { - drop(p, "XXX"); - exit(1); - } - return t; -} - - -/* - * txtime() - calculate tx time for packet of size "psz" bytes - * at rate "drt" bps - */ -double -Mac802_11::txtime(double psz, double drt) -{ - double dsz = psz - phymib_.getPLCPhdrLen(); - int plcp_hdr = phymib_.getPLCPhdrLen() << 3; - int datalen = (int)dsz << 3; - double t = (((double)plcp_hdr)/phymib_.getPLCPDataRate()) - + (((double)datalen)/drt); - return(t); -} - - - -void -Mac802_11::recvCTS(Packet *p) -{ - if(tx_state_ != MAC_RTS) { - discard(p, DROP_MAC_INVALID_STATE); - return; - } - - assert(pktRTS_); - Packet::free(pktRTS_); pktRTS_ = 0; - - assert(pktTx_); - mhSend_.stop(); - - /* - * The successful reception of this CTS packet implies - * that our RTS was successful. - * According to the IEEE spec 9.2.5.3, you must - * reset the ssrc_, but not the congestion window. - */ - ssrc_ = 0; - tx_resume(); - - mac_log(p); -} - -void -Mac802_11::recvDATA(Packet *p) -{ - struct hdr_mac802_11 *dh = HDR_MAC802_11(p); - u_int32_t dst, src, size; - struct hdr_cmn *ch = HDR_CMN(p); - - dst = ETHER_ADDR(dh->dh_ra); - src = ETHER_ADDR(dh->dh_ta); - size = ch->size(); - /* - * Adjust the MAC packet size - ie; strip - * off the mac header - */ - ch->size() -= phymib_.getHdrLen11(); - ch->num_forwards() += 1; - - /* - * If we sent a CTS, clean up... - */ - if(dst != MAC_BROADCAST) { - if(size >= macmib_.getRTSThreshold()) { - if (tx_state_ == MAC_CTS) { - assert(pktCTRL_); - Packet::free(pktCTRL_); pktCTRL_ = 0; - mhSend_.stop(); - /* - * Our CTS got through. - */ - } else { - discard(p, DROP_MAC_BUSY); - return; - } - sendACK(src); - tx_resume(); - } else { - /* - * We did not send a CTS and there's no - * room to buffer an ACK. - */ - if(pktCTRL_) { - discard(p, DROP_MAC_BUSY); - return; - } - sendACK(src); - if(mhSend_.busy() == 0) - tx_resume(); - } - } - - /* ============================================================ - Make/update an entry in our sequence number cache. - ============================================================ */ - - /* Changed by Debojyoti Dutta. This upper loop of if{}else was - suggested by Joerg Diederich . - Changed on 19th Oct'2000 */ - - if(dst != MAC_BROADCAST) { - if (src < (u_int32_t) cache_node_count_) { - Host *h = &cache_[src]; - - if(h->seqno && h->seqno == dh->dh_scontrol) { - discard(p, DROP_MAC_DUPLICATE); - return; - } - h->seqno = dh->dh_scontrol; - } else { - static int count = 0; - if (++count <= 10) { - printf ("MAC_802_11: accessing MAC cache_ array out of range (src %u, dst %u, size %d)!\n", src, dst, cache_node_count_); - if (count == 10) - printf ("[suppressing additional MAC cache_ warnings]\n"); - }; - }; - } - - /* - * Pass the packet up to the link-layer. - * XXX - we could schedule an event to account - * for this processing delay. - */ - - /* in BSS mode, if a station receives a packet via - * the AP, and higher layers are interested in looking - * at the src address, we might need to put it at - * the right place - lest the higher layers end up - * believing the AP address to be the src addr! a quick - * grep didn't turn up any higher layers interested in - * the src addr though! - * anyway, here if I'm the AP and the destination - * address (in dh_3a) isn't me, then we have to fwd - * the packet; we pick the real destination and set - * set it up for the LL; we save the real src into - * the dh_3a field for the 'interested in the info' - * receiver; we finally push the packet towards the - * LL to be added back to my queue - accomplish this - * by reversing the direction!*/ - - if ((bss_id() == addr()) && ((u_int32_t)ETHER_ADDR(dh->dh_ra)!= MAC_BROADCAST)&& ((u_int32_t)ETHER_ADDR(dh->dh_3a) != ((u_int32_t)addr()))) { - struct hdr_cmn *ch = HDR_CMN(p); - u_int32_t dst = ETHER_ADDR(dh->dh_3a); - u_int32_t src = ETHER_ADDR(dh->dh_ta); - /* if it is a broadcast pkt then send a copy up - * my stack also - */ - if (dst == MAC_BROADCAST) { - uptarget_->recv(p->copy(), (Handler*) 0); - } - - ch->next_hop() = dst; - STORE4BYTE(&src, (dh->dh_3a)); - ch->addr_type() = NS_AF_ILINK; - ch->direction() = hdr_cmn::DOWN; - } - - uptarget_->recv(p, (Handler*) 0); -} - - -void -Mac802_11::recvACK(Packet *p) -{ - if(tx_state_ != MAC_SEND) { - discard(p, DROP_MAC_INVALID_STATE); - return; - } - assert(pktTx_); - - mhSend_.stop(); - - /* - * The successful reception of this ACK packet implies - * that our DATA transmission was successful. Hence, - * we can reset the Short/Long Retry Count and the CW. - * - * need to check the size of the packet we sent that's being - * ACK'd, not the size of the ACK packet. - */ - if((u_int32_t) HDR_CMN(pktTx_)->size() <= macmib_.getRTSThreshold()) - ssrc_ = 0; - else - slrc_ = 0; - rst_cw(); - Packet::free(pktTx_); - pktTx_ = 0; - - /* - * Backoff before sending again. - */ - assert(mhBackoff_.busy() == 0); - mhBackoff_.start(cw_, is_idle()); - - tx_resume(); - - mac_log(p); -} +/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- + * + * Copyright (c) 1997 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. + * 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. + * + * $Header: /cvsroot/nsnam/ns-2/mac/mac-802_11.cc,v 1.51 2006/01/30 21:27:51 mweigle Exp $ + * + * Ported from CMU/Monarch's code, nov'98 -Padma. + * Contributions by: + * - Mike Holland + * - Sushmita + */ + +#include "delay.h" +#include "connector.h" +#include "packet.h" +#include "random.h" +#include "mobilenode.h" + +// #define DEBUG 99 + +#include "arp.h" +#include "ll.h" +#include "mac.h" +#include "mac-timers.h" +#include "mac-802_11.h" +#include "cmu-trace.h" + +// Added by Sushmita to support event tracing +#include "agent.h" +#include "basetrace.h" + + +/* our backoff timer doesn't count down in idle times during a + * frame-exchange sequence as the mac tx state isn't idle; genreally + * these idle times are less than DIFS and won't contribute to + * counting down the backoff period, but this could be a real + * problem if the frame exchange ends up in a timeout! in that case, + * i.e. if a timeout happens we've not been counting down for the + * duration of the timeout, and in fact begin counting down only + * DIFS after the timeout!! we lose the timeout interval - which + * will is not the REAL case! also, the backoff timer could be NULL + * and we could have a pending transmission which we could have + * sent! one could argue this is an implementation artifact which + * doesn't violate the spec.. and the timeout interval is expected + * to be less than DIFS .. which means its not a lot of time we + * lose.. anyway if everyone hears everyone the only reason a ack will + * be delayed will be due to a collision => the medium won't really be + * idle for a DIFS for this to really matter!! + */ + +inline void +Mac802_11::checkBackoffTimer() +{ + if(is_idle() && mhBackoff_.paused()) + mhBackoff_.resume(phymib_.getDIFS()); + if(! is_idle() && mhBackoff_.busy() && ! mhBackoff_.paused()) + mhBackoff_.pause(); +} + +inline void +Mac802_11::transmit(Packet *p, double timeout) +{ + tx_active_ = 1; + + if (EOTtarget_) { + assert (eotPacket_ == NULL); + eotPacket_ = p->copy(); + } + + /* + * If I'm transmitting without doing CS, such as when + * sending an ACK, any incoming packet will be "missed" + * and hence, must be discarded. + */ + if(rx_state_ != MAC_IDLE) { + //assert(dh->dh_fc.fc_type == MAC_Type_Control); + //assert(dh->dh_fc.fc_subtype == MAC_Subtype_ACK); + assert(pktRx_); + struct hdr_cmn *ch = HDR_CMN(pktRx_); + ch->error() = 1; /* force packet discard */ + } + + /* + * pass the packet on the "interface" which will in turn + * place the packet on the channel. + * + * NOTE: a handler is passed along so that the Network + * Interface can distinguish between incoming and + * outgoing packets. + */ + downtarget_->recv(p->copy(), this); + mhSend_.start(timeout); + mhIF_.start(txtime(p)); +} +inline void +Mac802_11::setRxState(MacState newState) +{ + rx_state_ = newState; + checkBackoffTimer(); +} + +inline void +Mac802_11::setTxState(MacState newState) +{ + tx_state_ = newState; + checkBackoffTimer(); +} + + +/* ====================================================================== + TCL Hooks for the simulator + ====================================================================== */ +static class Mac802_11Class : public TclClass { +public: + Mac802_11Class() : TclClass("Mac/802_11") {} + TclObject* create(int, const char*const*) { + return (new Mac802_11()); + +} +} class_mac802_11; + + +/* ====================================================================== + Mac and Phy MIB Class Functions + ====================================================================== */ + +PHY_MIB::PHY_MIB(Mac802_11 *parent) +{ + /* + * Bind the phy mib objects. Note that these will be bound + * to Mac/802_11 variables + */ + + parent->bind("CWMin_", &CWMin); + parent->bind("CWMax_", &CWMax); + parent->bind("SlotTime_", &SlotTime); + parent->bind("SIFS_", &SIFSTime); + parent->bind("BeaconInterval_", &BeaconInterval); + parent->bind("PreambleLength_", &PreambleLength); + parent->bind("PLCPHeaderLength_", &PLCPHeaderLength); + parent->bind_bw("PLCPDataRate_", &PLCPDataRate); +} + +MAC_MIB::MAC_MIB(Mac802_11 *parent) +{ + /* + * Bind the phy mib objects. Note that these will be bound + * to Mac/802_11 variables + */ + + parent->bind("RTSThreshold_", &RTSThreshold); + parent->bind("ShortRetryLimit_", &ShortRetryLimit); + parent->bind("LongRetryLimit_", &LongRetryLimit); +} + +/* ====================================================================== + Mac Class Functions + ====================================================================== */ +Mac802_11::Mac802_11() : + Mac(), phymib_(this), macmib_(this), mhIF_(this), mhNav_(this), + mhRecv_(this), mhSend_(this), + mhDefer_(this), mhBackoff_(this), mhBeacon_(this) +{ + + nav_ = 0.0; + tx_state_ = rx_state_ = MAC_IDLE; + tx_active_ = 0; + eotPacket_ = NULL; + pktRTS_ = 0; + pktCTRL_ = 0; + pktBEACON_ = 0; + pktASSOCREP_ = 0; + pktASSOCREQ_ = 0; + BeaconTxtime_ = 0; + cw_ = phymib_.getCWMin(); + ssrc_ = slrc_ = 0; + // Added by Sushmita + et_ = new EventTrace(); + + sta_seqno_ = 1; + cache_ = 0; + cache_node_count_ = 0; + + node_list = NULL; + power_list = NULL; + Pr = 0; + ap = -1; + ap_addr = -1; + associated = 0; + scan_ = 1; +// ssid_ = "0"; + + // chk if basic/data rates are set + // otherwise use bandwidth_ as default; + + Tcl& tcl = Tcl::instance(); + tcl.evalf("Mac/802_11 set basicRate_"); + if (strcmp(tcl.result(), "0") != 0) + bind_bw("basicRate_", &basicRate_); + else + basicRate_ = bandwidth_; + + tcl.evalf("Mac/802_11 set dataRate_"); + if (strcmp(tcl.result(), "0") != 0) + bind_bw("dataRate_", &dataRate_); + else + dataRate_ = bandwidth_; + + bind_bool("bugFix_timer_", &bugFix_timer_); + + EOTtarget_ = 0; + bss_id_ = IBSS_ID; +} + + +int +Mac802_11::command(int argc, const char*const* argv) +{ + if (argc == 3) { + if (strcmp(argv[1], "scanning") == 0) { + if (strcmp(argv[2], "OFF") == 0) { + scan_ = 0; + } else { + scan_ = 1; + } + return TCL_OK; + } + if (strcmp(argv[1], "eot-target") == 0) { + EOTtarget_ = (NsObject*) TclObject::lookup(argv[2]); + if (EOTtarget_ == 0) + return TCL_ERROR; + return TCL_OK; + } + if (strcmp(argv[1], "ap") == 0) { + ap_addr = addr(); + mhBeacon_.start((Random::random() % cw_) * + phymib_.getSlotTime()); + return TCL_OK; + } + else if (strcmp(argv[1], "log-target") == 0) { + logtarget_ = (NsObject*) TclObject::lookup(argv[2]); + if(logtarget_ == 0) + return TCL_ERROR; + return TCL_OK; + } else if(strcmp(argv[1], "nodes") == 0) { + if(cache_) return TCL_ERROR; + cache_node_count_ = atoi(argv[2]); + cache_ = new Host[cache_node_count_ + 1]; + assert(cache_); + bzero(cache_, sizeof(Host) * (cache_node_count_+1 )); + return TCL_OK; + } else if(strcmp(argv[1], "eventtrace") == 0) { + // command added to support event tracing by Sushmita + et_ = (EventTrace *)TclObject::lookup(argv[2]); + return (TCL_OK); + } + } + return Mac::command(argc, argv); +} + +// Added by Sushmita to support event tracing +void Mac802_11::trace_event(char *eventtype, Packet *p) +{ + if (et_ == NULL) return; + char *wrk = et_->buffer(); + char *nwrk = et_->nbuffer(); + + //char *src_nodeaddr = + // Address::instance().print_nodeaddr(iph->saddr()); + //char *dst_nodeaddr = + // Address::instance().print_nodeaddr(iph->daddr()); + + struct hdr_mac802_11* dh = HDR_MAC802_11(p); + + //struct hdr_cmn *ch = HDR_CMN(p); + + if(wrk != 0) { + sprintf(wrk, "E -t "TIME_FORMAT" %s %2x ", + et_->round(Scheduler::instance().clock()), + eventtype, + //ETHER_ADDR(dh->dh_sa) + ETHER_ADDR(dh->dh_ta) + ); + } + if(nwrk != 0) { + sprintf(nwrk, "E -t "TIME_FORMAT" %s %2x ", + et_->round(Scheduler::instance().clock()), + eventtype, + //ETHER_ADDR(dh->dh_sa) + ETHER_ADDR(dh->dh_ta) + ); + } + et_->dump(); +} + +/* ====================================================================== + Debugging Routines + ====================================================================== */ +void +Mac802_11::trace_pkt(Packet *p) +{ + struct hdr_cmn *ch = HDR_CMN(p); + struct hdr_mac802_11* dh = HDR_MAC802_11(p); + u_int16_t *t = (u_int16_t*) &dh->dh_fc; + + fprintf(stderr, "\t[ %2x %2x %2x %2x ] %x %s %d\n", + *t, dh->dh_duration, + ETHER_ADDR(dh->dh_ra), ETHER_ADDR(dh->dh_ta), + index_, packet_info.name(ch->ptype()), ch->size()); +} + +void +Mac802_11::dump(char *fname) +{ + fprintf(stderr, + "\n%s --- (INDEX: %d, time: %2.9f)\n", + fname, index_, Scheduler::instance().clock()); + + fprintf(stderr, + "\ttx_state_: %x, rx_state_: %x, nav: %2.9f, idle: %d\n", + tx_state_, rx_state_, nav_, is_idle()); + + fprintf(stderr, + "\tpktTx_: %lx, pktRx_: %lx, pktRTS_: %lx, pktCTRL_: %lx, pktBEACON_: %lx, pktASSOCREQ_: %lx, pktASSOCREP_: %lx, callback: %lx\n", + (long) pktTx_, (long) pktRx_, (long) pktRTS_, + (long) pktCTRL_, (long) pktBEACON_, (long) pktASSOCREQ_, (long) pktASSOCREP_, (long) callback_); + + fprintf(stderr, + "\tDefer: %d, Backoff: %d (%d), Recv: %d, Timer: %d Nav: %d\n", + mhDefer_.busy(), mhBackoff_.busy(), mhBackoff_.paused(), + mhRecv_.busy(), mhSend_.busy(), mhNav_.busy()); + fprintf(stderr, + "\tBackoff Expire: %f\n", + mhBackoff_.expire()); +} + + +/* ====================================================================== + Packet Headers Routines + ====================================================================== */ +inline int +Mac802_11::hdr_dst(char* hdr, int dst ) +{ + struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr; + + if (dst > -2) { + if (bss_id() == ((int)IBSS_ID) || addr() == bss_id_) { + + +// if I'm AP (2nd condition above!), the dh_3a +// * is already set by the MAC whilst fwding; if +// * locally originated pkt, it might make sense +// * to set the dh_3a to myself here! don't know +// * how to distinguish between the two here - and +// * the info is not critical to the dst station +// * anyway! +// * + STORE4BYTE(&dst, (dh->dh_ra)); + + } else { + /* in BSS mode, the AP forwards everything; + * therefore, the real dest goes in the 3rd + * address, and the AP address goes in the + * destination address + */ + STORE4BYTE(&bss_id_, (dh->dh_ra)); + STORE4BYTE(&dst, (dh->dh_3a)); + } + } + + + return (u_int32_t)ETHER_ADDR(dh->dh_ra); +} + +inline int +Mac802_11::hdr_src(char* hdr, int src ) +{ + struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr; + if(src > -2) + STORE4BYTE(&src, (dh->dh_ta)); + return ETHER_ADDR(dh->dh_ta); +} + +inline int +Mac802_11::hdr_type(char* hdr, u_int16_t type) +{ + struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr; + if(type) + STORE2BYTE(&type,(dh->dh_body)); + return GET2BYTE(dh->dh_body); +} + + +/* ====================================================================== + Misc Routines + ====================================================================== */ +inline int +Mac802_11::is_idle() +{ + if(rx_state_ != MAC_IDLE) + return 0; + if(tx_state_ != MAC_IDLE) + return 0; + if(nav_ > Scheduler::instance().clock()) + return 0; + + return 1; +} + +void +Mac802_11::discard(Packet *p, const char* why) +{ + hdr_mac802_11* mh = HDR_MAC802_11(p); + hdr_cmn *ch = HDR_CMN(p); + + /* if the rcvd pkt contains errors, a real MAC layer couldn't + necessarily read any data from it, so we just toss it now */ + if(ch->error() != 0) { + Packet::free(p); + return; + } + + switch(mh->dh_fc.fc_type) { + case MAC_Type_Management: +// drop(p, why); +// return; + break; + case MAC_Type_Control: + switch(mh->dh_fc.fc_subtype) { + case MAC_Subtype_RTS: + if((u_int32_t)ETHER_ADDR(mh->dh_ta) == (u_int32_t)index_) { + drop(p, why); + return; + } + /* fall through - if necessary */ + case MAC_Subtype_CTS: + case MAC_Subtype_ACK: + if((u_int32_t)ETHER_ADDR(mh->dh_ra) == (u_int32_t)index_) { + drop(p, why); + return; + } + break; + default: + fprintf(stderr, "invalid MAC Control subtype\n"); + exit(1); + } + break; + case MAC_Type_Data: + switch(mh->dh_fc.fc_subtype) { + case MAC_Subtype_Data: + if((u_int32_t)ETHER_ADDR(mh->dh_ra) == \ + (u_int32_t)index_ || + (u_int32_t)ETHER_ADDR(mh->dh_ta) == \ + (u_int32_t)index_ || + (u_int32_t)ETHER_ADDR(mh->dh_ra) == MAC_BROADCAST) { + drop(p,why); + return; + } + break; + default: + fprintf(stderr, "invalid MAC Data subtype\n"); + exit(1); + } + break; + default: + fprintf(stderr, "invalid MAC type (%x)\n", mh->dh_fc.fc_type); + trace_pkt(p); + exit(1); + } + Packet::free(p); +} + +void +Mac802_11::capture(Packet *p) +{ + /* + * Update the NAV so that this does not screw + * up carrier sense. + */ + set_nav(usec(phymib_.getEIFS() + txtime(p))); + Packet::free(p); +} + +void +Mac802_11::collision(Packet *p) +{ + switch(rx_state_) { + case MAC_RECV: + setRxState(MAC_COLL); + /* fall through */ + case MAC_COLL: + assert(pktRx_); + assert(mhRecv_.busy()); + /* + * Since a collision has occurred, figure out + * which packet that caused the collision will + * "last" the longest. Make this packet, + * pktRx_ and reset the Recv Timer if necessary. + */ + if(txtime(p) > mhRecv_.expire()) { + mhRecv_.stop(); + discard(pktRx_, DROP_MAC_COLLISION); + pktRx_ = p; + mhRecv_.start(txtime(pktRx_)); + } + else { + discard(p, DROP_MAC_COLLISION); + } + break; + default: + assert(0); + } +} + +void +Mac802_11::tx_resume() +{ + double rTime; + assert(mhSend_.busy() == 0); + assert(mhDefer_.busy() == 0); + + if(pktASSOCREP_) { + /* + * Need to send an ASSOCIATION RESPONSE. + */ + + + mhDefer_.start(phymib_.getSIFS()); + } else + if(pktCTRL_) { + /* + * Need to send a CTS or ACK. + */ + mhDefer_.start(phymib_.getSIFS()); + } else if(pktRTS_) { + if (mhBackoff_.busy() == 0) { + if (bugFix_timer_) { + mhBackoff_.start(cw_, is_idle(), + phymib_.getDIFS()); + } + else { + rTime = (Random::random() % cw_) * + phymib_.getSlotTime(); + mhDefer_.start( phymib_.getDIFS() + rTime); + } + } + } else if(pktTx_) { + if (mhBackoff_.busy() == 0) { + hdr_cmn *ch = HDR_CMN(pktTx_); + struct hdr_mac802_11 *mh = HDR_MAC802_11(pktTx_); + + if ((u_int32_t) ch->size() < macmib_.getRTSThreshold() + || (u_int32_t) ETHER_ADDR(mh->dh_ra) == MAC_BROADCAST) { + if (bugFix_timer_) { + mhBackoff_.start(cw_, is_idle(), + phymib_.getDIFS()); + } + else { + rTime = (Random::random() % cw_) + * phymib_.getSlotTime(); + mhDefer_.start(phymib_.getDIFS() + + rTime); + } + } else { + mhDefer_.start(phymib_.getSIFS()); + } + } + } else if(callback_) { + Handler *h = callback_; + callback_ = 0; + h->handle((Event*) 0); + } + setTxState(MAC_IDLE); +} + +void +Mac802_11::rx_resume() +{ + assert(pktRx_ == 0); + assert(mhRecv_.busy() == 0); + setRxState(MAC_IDLE); +} + + +/* ====================================================================== + Timer Handler Routines + ====================================================================== */ +void +Mac802_11::backoffHandler() +{ + + if(check_pktASSOCREQ() == 0) + return; + + if(pktCTRL_) { + assert(mhSend_.busy() || mhDefer_.busy()); + return; + } + + if ( addr() == ap_addr ) { + if(pktBEACON_) { + struct beacon_frame *bf = (struct beacon_frame*)pktBEACON_->access(hdr_mac::offset_); + bf->bf_timestamp = Scheduler::instance().clock(); + setTxState(MAC_BCN); + transmit(pktBEACON_, BeaconTxtime_); + } + } + + if(check_pktRTS() == 0) + return; + + if(check_pktTx() == 0) + return; +} + +void +Mac802_11::BeaconHandler() +{ + + mhBeacon_.start(phymib_.getBeaconInterval()); + sendBEACON(index_); + +} + +void +Mac802_11::deferHandler() +{ + assert(pktCTRL_ || pktRTS_ || pktTx_ || pktASSOCREP_); + + if ( addr() == ap_addr && pktASSOCREP_ ) { + if (check_pktASSOCREP() == 0) + return; + } + + if(check_pktCTRL() == 0) + return; + assert(mhBackoff_.busy() == 0); + if(check_pktRTS() == 0) + return; + if(check_pktTx() == 0) + return; +} + +void +Mac802_11::navHandler() +{ + if(is_idle() && mhBackoff_.paused()) + mhBackoff_.resume(phymib_.getDIFS()); +} + +void +Mac802_11::recvHandler() +{ + recv_timer(); +} + +void +Mac802_11::sendHandler() +{ + send_timer(); +} + + +void +Mac802_11::txHandler() +{ + if (EOTtarget_) { + assert(eotPacket_); + EOTtarget_->recv(eotPacket_, (Handler *) 0); + eotPacket_ = NULL; + } + tx_active_ = 0; +} + + +/* ====================================================================== + The "real" Timer Handler Routines + ====================================================================== */ +void +Mac802_11::send_timer() +{ + double rTime; + switch(tx_state_) { + /* + * Sent a RTS, but did not receive a CTS. + */ + case MAC_MGMT: + if (pktASSOCREQ_) { + + if(mhBackoff_.busy() == 0) { + if(is_idle()) { + if (mhDefer_.busy() == 0) { + if (bugFix_timer_) { + mhBackoff_.start(cw_, is_idle(), + phymib_.getDIFS()); + } + else { + rTime = (Random::random() % cw_) + * (phymib_.getSlotTime()); + mhDefer_.start(phymib_.getDIFS() + + rTime); + } + } + } else { + mhBackoff_.start(cw_, is_idle()); + + } + } + break; + } + if (pktASSOCREP_) { + + assert(pktASSOCREP_); + Packet::free(pktASSOCREP_); + pktASSOCREP_ = 0; + break; + } + case MAC_BCN: + assert(pktBEACON_); + Packet::free(pktBEACON_); + pktBEACON_ = 0; + break; + + case MAC_RTS: + RetransmitRTS(); + break; + /* + * Sent a CTS, but did not receive a DATA packet. + */ + case MAC_CTS: + assert(pktCTRL_); + Packet::free(pktCTRL_); + pktCTRL_ = 0; + break; + /* + * Sent DATA, but did not receive an ACK packet. + */ + case MAC_SEND: + RetransmitDATA(); + break; + /* + * Sent an ACK, and now ready to resume transmission. + */ + case MAC_ACK: + assert(pktCTRL_); + Packet::free(pktCTRL_); + pktCTRL_ = 0; + break; + case MAC_IDLE: + break; + default: + assert(0); + } + tx_resume(); +} + + +/* ====================================================================== + Outgoing Packet Routines + ====================================================================== */ +int +Mac802_11::check_pktCTRL() +{ + struct hdr_mac802_11 *mh; + double timeout; + + if(pktCTRL_ == 0) + return -1; + if(tx_state_ == MAC_CTS || tx_state_ == MAC_ACK) + return -1; + + mh = HDR_MAC802_11(pktCTRL_); + + switch(mh->dh_fc.fc_subtype) { + /* + * If the medium is not IDLE, don't send the CTS. + */ + case MAC_Subtype_CTS: + if(!is_idle()) { + discard(pktCTRL_, DROP_MAC_BUSY); pktCTRL_ = 0; + return 0; + } + setTxState(MAC_CTS); + /* + * timeout: cts + data tx time calculated by + * adding cts tx time to the cts duration + * minus ack tx time -- this timeout is + * a guess since it is unspecified + * (note: mh->dh_duration == cf->cf_duration) + */ + timeout = txtime(phymib_.getCTSlen(), basicRate_) + + DSSS_MaxPropagationDelay // XXX + + sec(mh->dh_duration) + + DSSS_MaxPropagationDelay // XXX + - phymib_.getSIFS() + - txtime(phymib_.getACKlen(), basicRate_); + break; + /* + * IEEE 802.11 specs, section 9.2.8 + * Acknowledments are sent after an SIFS, without regard to + * the busy/idle state of the medium. + */ + case MAC_Subtype_ACK: + setTxState(MAC_ACK); + timeout = txtime(phymib_.getACKlen(), basicRate_); + break; + default: + fprintf(stderr, "check_pktCTRL:Invalid MAC Control subtype\n"); + exit(1); + } + transmit(pktCTRL_, timeout); + return 0; +} + +int +Mac802_11::check_pktRTS() +{ + struct hdr_mac802_11 *mh; + double timeout; + + assert(mhBackoff_.busy() == 0); + + if(pktRTS_ == 0) + return -1; + mh = HDR_MAC802_11(pktRTS_); + + switch(mh->dh_fc.fc_subtype) { + case MAC_Subtype_RTS: + if(! is_idle()) { + inc_cw(); + mhBackoff_.start(cw_, is_idle()); + return 0; + } + setTxState(MAC_RTS); + timeout = txtime(phymib_.getRTSlen(), basicRate_) + + DSSS_MaxPropagationDelay // XXX + + phymib_.getSIFS() + + txtime(phymib_.getCTSlen(), basicRate_) + + DSSS_MaxPropagationDelay; + break; + default: + fprintf(stderr, "check_pktRTS:Invalid MAC Control subtype\n"); + exit(1); + } + transmit(pktRTS_, timeout); + + + return 0; +} + +int +Mac802_11::check_pktTx() +{ + struct hdr_mac802_11 *mh; + double timeout; + + assert(mhBackoff_.busy() == 0); + + if(pktTx_ == 0) + return -1; + + mh = HDR_MAC802_11(pktTx_); + + switch(mh->dh_fc.fc_subtype) { + case MAC_Subtype_Data: + if(! is_idle()) { + sendRTS(ETHER_ADDR(mh->dh_ra)); + inc_cw(); + mhBackoff_.start(cw_, is_idle()); + return 0; + } + setTxState(MAC_SEND); + if((u_int32_t)ETHER_ADDR(mh->dh_ra) != MAC_BROADCAST) + timeout = txtime(pktTx_) + + DSSS_MaxPropagationDelay // XXX + + phymib_.getSIFS() + + txtime(phymib_.getACKlen(), basicRate_) + + DSSS_MaxPropagationDelay; // XXX + else + timeout = txtime(pktTx_); + break; + default: + fprintf(stderr, "check_pktTx:Invalid MAC Control subtype\n"); + exit(1); + } + transmit(pktTx_, timeout); + return 0; +} +/* + * Low-level transmit functions that actually place the packet onto + * the channel. + */ +void +Mac802_11::sendRTS(int dst) +{ + Packet *p = Packet::alloc(); + hdr_cmn* ch = HDR_CMN(p); + struct rts_frame *rf = (struct rts_frame*)p->access(hdr_mac::offset_); + + assert(pktTx_); + assert(pktRTS_ == 0); + + /* + * If the size of the packet is larger than the + * RTSThreshold, then perform the RTS/CTS exchange. + */ + if( (u_int32_t) HDR_CMN(pktTx_)->size() < macmib_.getRTSThreshold() || + (u_int32_t) dst == MAC_BROADCAST) { + Packet::free(p); + return; + } + + ch->uid() = 0; + ch->ptype() = PT_MAC; + ch->size() = phymib_.getRTSlen(); + ch->iface() = -2; + ch->error() = 0; + + bzero(rf, MAC_HDR_LEN); + + rf->rf_fc.fc_protocol_version = MAC_ProtocolVersion; + rf->rf_fc.fc_type = MAC_Type_Control; + rf->rf_fc.fc_subtype = MAC_Subtype_RTS; + rf->rf_fc.fc_to_ds = 0; + rf->rf_fc.fc_from_ds = 0; + rf->rf_fc.fc_more_frag = 0; + rf->rf_fc.fc_retry = 0; + rf->rf_fc.fc_pwr_mgt = 0; + rf->rf_fc.fc_more_data = 0; + rf->rf_fc.fc_wep = 0; + rf->rf_fc.fc_order = 0; + + + //rf->rf_duration = RTS_DURATION(pktTx_); + STORE4BYTE(&dst, (rf->rf_ra)); + + /* store rts tx time */ + ch->txtime() = txtime(ch->size(), basicRate_); + + STORE4BYTE(&index_, (rf->rf_ta)); + + /* calculate rts duration field */ + rf->rf_duration = usec(phymib_.getSIFS() + + txtime(phymib_.getCTSlen(), basicRate_) + + phymib_.getSIFS() + + txtime(pktTx_) + + phymib_.getSIFS() + + txtime(phymib_.getACKlen(), basicRate_)); + pktRTS_ = p; +} + +void +Mac802_11::sendCTS(int dst, double rts_duration) +{ + Packet *p = Packet::alloc(); + hdr_cmn* ch = HDR_CMN(p); + struct cts_frame *cf = (struct cts_frame*)p->access(hdr_mac::offset_); + + assert(pktCTRL_ == 0); + + ch->uid() = 0; + ch->ptype() = PT_MAC; + ch->size() = phymib_.getCTSlen(); + + + ch->iface() = -2; + ch->error() = 0; + //ch->direction() = hdr_cmn::DOWN; + bzero(cf, MAC_HDR_LEN); + + cf->cf_fc.fc_protocol_version = MAC_ProtocolVersion; + cf->cf_fc.fc_type = MAC_Type_Control; + cf->cf_fc.fc_subtype = MAC_Subtype_CTS; + cf->cf_fc.fc_to_ds = 0; + cf->cf_fc.fc_from_ds = 0; + cf->cf_fc.fc_more_frag = 0; + cf->cf_fc.fc_retry = 0; + cf->cf_fc.fc_pwr_mgt = 0; + cf->cf_fc.fc_more_data = 0; + cf->cf_fc.fc_wep = 0; + cf->cf_fc.fc_order = 0; + + + //cf->cf_duration = CTS_DURATION(rts_duration); + STORE4BYTE(&dst, (cf->cf_ra)); + + /* store cts tx time */ + ch->txtime() = txtime(ch->size(), basicRate_); + + /* calculate cts duration */ + cf->cf_duration = usec(sec(rts_duration) + - phymib_.getSIFS() + - txtime(phymib_.getCTSlen(), basicRate_)); + + + + pktCTRL_ = p; + +} + +void +Mac802_11::sendACK(int dst) +{ + Packet *p = Packet::alloc(); + hdr_cmn* ch = HDR_CMN(p); + struct ack_frame *af = (struct ack_frame*)p->access(hdr_mac::offset_); + + assert(pktCTRL_ == 0); + + ch->uid() = 0; + ch->ptype() = PT_MAC; + // CHANGE WRT Mike's code + ch->size() = phymib_.getACKlen(); + ch->iface() = -2; + ch->error() = 0; + + bzero(af, MAC_HDR_LEN); + + af->af_fc.fc_protocol_version = MAC_ProtocolVersion; + af->af_fc.fc_type = MAC_Type_Control; + af->af_fc.fc_subtype = MAC_Subtype_ACK; + af->af_fc.fc_to_ds = 0; + af->af_fc.fc_from_ds = 0; + af->af_fc.fc_more_frag = 0; + af->af_fc.fc_retry = 0; + af->af_fc.fc_pwr_mgt = 0; + af->af_fc.fc_more_data = 0; + af->af_fc.fc_wep = 0; + af->af_fc.fc_order = 0; + + //af->af_duration = ACK_DURATION(); + STORE4BYTE(&dst, (af->af_ra)); + + /* store ack tx time */ + ch->txtime() = txtime(ch->size(), basicRate_); + + /* calculate ack duration */ + af->af_duration = 0; + + pktCTRL_ = p; +} + +void +Mac802_11::sendDATA(Packet *p) +{ + hdr_cmn* ch = HDR_CMN(p); + struct hdr_mac802_11* dh = HDR_MAC802_11(p); + + assert(pktTx_ == 0); + + /* + * Update the MAC header + */ + ch->size() += phymib_.getHdrLen11(); + + dh->dh_fc.fc_protocol_version = MAC_ProtocolVersion; + dh->dh_fc.fc_type = MAC_Type_Data; + dh->dh_fc.fc_subtype = MAC_Subtype_Data; + if ( bss_id_ != (int)IBSS_ID ) { + if ( index_ == ap_addr ) { + dh->dh_fc.fc_to_ds = 0; + dh->dh_fc.fc_from_ds = 1; + } else { + dh->dh_fc.fc_to_ds = 1; + dh->dh_fc.fc_from_ds = 0; + } + } else { + dh->dh_fc.fc_to_ds = 0; + dh->dh_fc.fc_from_ds = 0; + } +// dh->dh_fc.fc_to_ds = 0; +// dh->dh_fc.fc_from_ds = 0; + dh->dh_fc.fc_more_frag = 0; + dh->dh_fc.fc_retry = 0; + dh->dh_fc.fc_pwr_mgt = 0; + dh->dh_fc.fc_more_data = 0; + dh->dh_fc.fc_wep = 0; + dh->dh_fc.fc_order = 0; + + /* store data tx time */ + ch->txtime() = txtime(ch->size(), dataRate_); + + if((u_int32_t)ETHER_ADDR(dh->dh_ra) != MAC_BROADCAST) { + /* store data tx time for unicast packets */ + ch->txtime() = txtime(ch->size(), dataRate_); + + dh->dh_duration = usec(txtime(phymib_.getACKlen(), basicRate_) + + phymib_.getSIFS()); + + + + } else { + /* store data tx time for broadcast packets (see 9.6) */ + ch->txtime() = txtime(ch->size(), basicRate_); + + dh->dh_duration = 0; + } + pktTx_ = p; +} + +/* ====================================================================== + Retransmission Routines + ====================================================================== */ +void +Mac802_11::RetransmitRTS() +{ + assert(pktTx_); + assert(pktRTS_); + assert(mhBackoff_.busy() == 0); + macmib_.RTSFailureCount++; + + + ssrc_ += 1; // STA Short Retry Count + + if(ssrc_ >= macmib_.getShortRetryLimit()) { + discard(pktRTS_, DROP_MAC_RETRY_COUNT_EXCEEDED); pktRTS_ = 0; + /* tell the callback the send operation failed + before discarding the packet */ + hdr_cmn *ch = HDR_CMN(pktTx_); + if (ch->xmit_failure_) { + /* + * Need to remove the MAC header so that + * re-cycled packets don't keep getting + * bigger. + */ + ch->size() -= phymib_.getHdrLen11(); + ch->xmit_reason_ = XMIT_REASON_RTS; + ch->xmit_failure_(pktTx_->copy(), + ch->xmit_failure_data_); + } + discard(pktTx_, DROP_MAC_RETRY_COUNT_EXCEEDED); + pktTx_ = 0; + ssrc_ = 0; + rst_cw(); + } else { + struct rts_frame *rf; + rf = (struct rts_frame*)pktRTS_->access(hdr_mac::offset_); + rf->rf_fc.fc_retry = 1; + + inc_cw(); + mhBackoff_.start(cw_, is_idle()); + } +} + +void +Mac802_11::RetransmitDATA() +{ + struct hdr_cmn *ch; + struct hdr_mac802_11 *mh; + u_int32_t *rcount, thresh; + assert(mhBackoff_.busy() == 0); + + assert(pktTx_); + assert(pktRTS_ == 0); + + ch = HDR_CMN(pktTx_); + mh = HDR_MAC802_11(pktTx_); + + /* + * Broadcast packets don't get ACKed and therefore + * are never retransmitted. + */ + if((u_int32_t)ETHER_ADDR(mh->dh_ra) == MAC_BROADCAST) { + Packet::free(pktTx_); + pktTx_ = 0; + + /* + * Backoff at end of TX. + */ + rst_cw(); + mhBackoff_.start(cw_, is_idle()); + + return; + } + + macmib_.ACKFailureCount++; + + if((u_int32_t) ch->size() <= macmib_.getRTSThreshold()) { + rcount = &ssrc_; + thresh = macmib_.getShortRetryLimit(); + } else { + rcount = &slrc_; + thresh = macmib_.getLongRetryLimit(); + } + + (*rcount)++; + + if(*rcount >= thresh) { + /* IEEE Spec section 9.2.3.5 says this should be greater than + or equal */ + macmib_.FailedCount++; + /* tell the callback the send operation failed + before discarding the packet */ + hdr_cmn *ch = HDR_CMN(pktTx_); + if (ch->xmit_failure_) { + ch->size() -= phymib_.getHdrLen11(); + ch->xmit_reason_ = XMIT_REASON_ACK; + ch->xmit_failure_(pktTx_->copy(), + ch->xmit_failure_data_); + } + + discard(pktTx_, DROP_MAC_RETRY_COUNT_EXCEEDED); + pktTx_ = 0; + *rcount = 0; + rst_cw(); + } + else { + struct hdr_mac802_11 *dh; + dh = HDR_MAC802_11(pktTx_); + dh->dh_fc.fc_retry = 1; + + + sendRTS(ETHER_ADDR(mh->dh_ra)); + inc_cw(); + mhBackoff_.start(cw_, is_idle()); + } +} + +/* ====================================================================== + Incoming Packet Routines + ====================================================================== */ +void +Mac802_11::send(Packet *p, Handler *h) +{ + double rTime; + struct hdr_mac802_11* dh = HDR_MAC802_11(p); + + EnergyModel *em = netif_->node()->energy_model(); + if (em && em->sleep()) { + em->set_node_sleep(0); + em->set_node_state(EnergyModel::INROUTE); + } + + callback_ = h; + sendDATA(p); + sendRTS(ETHER_ADDR(dh->dh_ra)); + + /* + * Assign the data packet a sequence number. + */ + dh->dh_scontrol = sta_seqno_++; + + /* + * If the medium is IDLE, we must wait for a DIFS + * Space before transmitting. + */ + + if(mhBackoff_.busy() == 0) { + if(is_idle()) { + if (mhDefer_.busy() == 0) { + /* + * If we are already deferring, there is no + * need to reset the Defer timer. + */ + if (bugFix_timer_) { + mhBackoff_.start(cw_, is_idle(), + phymib_.getDIFS()); + } + else { + rTime = (Random::random() % cw_) + * (phymib_.getSlotTime()); + mhDefer_.start(phymib_.getDIFS() + + rTime); + } + } + } else { + /* + * If the medium is NOT IDLE, then we start + * the backoff timer. + */ + mhBackoff_.start(cw_, is_idle()); + } + } + +} + +void +Mac802_11::recv(Packet *p, Handler *h) +{ + struct hdr_cmn *hdr = HDR_CMN(p); + /* + * Sanity Check + */ + assert(initialized()); + + /* + * Handle outgoing packets. + */ + if(hdr->direction() == hdr_cmn::DOWN) { + send(p, h); + return; + } + /* + * Handle incoming packets. + * + * We just received the 1st bit of a packet on the network + * interface. + * + */ + + /* + * If the interface is currently in transmit mode, then + * it probably won't even see this packet. However, the + * "air" around me is BUSY so I need to let the packet + * proceed. Just set the error flag in the common header + * to that the packet gets thrown away. + */ + if(tx_active_ && hdr->error() == 0) { + hdr->error() = 1; + } + + if(rx_state_ == MAC_IDLE) { + setRxState(MAC_RECV); + pktRx_ = p; + /* + * Schedule the reception of this packet, in + * txtime seconds. + */ + mhRecv_.start(txtime(p)); + } else { + /* + * If the power of the incoming packet is smaller than the + * power of the packet currently being received by at least + * the capture threshold, then we ignore the new packet. + */ + if(pktRx_->txinfo_.RxPr / p->txinfo_.RxPr >= p->txinfo_.CPThresh) { + capture(p); + } else { + collision(p); + } + } +} + +void +Mac802_11::recv_timer() +{ + u_int32_t src; + hdr_cmn *ch = HDR_CMN(pktRx_); + hdr_mac802_11 *mh = HDR_MAC802_11(pktRx_); + u_int32_t dst = ETHER_ADDR(mh->dh_ra); + + u_int8_t type = mh->dh_fc.fc_type; + u_int8_t subtype = mh->dh_fc.fc_subtype; + + assert(pktRx_); + assert(rx_state_ == MAC_RECV || rx_state_ == MAC_COLL); + + + /* + * If the interface is in TRANSMIT mode when this packet + * "arrives", then I would never have seen it and should + * do a silent discard without adjusting the NAV. + */ + if(tx_active_) { + Packet::free(pktRx_); + goto done; + } + + /* + * Handle collisions. + */ + if(rx_state_ == MAC_COLL) { + discard(pktRx_, DROP_MAC_COLLISION); + set_nav(usec(phymib_.getEIFS())); + goto done; + } + + /* + * Check to see if this packet was received with enough + * bit errors that the current level of FEC still could not + * fix all of the problems - ie; after FEC, the checksum still + * failed. + */ + if( ch->error() ) { + Packet::free(pktRx_); + set_nav(usec(phymib_.getEIFS())); + goto done; + } + + /* + * IEEE 802.11 specs, section 9.2.5.6 + * - update the NAV (Network Allocation Vector) + */ + if(dst != (u_int32_t)index_) { + set_nav(mh->dh_duration); + } + + /* tap out - */ + if (tap_ && type == MAC_Type_Data && + MAC_Subtype_Data == subtype ) + tap_->tap(pktRx_); + /* + * Adaptive Fidelity Algorithm Support - neighborhood infomation + * collection + * + * Hacking: Before filter the packet, log the neighbor node + * I can hear the packet, the src is my neighbor + */ + if (netif_->node()->energy_model() && + netif_->node()->energy_model()->adaptivefidelity()) { + src = ETHER_ADDR(mh->dh_ta); + netif_->node()->energy_model()->add_neighbor(src); + } + /* + * Address Filtering + */ + if(dst != (u_int32_t)index_ && dst != MAC_BROADCAST) { + /* + * We don't want to log this event, so we just free + * the packet instead of calling the drop routine. + */ + + discard(pktRx_, "---"); + goto done; + } + + + switch(type) { + + case MAC_Type_Management: + //discard(pktRx_, DROP_MAC_PACKET_ERROR); + switch(subtype) { + case MAC_Subtype_11_Beacon: + recvBEACON(pktRx_); + break; + + case MAC_Subtype_AssocReq: + recvASSOCREQ(pktRx_); + break; + case MAC_Subtype_AssocRep: + recvASSOCREP(pktRx_); + break; + } + break; + case MAC_Type_Control: + switch(subtype) { + case MAC_Subtype_RTS: + recvRTS(pktRx_); + break; + case MAC_Subtype_CTS: + recvCTS(pktRx_); + break; + case MAC_Subtype_ACK: + recvACK(pktRx_); + break; + default: + fprintf(stderr,"recvTimer1:Invalid MAC Control Subtype %x\n", + subtype); + exit(1); + } + break; + case MAC_Type_Data: + switch(subtype) { + case MAC_Subtype_Data: + recvDATA(pktRx_); + break; + default: + fprintf(stderr, "recv_timer2:Invalid MAC Data Subtype %x\n", + subtype); + exit(1); + } + break; + default: + fprintf(stderr, "recv_timer3:Invalid MAC Type %x\n", subtype); + exit(1); + } + done: + pktRx_ = 0; + rx_resume(); +} + + +void +Mac802_11::recvRTS(Packet *p) +{ + struct rts_frame *rf = (struct rts_frame*)p->access(hdr_mac::offset_); + + if(tx_state_ != MAC_IDLE) { + discard(p, DROP_MAC_BUSY); + return; + } + + /* + * If I'm responding to someone else, discard this RTS. + */ + if(pktCTRL_) { + discard(p, DROP_MAC_BUSY); + return; + } + + sendCTS(ETHER_ADDR(rf->rf_ta), rf->rf_duration); + + /* + * Stop deferring - will be reset in tx_resume(). + */ + if(mhDefer_.busy()) mhDefer_.stop(); + + tx_resume(); + + mac_log(p); +} + +/* + * txtime() - pluck the precomputed tx time from the packet header + */ +double +Mac802_11::txtime(Packet *p) +{ + struct hdr_cmn *ch = HDR_CMN(p); + double t = ch->txtime(); + if (t < 0.0) { + drop(p, "XXX"); + exit(1); + } + return t; +} + + +/* + * txtime() - calculate tx time for packet of size "psz" bytes + * at rate "drt" bps + */ +double +Mac802_11::txtime(double psz, double drt) +{ + double dsz = psz - phymib_.getPLCPhdrLen(); + int plcp_hdr = phymib_.getPLCPhdrLen() << 3; + int datalen = (int)dsz << 3; + double t = (((double)plcp_hdr)/phymib_.getPLCPDataRate()) + + (((double)datalen)/drt); + return(t); +} + + + +void +Mac802_11::recvCTS(Packet *p) +{ + if(tx_state_ != MAC_RTS) { + discard(p, DROP_MAC_INVALID_STATE); + return; + } + + assert(pktRTS_); + Packet::free(pktRTS_); pktRTS_ = 0; + + assert(pktTx_); + mhSend_.stop(); + + /* + * The successful reception of this CTS packet implies + * that our RTS was successful. + * According to the IEEE spec 9.2.5.3, you must + * reset the ssrc_, but not the congestion window. + */ + ssrc_ = 0; + tx_resume(); + + mac_log(p); +} + +void +Mac802_11::recvDATA(Packet *p) +{ + struct hdr_mac802_11 *dh = HDR_MAC802_11(p); + u_int32_t dst, src, size; + struct hdr_cmn *ch = HDR_CMN(p); + + dst = ETHER_ADDR(dh->dh_ra); + src = ETHER_ADDR(dh->dh_ta); + size = ch->size(); + /* + * Adjust the MAC packet size - ie; strip + * off the mac header + */ + ch->size() -= phymib_.getHdrLen11(); + ch->num_forwards() += 1; + + /* + * If we sent a CTS, clean up... + */ + if(dst != MAC_BROADCAST) { + if(size >= macmib_.getRTSThreshold()) { + if (tx_state_ == MAC_CTS) { + assert(pktCTRL_); + Packet::free(pktCTRL_); pktCTRL_ = 0; + mhSend_.stop(); + /* + * Our CTS got through. + */ + } else { + discard(p, DROP_MAC_BUSY); + return; + } + sendACK(src); + tx_resume(); + } else { + /* + * We did not send a CTS and there's no + * room to buffer an ACK. + */ + if(pktCTRL_) { + discard(p, DROP_MAC_BUSY); + return; + } + sendACK(src); + if(mhSend_.busy() == 0) + tx_resume(); + } + } + + /* ============================================================ + Make/update an entry in our sequence number cache. + ============================================================ */ + + /* Changed by Debojyoti Dutta. This upper loop of if{}else was + suggested by Joerg Diederich . + Changed on 19th Oct'2000 */ + + if(dst != MAC_BROADCAST) { + if (src < (u_int32_t) cache_node_count_) { + Host *h = &cache_[src]; + + if(h->seqno && h->seqno == dh->dh_scontrol) { + discard(p, DROP_MAC_DUPLICATE); + return; + } + h->seqno = dh->dh_scontrol; + } else { + static int count = 0; + if (++count <= 10) { + printf ("MAC_802_11: accessing MAC cache_ array out of range (src %u, dst %u, size %d)!\n", src, dst, cache_node_count_); + if (count == 10) + printf ("[suppressing additional MAC cache_ warnings]\n"); + }; + }; + } + + /* + * Pass the packet up to the link-layer. + * XXX - we could schedule an event to account + * for this processing delay. + */ + + /* in BSS mode, if a station receives a packet via + * the AP, and higher layers are interested in looking + * at the src address, we might need to put it at + * the right place - lest the higher layers end up + * believing the AP address to be the src addr! a quick + * grep didn't turn up any higher layers interested in + * the src addr though! + * anyway, here if I'm the AP and the destination + * address (in dh_3a) isn't me, then we have to fwd + * the packet; we pick the real destination and set + * set it up for the LL; we save the real src into + * the dh_3a field for the 'interested in the info' + * receiver; we finally push the packet towards the + * LL to be added back to my queue - accomplish this + * by reversing the direction!*/ + + if ((bss_id() == addr()) && ((u_int32_t)ETHER_ADDR(dh->dh_ra)!= MAC_BROADCAST)&& ((u_int32_t)ETHER_ADDR(dh->dh_3a) != ((u_int32_t)addr()))) { + struct hdr_cmn *ch = HDR_CMN(p); + + u_int32_t dst = ETHER_ADDR(dh->dh_3a); + u_int32_t src = ETHER_ADDR(dh->dh_ta); + /* if it is a broadcast pkt then send a copy up + * my stack also + */ + + if (dst == MAC_BROADCAST) { + uptarget_->recv(p->copy(), (Handler*) 0); + } + + ch->next_hop() = dst; + STORE4BYTE(&src, (dh->dh_3a)); + ch->addr_type() = NS_AF_ILINK; + ch->direction() = hdr_cmn::DOWN; + + } + + uptarget_->recv(p, (Handler*) 0); + +} + + +void +Mac802_11::recvACK(Packet *p) +{ + if(tx_state_ != MAC_SEND) { + discard(p, DROP_MAC_INVALID_STATE); + return; + } + assert(pktTx_); + + mhSend_.stop(); + + /* + * The successful reception of this ACK packet implies + * that our DATA transmission was successful. Hence, + * we can reset the Short/Long Retry Count and the CW. + * + * need to check the size of the packet we sent that's being + * ACK'd, not the size of the ACK packet. + */ + if((u_int32_t) HDR_CMN(pktTx_)->size() <= macmib_.getRTSThreshold()) + ssrc_ = 0; + else + slrc_ = 0; + rst_cw(); + Packet::free(pktTx_); + pktTx_ = 0; + + /* + * Backoff before sending again. + */ + assert(mhBackoff_.busy() == 0); + mhBackoff_.start(cw_, is_idle()); + + tx_resume(); + + mac_log(p); +} + + +/* AP's association table functions +*/ +void Mac802_11::update_ap_table(int num) { + if (node_list == NULL) { + node_list = (struct ap_table*)malloc(sizeof(struct ap_table)); + node_list->node_id=num; + node_list->next=NULL; + } + else { + push(num); + } + printf("Associated Nodes for AP %d\n",index_); + struct ap_table *temp; + temp = node_list; + while (temp != NULL) { + printf("%d ", temp->node_id); + temp=temp->next; + } + printf("\n"); +} + +void Mac802_11::push(int num) { + struct ap_table *temp; + temp = node_list; + while (temp->next != NULL) { + + temp=temp->next; + } + temp->next = (struct ap_table*)malloc(sizeof(struct ap_table)); + temp->next->node_id = num; + temp->next->next = NULL; +} + +int Mac802_11::find_node(int num) { + struct ap_table *temp; + temp = node_list; + while (temp != NULL) { + if (temp->node_id == num) { + return 1; + break; + } + + temp=temp->next; + + if (temp == NULL) { + return 0; + } + } +} + +/* Beacon send and Receive functions +*/ +void +Mac802_11::sendBEACON(int src) +{ +// printf("SendBEACON entered at %f for node %d\n",NOW,index_); + Packet *p = Packet::alloc(); + + hdr_cmn* ch = HDR_CMN(p); + struct beacon_frame *bf = (struct beacon_frame*)p->access(hdr_mac::offset_); + + pktBEACON_ = 0; + + ch->uid() = 0; + + + ch->ptype() = PT_MAC; + ch->size() = phymib_.getBEACONlen(); + ch->iface() = -2; + ch->error() = 0; + + bzero(bf, MAC_HDR_LEN); + +/* Note: I had to give a different name for MAC_Subtype_Beacon as MAC_Subtype_11_Beacon as MAC_Subtype_Beacon is already defined for 802.15.4 with a different value!! (See cmu-trace.cc). +*/ + + bf->bf_fc.fc_protocol_version = MAC_ProtocolVersion; + bf->bf_fc.fc_type = MAC_Type_Management; + bf->bf_fc.fc_subtype = MAC_Subtype_11_Beacon; + bf->bf_fc.fc_to_ds = 0; + bf->bf_fc.fc_from_ds = 1; + bf->bf_fc.fc_more_frag = 0; + bf->bf_fc.fc_retry = 0; + bf->bf_fc.fc_pwr_mgt = 0; + bf->bf_fc.fc_more_data = 0; + bf->bf_fc.fc_wep = 0; + bf->bf_fc.fc_order = 0; + + + + int dst = MAC_BROADCAST; + STORE4BYTE(&dst, (bf->bf_ra)); + STORE4BYTE(&src, (bf->bf_ta)); + STORE4BYTE(&ap_addr, (bf->bf_3a)); + + bf->bf_timestamp = Scheduler::instance().clock(); + bf->bf_beaconint = phymib_.getBeaconInterval(); + + /* store beacon tx time */ + + ch->txtime() = txtime(ch->size(), basicRate_); + + /* calculate beacon duration??? */ + bf->bf_duration = 0; + + pktBEACON_ = p; + + BeaconTxtime_ = txtime(phymib_.getBEACONlen(), basicRate_); + + if(mhBackoff_.busy() == 0) { + if(is_idle()) { + if (mhDefer_.busy() == 0) { + + setTxState(MAC_BCN); + transmit(pktBEACON_, BeaconTxtime_); + } else { + mhBackoff_.start(cw_, !is_idle()); + } + + } else { + /* + * If the medium is NOT IDLE, then we start + * the backoff timer. + */ + + mhBackoff_.start(cw_, is_idle()); + + } + } + + +} + +void +Mac802_11::recvBEACON(Packet *p) +{ + struct beacon_frame *bf = (struct beacon_frame*)p->access(hdr_mac::offset_); + + if(tx_state_ != MAC_IDLE) { + discard(p, DROP_MAC_BUSY); + return; + } + u_int32_t bss_id, src; + double timestamp, beaconint; + struct hdr_cmn *ch = HDR_CMN(p); + + bss_id = ETHER_ADDR(bf->bf_3a); + src = ETHER_ADDR(bf->bf_ta); + static int count = 0; + + + + timestamp = bf->bf_timestamp; + beaconint = bf->bf_beaconint; + + if (scan_ == 0) { + + goto done; + } + + Pr = p->txinfo_.RxPr; + if ( addr() != ap_addr ) { + if (associated == 0) { + if (find_ap(src,Pr) == 1) { + + if (strongest_beacon() >= 0) + ap = strongest_beacon(); + + sendASSOCREQ(ap); + } else { + add_beacon_table(src,Pr); + } + } + } +done: + count = count + 1; + mac_log(p); +} + + +void +Mac802_11::sendASSOCREQ(int dst) +{ + Packet *p = Packet::alloc(); + hdr_cmn* ch = HDR_CMN(p); + struct assocreq_frame *acf =(struct assocreq_frame*)p->access(hdr_mac::offset_); + + double rTime; + pktASSOCREQ_ = 0; + + ch->uid() = 0; + + + ch->ptype() = PT_MAC; + ch->size() = phymib_.getASSOCREQlen(); + ch->iface() = -2; + ch->error() = 0; + + bzero(acf, MAC_HDR_LEN); + + acf->acf_fc.fc_protocol_version = MAC_ProtocolVersion; + acf->acf_fc.fc_type = MAC_Type_Management; + acf->acf_fc.fc_subtype = MAC_Subtype_AssocReq; + acf->acf_fc.fc_to_ds = 0; + acf->acf_fc.fc_from_ds = 0; + acf->acf_fc.fc_more_frag= 0; + acf->acf_fc.fc_retry = 0; + acf->acf_fc.fc_pwr_mgt = 0; + acf->acf_fc.fc_more_data= 0; + acf->acf_fc.fc_wep = 0; + acf->acf_fc.fc_order = 0; + + STORE4BYTE(&dst, (acf->acf_ra)); + STORE4BYTE(&index_, (acf->acf_ta)); + STORE4BYTE(&dst, (acf->acf_3a)); + + + ch->txtime() = txtime(ch->size(), basicRate_); + acf->acf_duration = usec(phymib_.getSIFS() + + txtime(phymib_.getASSOCREPlen(), basicRate_)); + + + pktASSOCREQ_ = p; + + if(mhBackoff_.busy() == 0) { + if(is_idle()) { + if (mhDefer_.busy() == 0) { + if (bugFix_timer_) { + mhBackoff_.start(cw_, is_idle(), + phymib_.getDIFS()); + } + else { + rTime = (Random::random() % cw_) + * (phymib_.getSlotTime()); + mhDefer_.start(phymib_.getDIFS() + + rTime); + } + } + } else { + mhBackoff_.start(cw_, is_idle()); + + } + } +} + + +int +Mac802_11::check_pktASSOCREQ() +{ + struct hdr_mac802_11 *mh; + double timeout; + + assert(mhBackoff_.busy() == 0); + + if(pktASSOCREQ_ == 0) + return -1; + mh = HDR_MAC802_11(pktASSOCREQ_); + + switch(mh->dh_fc.fc_subtype) { + case MAC_Subtype_AssocReq: + if(! is_idle()) { + inc_cw(); + mhBackoff_.start(cw_, is_idle()); + return 0; + } + setTxState(MAC_MGMT); + timeout = txtime(phymib_.getASSOCREQlen(), basicRate_) + + DSSS_MaxPropagationDelay + + phymib_.getSIFS() + + txtime(phymib_.getASSOCREPlen(), basicRate_) + + DSSS_MaxPropagationDelay; +; + break; + default: + fprintf(stderr, "check_pktASSOCREQ:Invalid MAC Control subtype\n"); + exit(1); + } + + transmit(pktASSOCREQ_, timeout); + + + return 0; +} + +void +Mac802_11::sendASSOCREP(int dst) +{ + + Packet *p = Packet::alloc(); + hdr_cmn* ch = HDR_CMN(p); + struct assocrep_frame *acf =(struct assocrep_frame*)p->access(hdr_mac::offset_); + + pktASSOCREP_ = 0; + + ch->uid() = 0; + + + ch->ptype() = PT_MAC; + ch->size() = phymib_.getASSOCREPlen(); + ch->iface() = -2; + ch->error() = 0; + + bzero(acf, MAC_HDR_LEN); + + acf->acf_fc.fc_protocol_version = MAC_ProtocolVersion; + acf->acf_fc.fc_type = MAC_Type_Management; + acf->acf_fc.fc_subtype = MAC_Subtype_AssocRep; + acf->acf_fc.fc_to_ds = 0; + acf->acf_fc.fc_from_ds = 0; + acf->acf_fc.fc_more_frag= 0; + acf->acf_fc.fc_retry = 0; + acf->acf_fc.fc_pwr_mgt = 0; + acf->acf_fc.fc_more_data= 0; + acf->acf_fc.fc_wep = 0; + acf->acf_fc.fc_order = 0; + + STORE4BYTE(&dst, (acf->acf_ra)); + STORE4BYTE(&index_, (acf->acf_ta)); + STORE4BYTE(&index_, (acf->acf_3a)); + + acf->acf_statuscode = 0; + ch->txtime() = txtime(ch->size(), basicRate_); + acf->acf_duration = 0; + + + pktASSOCREP_ = p; + + +} + +int +Mac802_11::check_pktASSOCREP() +{ + + struct hdr_mac802_11 *mh; + double timeout; + + assert(mhBackoff_.busy() == 0); + + if(pktASSOCREP_ == 0) + return -1; + + mh = HDR_MAC802_11(pktASSOCREP_); + + switch(mh->dh_fc.fc_subtype) { + case MAC_Subtype_AssocRep: + if(!is_idle()) { + discard(pktASSOCREP_, DROP_MAC_BUSY); pktASSOCREP_ = 0; + return 0; + } + + setTxState(MAC_MGMT); + timeout = txtime(phymib_.getASSOCREPlen(), basicRate_); + break; + default: + fprintf(stderr, "check_pktASSOCREP:Invalid MAC Control subtype\n"); + exit(1); + } + + transmit(pktASSOCREP_, timeout); + return 0; +} + +void +Mac802_11::recvASSOCREQ(Packet *p) +{ + struct assocreq_frame *acf = (struct assocreq_frame*)p->access(hdr_mac::offset_); + + if(tx_state_ != MAC_IDLE) { + discard(p, DROP_MAC_BUSY); + return; + } + u_int32_t dst, bss_id, src, size; + struct hdr_cmn *ch = HDR_CMN(p); + + bss_id = ETHER_ADDR(acf->acf_3a); + src = ETHER_ADDR(acf->acf_ta); + bss_id_ = ap_addr; + update_ap_table(src); + sendASSOCREP(src); + + tx_resume(); + + mac_log(p); +} + +void +Mac802_11::recvASSOCREP(Packet *p) +{ + + struct assocrep_frame *acf = (struct assocrep_frame*)p->access(hdr_mac::offset_); + + assert(pktASSOCREQ_); + Packet::free(pktASSOCREQ_); + pktASSOCREQ_ = 0; + + mhSend_.stop(); + + u_int32_t dst, bss_id, src, size; + u_int16_t statuscode; + struct hdr_cmn *ch = HDR_CMN(p); + + bss_id_ = (u_int32_t)(ETHER_ADDR(acf->acf_3a)); + + + src = ETHER_ADDR(acf->acf_ta); + statuscode = acf->acf_statuscode; + + associated = 1; + + tx_resume(); + + mac_log(p); + + + +} + + +/* STA's beacon power table functions +*/ +void Mac802_11::add_beacon_table(int num, double power) { + + if (power_list == NULL) { + power_list = (struct beacon_table*)malloc(sizeof(struct beacon_table)); + power_list->ap_id=num; + power_list->beacon_power = power; + power_list->next=NULL; + } + else { + push_ap(num, power); + } + struct beacon_table *temp; + temp = power_list; + + while (temp != NULL) { + + temp=temp->next; + } +} + +void Mac802_11::push_ap(int num, double power) { + struct beacon_table *temp; + temp = power_list; + while (temp->next != NULL) { + + temp=temp->next; + } + temp->next = (struct beacon_table*)malloc(sizeof(struct beacon_table)); + temp->next->ap_id = num; + temp->next->beacon_power= power; + temp->next->next = NULL; +} + +int Mac802_11::strongest_beacon() { + struct beacon_table *temp; + double max_power; + int ap; + temp = power_list; + + while (temp != NULL) { + temp=temp->next; + } + + temp = power_list; + if (power_list == NULL) + return -1; + max_power = 0; + while (temp != NULL) { + if (temp->beacon_power > max_power) { + max_power = temp->beacon_power; + ap = temp->ap_id; + } + temp = temp->next; + } + + return ap; +} + +int Mac802_11::find_ap(int num, double power) { + struct beacon_table *temp; + temp = power_list; + while (temp != NULL) { + if (temp->ap_id == num) { + temp->beacon_power = power; + return 1; + } + + temp=temp->next; + + if (temp == NULL) { + return 0; + } + } +} + +void Mac802_11::deletelist( struct beacon_table *ptr ) +{ + struct beacon_table *temp; + + if( power_list == NULL ) return; + + while( ptr != NULL ) { + temp = ptr->next; + free( ptr ); + ptr = temp; + + } +} + + + diff -Naur ns-2.30/mac/mac-802_11.h ns-modified-2.30/mac/mac-802_11.h --- ns-2.30/mac/mac-802_11.h 2006-09-24 23:01:21.000000000 -0700 +++ ns-modified-2.30/mac/mac-802_11.h 2007-05-14 13:09:46.000000000 -0700 @@ -71,6 +71,12 @@ #define MAC_Subtype_Data 0x00 +#define MAC_Subtype_11_Beacon 0x08 +#define MAC_Subtype_AssocReq 0x00 +#define MAC_Subtype_AssocRep 0x01 + +#define SSID_LENGTH 32 + struct frame_control { u_char fc_subtype : 4; u_char fc_type : 2; @@ -108,6 +114,40 @@ u_char af_fcs[ETHER_FCS_LEN]; }; +struct beacon_frame { + struct frame_control bf_fc; + u_int16_t bf_duration; + u_char bf_ra[ETHER_ADDR_LEN]; + u_char bf_ta[ETHER_ADDR_LEN]; + u_char bf_3a[ETHER_ADDR_LEN]; + u_int16_t bf_scontrol; + double bf_timestamp; + double bf_beaconint; + u_int8_t bf_datarates[1]; + u_char bf_fcs[ETHER_FCS_LEN]; +}; + +struct assocreq_frame { + struct frame_control acf_fc; + u_int16_t acf_duration; + u_char acf_ra[ETHER_ADDR_LEN]; + u_char acf_ta[ETHER_ADDR_LEN]; + u_char acf_3a[ETHER_ADDR_LEN]; + u_int16_t acf_scontrol; + u_char acf_fcs[ETHER_FCS_LEN]; +}; + +struct assocrep_frame { + struct frame_control acf_fc; + u_int16_t acf_duration; + u_char acf_ra[ETHER_ADDR_LEN]; + u_char acf_ta[ETHER_ADDR_LEN]; + u_char acf_3a[ETHER_ADDR_LEN]; + u_int16_t acf_scontrol; + u_int16_t acf_statuscode; + u_char acf_fcs[ETHER_FCS_LEN]; +}; + // XXX This header does not have its header access function because it shares // the same header space with hdr_mac. struct hdr_mac802_11 { @@ -116,10 +156,22 @@ u_char dh_ra[ETHER_ADDR_LEN]; u_char dh_ta[ETHER_ADDR_LEN]; u_char dh_3a[ETHER_ADDR_LEN]; + u_char dh_4a[ETHER_ADDR_LEN]; u_int16_t dh_scontrol; u_char dh_body[1]; // size of 1 for ANSI compatibility }; +struct ap_table { + int node_id; + struct ap_table *next; +}; + +struct beacon_table { + int ap_id; + double beacon_power; + struct beacon_table *next; +}; + /* ====================================================================== Definitions @@ -138,6 +190,7 @@ inline u_int32_t getCWMin() { return(CWMin); } inline u_int32_t getCWMax() { return(CWMax); } inline double getSlotTime() { return(SlotTime); } + inline double getBeaconInterval() { return(BeaconInterval); } inline double getSIFS() { return(SIFSTime); } inline double getPIFS() { return(SIFSTime + SlotTime); } inline double getDIFS() { return(SIFSTime + 2 * SlotTime); } @@ -149,6 +202,7 @@ inline u_int32_t getPreambleLength() { return(PreambleLength); } inline double getPLCPDataRate() { return(PLCPDataRate); } + inline u_int32_t getPLCPhdrLen() { return((PreambleLength + PLCPHeaderLength) >> 3); } @@ -169,6 +223,15 @@ inline u_int32_t getACKlen() { return(getPLCPhdrLen() + sizeof(struct ack_frame)); } + inline u_int32_t getBEACONlen() { + return(getPLCPhdrLen() + sizeof(struct beacon_frame)); + } + inline u_int32_t getASSOCREQlen() { + return(getPLCPhdrLen() + sizeof(struct assocreq_frame)); + } + inline u_int32_t getASSOCREPlen() { + return(getPLCPhdrLen() + sizeof(struct assocrep_frame)); + } private: @@ -179,6 +242,7 @@ u_int32_t CWMax; double SlotTime; double SIFSTime; + double BeaconInterval; u_int32_t PreambleLength; u_int32_t PLCPHeaderLength; double PLCPDataRate; @@ -230,7 +294,7 @@ class Mac802_11 : public Mac { friend class DeferTimer; - + friend class BeaconTimer; friend class BackoffTimer; friend class IFTimer; friend class NavTimer; @@ -248,23 +312,38 @@ // Added by Sushmita to support event tracing void trace_event(char *, Packet *); EventTrace *et_; + int ap_addr; + u_char ssid_[SSID_LENGTH]; protected: void backoffHandler(void); void deferHandler(void); + void BeaconHandler(void); void navHandler(void); void recvHandler(void); void sendHandler(void); void txHandler(void); private: - int command(int argc, const char*const* argv); + void update_ap_table(int num); + void push(int num); + int find_node(int num); + void add_beacon_table(int num, double power); + void push_ap(int num, double power); + int strongest_beacon(); + int find_ap(int num, double power); + void deletelist(struct beacon_table *ptr); + int command(int argc, const char*const* argv); /* In support of bug fix described at * http://www.dei.unipd.it/wdyn/?IDsezione=2435 */ int bugFix_timer_; - + double BeaconTxtime_; + int associated; + double Pr; + int ap; + /* * Called by the timers. */ @@ -273,7 +352,9 @@ int check_pktCTRL(); int check_pktRTS(); int check_pktTx(); - + int check_pktASSOCREQ(); + int check_pktASSOCREP(); + int check_pktBEACON(); /* * Packet Transmission Functions. */ @@ -282,9 +363,12 @@ void sendCTS(int dst, double duration); void sendACK(int dst); void sendDATA(Packet *p); + void sendBEACON(int src); + void sendASSOCREQ(int dst); + void sendASSOCREP(int dst); void RetransmitRTS(); void RetransmitDATA(); - + /* * Packet Reception Functions. */ @@ -292,6 +376,9 @@ void recvCTS(Packet *p); void recvACK(Packet *p); void recvDATA(Packet *p); + void recvBEACON(Packet *p); + void recvASSOCREQ(Packet *p); + void recvASSOCREP(Packet *p); void capture(Packet *p); void collision(Packet *p); @@ -360,12 +447,15 @@ * purpose */ int bss_id_; + int scan_; enum {IBSS_ID=MAC_BROADCAST}; private: double basicRate_; double dataRate_; + struct ap_table *node_list; + struct beacon_table *power_list; /* * Mac Timers @@ -377,6 +467,7 @@ DeferTimer mhDefer_; // defer timer BackoffTimer mhBackoff_; // backoff timer + BeaconTimer mhBeacon_; // Beacon Timer /* ============================================================ Internal MAC State @@ -391,6 +482,9 @@ Packet *pktRTS_; // outgoing RTS packet Packet *pktCTRL_; // outgoing non-RTS packet + Packet *pktBEACON_; //outgoing Beacon Packet + Packet *pktASSOCREQ_; //Association request + Packet *pktASSOCREP_; // Association reply u_int32_t cw_; // Contention Window u_int32_t ssrc_; // STA Short Retry Count @@ -402,8 +496,6 @@ NsObject* EOTtarget_; // given a copy of packet at TX end - - /* ============================================================ Duplicate Detection state ============================================================ */ diff -Naur ns-2.30/mac/mac.h ns-modified-2.30/mac/mac.h --- ns-2.30/mac/mac.h 2006-09-24 23:01:21.000000000 -0700 +++ ns-modified-2.30/mac/mac.h 2007-05-14 12:10:16.000000000 -0700 @@ -83,9 +83,12 @@ MAC_RECV = 0x0010, MAC_SEND = 0x0100, MAC_RTS = 0x0200, + MAC_BCN = 0x0300, + MAC_BEACON = 0x0300, MAC_CTS = 0x0400, MAC_ACK = 0x0800, - MAC_COLL = 0x1000 + MAC_COLL = 0x1000, + MAC_MGMT = 0x1001 }; enum MacFrameType { diff -Naur ns-2.30/mac/mac-timers.cc ns-modified-2.30/mac/mac-timers.cc --- ns-2.30/mac/mac-timers.cc 2006-09-24 23:01:21.000000000 -0700 +++ ns-modified-2.30/mac/mac-timers.cc 2007-05-14 13:10:45.000000000 -0700 @@ -145,6 +145,39 @@ /* ====================================================================== + Beacon Timer + ====================================================================== */ +void +BeaconTimer::start(double time) +{ + Scheduler &s = Scheduler::instance(); + + assert(busy_ == 0); + + busy_ = 1; + paused_ = 0; + stime = s.clock(); + rtime = time; + + assert(rtime >= 0.0); + + s.schedule(this, &intr, rtime); +} + + +void +BeaconTimer::handle(Event *) +{ + busy_ = 0; + paused_ = 0; + stime = 0.0; + rtime = 0.0; + + mac->BeaconHandler(); +} + + +/* ====================================================================== NAV Timer ====================================================================== */ void @@ -234,8 +267,6 @@ rtime = (Random::random() % cw) * mac->phymib_.getSlotTime(); - - #ifdef USE_SLOT_TIME ROUND_TIME(); #endif @@ -244,6 +275,7 @@ if(idle == 0) paused_ = 1; else { + assert(rtime + difs_wait >= 0.0); s.schedule(this, &intr, rtime + difs_wait); } @@ -259,14 +291,16 @@ // looks dummy double st = s.clock(); + + double rt = stime + difs_wait; double sr = st - rt; double mst = (mac->phymib_.getSlotTime()); - - + int slots = int (sr/mst); - + + if(slots < 0) slots = 0; assert(busy_ && ! paused_); @@ -274,7 +308,7 @@ paused_ = 1; rtime -= (slots * mac->phymib_.getSlotTime()); - + assert(rtime >= 0.0); difs_wait = 0.0; @@ -303,6 +337,7 @@ ROUND_TIME(); #endif */ + assert(rtime + difs_wait >= 0.0); s.schedule(this, &intr, rtime + difs_wait); } diff -Naur ns-2.30/mac/mac-timers.h ns-modified-2.30/mac/mac-timers.h --- ns-2.30/mac/mac-timers.h 2006-09-24 23:01:21.000000000 -0700 +++ ns-modified-2.30/mac/mac-timers.h 2007-05-14 13:10:46.000000000 -0700 @@ -92,6 +92,14 @@ void handle(Event *e); }; +class BeaconTimer : public MacTimer { +public: + BeaconTimer(Mac802_11 *m) : MacTimer(m) {} + + void start(double); + void handle(Event *e); +}; + class IFTimer : public MacTimer { diff -Naur ns-2.30/tcl/ex/802.11/infra.tcl ns-modified-2.30/tcl/ex/802.11/infra.tcl --- ns-2.30/tcl/ex/802.11/infra.tcl 1969-12-31 16:00:00.000000000 -0800 +++ ns-modified-2.30/tcl/ex/802.11/infra.tcl 2007-05-16 15:46:33.000000000 -0700 @@ -0,0 +1,134 @@ +set val(chan) Channel/WirelessChannel ;#Channel Type +set val(prop) Propagation/TwoRayGround ;# radio-propagation model +set val(netif) Phy/WirelessPhy ;# network interface type +set val(mac) Mac/802_11 ;# MAC type +set val(ifq) Queue/DropTail ;# interface queue type +set val(ll) LL ;# link layer type +set val(ant) Antenna/OmniAntenna ;# antenna model +set val(ifqlen) 500 ;# max packet in ifq +set val(nn) 10 ;# number of mobilenodes +set val(rp) DumbAgent ;# routing protocol +set val(x) 50 +set val(y) 50 + +Mac/802_11 set dataRate_ 11Mb + +#Phy/WirelessPhy set CSThresh_ 10.00e-12 +#Phy/WirelessPhy set RXThresh_ 10.00e-11 +#Phy/WirelessPhy set Pt_ 0.1 +#Phy/WirelessPhy set Pt_ 7.214e-3 + +# Initialize Global Variables +set ns_ [new Simulator] +set tracefd [open infra.tr w] +$ns_ trace-all $tracefd + +#set namtrace [open 802.nam w] +#$ns_ namtrace-all-wireless $namtrace #$val(x) $val(y) + +# set up topography object +set topo [new Topography] + +$topo load_flatgrid $val(x) $val(y) + +# Create God +create-god $val(nn) + +# Create channel +set chan_1_ [new $val(chan)] + + +$ns_ node-config -adhocRouting $val(rp) \ + -llType $val(ll) \ + -macType $val(mac) \ + -ifqType $val(ifq) \ + -ifqLen $val(ifqlen) \ + -antType $val(ant) \ + -propType $val(prop) \ + -phyType $val(netif) \ + -topoInstance $topo \ + -agentTrace OFF \ + -routerTrace OFF \ + -macTrace ON \ + -movementTrace OFF \ + -channel $chan_1_ + + + for {set i 0} {$i < [expr $val(nn)]} {incr i} { + set node_($i) [$ns_ node] + + $node_($i) random-motion 0 ;# disable random motion + set mac_($i) [$node_($i) getMac 0] + + #$mac_($i) set dataRate_ 54Mb + #$mac_($i) set basicRate_ 24Mb + $mac_($i) set RTSThreshold_ 3000 + # $mac_($i) scanning OFF + $node_($i) set X_ $i + $node_($i) set Y_ 0 ;# Horizontal arrangement of nodes + $node_($i) set Z_ 0.0 + + } + +#Set Node 0 and Node $val(nn) as the APs. Thus the APs are the ends of the horizontal line. Each STA receives different power levels and hence Passive scanning can be observed. + +#Mac/802_11 set BeaconInterval_ 1.0 + +set AP_ADDR1 [$mac_(0) id] +$mac_(0) ap $AP_ADDR1 + + + +set AP_ADDR2 [$mac_([expr $val(nn) - 1]) id] +$mac_([expr $val(nn) - 1]) ap $AP_ADDR2 + + + +Application/Traffic/CBR set packetSize_ 1023 +Application/Traffic/CBR set rate_ 256Kb + + + +for {set i 1} {$i < [expr $val(nn) - 1]} {incr i} { + set udp1($i) [new Agent/UDP] + + $ns_ attach-agent $node_($i) $udp1($i) + set cbr1($i) [new Application/Traffic/CBR] + $cbr1($i) attach-agent $udp1($i) +} + +# Create connections between clients of the same BSS. + +set base0 [new Agent/Null] + +$ns_ attach-agent $node_(1) $base0 + +set base1 [new Agent/Null] + +$ns_ attach-agent $node_(8) $base1 + +$ns_ connect $udp1(4) $base0 +$ns_ connect $udp1(5) $base1 + + +$ns_ at 2.0 "$cbr1(4) start" + +$ns_ at 4.0 "$cbr1(5) start" + + +$ns_ at 40.0 "stop" +$ns_ at 40.0 "puts \"NS EXITING...\" ; $ns_ halt" + +proc stop {} { + global ns_ tracefd #namtrace + $ns_ flush-trace + close $tracefd + # close $namtrace + + # puts "running nam..." + # exec nam 802.nam & + exit 0 +} + +puts "Starting Simulation..." +$ns_ run diff -Naur ns-2.30/tcl/ex/802.11/infra.tcl~ ns-modified-2.30/tcl/ex/802.11/infra.tcl~ --- ns-2.30/tcl/ex/802.11/infra.tcl~ 1969-12-31 16:00:00.000000000 -0800 +++ ns-modified-2.30/tcl/ex/802.11/infra.tcl~ 2007-05-15 17:27:00.000000000 -0700 @@ -0,0 +1,134 @@ +set val(chan) Channel/WirelessChannel ;#Channel Type +set val(prop) Propagation/TwoRayGround ;# radio-propagation model +set val(netif) Phy/WirelessPhy ;# network interface type +set val(mac) Mac/802_11 ;# MAC type +set val(ifq) Queue/DropTail ;# interface queue type +set val(ll) LL ;# link layer type +set val(ant) Antenna/OmniAntenna ;# antenna model +set val(ifqlen) 500 ;# max packet in ifq +set val(nn) 10 ;# number of mobilenodes +set val(rp) DumbAgent ;# routing protocol +set val(x) 50 +set val(y) 50 + +Mac/802_11 set dataRate_ 11Mb + +#Phy/WirelessPhy set CSThresh_ 10.00e-12 +#Phy/WirelessPhy set RXThresh_ 10.00e-11 +#Phy/WirelessPhy set Pt_ 0.1 +#Phy/WirelessPhy set Pt_ 7.214e-3 + +# Initialize Global Variables +set ns_ [new Simulator] +set tracefd [open infra.tr w] +$ns_ trace-all $tracefd + +#set namtrace [open 802.nam w] +#$ns_ namtrace-all-wireless $namtrace #$val(x) $val(y) + +# set up topography object +set topo [new Topography] + +$topo load_flatgrid $val(x) $val(y) + +# Create God +create-god $val(nn) + +# Create channel +set chan_1_ [new $val(chan)] + + +$ns_ node-config -adhocRouting $val(rp) \ + -llType $val(ll) \ + -macType $val(mac) \ + -ifqType $val(ifq) \ + -ifqLen $val(ifqlen) \ + -antType $val(ant) \ + -propType $val(prop) \ + -phyType $val(netif) \ + -topoInstance $topo \ + -agentTrace OFF \ + -routerTrace OFF \ + -macTrace ON \ + -movementTrace OFF \ + -channel $chan_1_ + + + for {set i 0} {$i < [expr $val(nn)]} {incr i} { + set node_($i) [$ns_ node] + + $node_($i) random-motion 0 ;# disable random motion + set mac_($i) [$node_($i) getMac 0] + + #$mac_($i) set dataRate_ 54Mb + #$mac_($i) set basicRate_ 24Mb + $mac_($i) set RTSThreshold_ 3000 + # $mac_($i) scanning OFF + $node_($i) set X_ $i + $node_($i) set Y_ 0 ;# Horizontal arrangement of nodes + $node_($i) set Z_ 0.0 + + } + +#Set Node 0 and Node $val(nn) as the APs. Thus the APs are the ends of the horizontal line. Each STA receives different power levels and hence Passive scanning can be observed. + +#Mac/802_11 set BeaconInterval_ 1.0 + +#set AP_ADDR1 [$mac_(0) id] +#$mac_(0) ap $AP_ADDR1 + + + +#set AP_ADDR2 [$mac_([expr $val(nn) - 1]) id] +#$mac_([expr $val(nn) - 1]) ap $AP_ADDR2 + + + +Application/Traffic/CBR set packetSize_ 1023 +Application/Traffic/CBR set rate_ 256Kb + + + +for {set i 1} {$i < [expr $val(nn) - 1]} {incr i} { + set udp1($i) [new Agent/UDP] + + $ns_ attach-agent $node_($i) $udp1($i) + set cbr1($i) [new Application/Traffic/CBR] + $cbr1($i) attach-agent $udp1($i) +} + +# Create connections between clients of the same BSS. + +set base0 [new Agent/Null] + +$ns_ attach-agent $node_(1) $base0 + +set base1 [new Agent/Null] + +$ns_ attach-agent $node_(8) $base1 + +$ns_ connect $udp1(4) $base0 +$ns_ connect $udp1(5) $base1 + + +$ns_ at 2.0 "$cbr1(4) start" + +$ns_ at 4.0 "$cbr1(5) start" + + +$ns_ at 40.0 "stop" +$ns_ at 40.0 "puts \"NS EXITING...\" ; $ns_ halt" + +proc stop {} { + global ns_ tracefd #namtrace + $ns_ flush-trace + close $tracefd + # close $namtrace + + # puts "running nam..." + # exec nam 802.nam & + exit 0 +} + +puts "Starting Simulation..." +$ns_ run diff -Naur ns-2.30/tcl/lib/ns-default.tcl ns-modified-2.30/tcl/lib/ns-default.tcl --- ns-2.30/tcl/lib/ns-default.tcl 2006-09-24 23:01:16.000000000 -0700 +++ ns-modified-2.30/tcl/lib/ns-default.tcl 2007-05-14 13:11:44.000000000 -0700 @@ -672,6 +672,7 @@ Mac/802_11 set CWMax_ 1023 Mac/802_11 set SlotTime_ 0.000020 ;# 20us Mac/802_11 set SIFS_ 0.000010 ;# 10us + Mac/802_11 set BeaconInterval_ 0.1 ;# 100 ms Mac/802_11 set PreambleLength_ 144 ;# 144 bit Mac/802_11 set PLCPHeaderLength_ 48 ;# 48 bits Mac/802_11 set PLCPDataRate_ 1.0e6 ;# 1Mbps diff -Naur ns-2.30/trace/cmu-trace.cc ns-modified-2.30/trace/cmu-trace.cc --- ns-2.30/trace/cmu-trace.cc 2006-09-24 23:01:14.000000000 -0700 +++ ns-modified-2.30/trace/cmu-trace.cc 2007-05-14 13:11:31.000000000 -0700 @@ -253,8 +253,11 @@ (mh->dh_fc.fc_subtype == MAC_Subtype_RTS) ? "RTS" : (mh->dh_fc.fc_subtype == MAC_Subtype_CTS) ? "CTS" : (mh->dh_fc.fc_subtype == MAC_Subtype_ACK) ? "ACK" : + (mh->dh_fc.fc_subtype == MAC_Subtype_11_Beacon) ? "BCN" : //Beacon + (mh->dh_fc.fc_subtype == MAC_Subtype_AssocReq) ? "ACRQ" : //Association request + (mh->dh_fc.fc_subtype == MAC_Subtype_AssocRep) ? "ACRP" : //Association Response // - (mh->dh_fc.fc_subtype == MAC_Subtype_Beacon) ? "BCN" : //Beacon +// (mh->dh_fc.fc_subtype == MAC_Subtype_Beacon) ? "BCN" : //Beacon (mh->dh_fc.fc_subtype == MAC_Subtype_Command_AssoReq) ? "CM1" : //CMD: Association request (mh->dh_fc.fc_subtype == MAC_Subtype_Command_AssoRsp) ? "CM2" : //CMD: Association response (mh->dh_fc.fc_subtype == MAC_Subtype_Command_DAssNtf) ? "CM3" : //CMD: Disassociation notification