📄 mac-802_11_unicst.cc
字号:
/* -*- 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"// VIVEK_ARFdouble link_SINR[NUM_DISCRETE_RATES] = {dBtomW(6.02), dBtomW(7.78), dBtomW(9.03), dBtomW(10.79), dBtomW(17.04), dBtomW(18.80), dBtomW(24.05), dBtomW(24.56)}; // SINRdouble link_bitrate[NUM_DISCRETE_RATES] = {6000000.0, 9000000.0, 12000000.0, 18000000.0, 24000000.00, 36000000.00, 48000000.00, 54000000.00}; // Corresponding Rate// VIVEK_ARF/* 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 voidMac802_11::checkBackoffTimer(){ if(is_idle() && mhBackoff_.paused()) mhBackoff_.resume(phymib_.getDIFS()); if(! is_idle() && mhBackoff_.busy() && ! mhBackoff_.paused()) mhBackoff_.pause();}inline voidMac802_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 voidMac802_11::setRxState(MacState newState){ rx_state_ = newState; checkBackoffTimer();}inline voidMac802_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){// int i; 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;// VIVEK MULTI-RATE, MULTI-SINR MODULE counter_ = 0; noise_ = dBtomW(DEFAULT_NOISE_POWER);// VIVEK MULTI-RATE, MULTI-SINR MODULE // 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_);}intMac802_11::command(int argc, const char*const* argv){// VIVEK MULTI-RATE, MULTI-SINR MODULE// $mac setup-link [$node2 id] <AUTO_RATE_ALGO> <INIT_INDEX>; if ((argc == 5) && (strcmp(argv[1], "setup-link") == 0)) { if ((atoi(argv[2]) < 0) || (atoi(argv[4]) > 7) ||(atoi(argv[4]) < 0) || (counter_ == MAXNHBR)) return TCL_ERROR; ARF_Entry[counter_].MAC_ID = (u_int32_t) atoi(argv[2]); ARF_Entry[counter_].rate_index = atoi(argv[4]); ARF_Entry[counter_].num_success = 0; ARF_Entry[counter_].num_failed = 0; ARF_Entry[counter_].probing_tx = 0; ARF_Entry[counter_].success_thresh = ARF_SUCCESS_THRESHOLD; if(atoi(argv[3]) == AUTO_RATE_ARF) ARF_Entry[counter_].algorithm = AUTO_RATE_ARF; else if (atoi(argv[3]) == AUTO_RATE_AARF) ARF_Entry[counter_].algorithm = AUTO_RATE_AARF; else if (atoi(argv[3]) == AUTO_RATE_NONE){ ARF_Entry[counter_].algorithm = AUTO_RATE_NONE; ARF_Entry[counter_].rate_index = atoi(argv[4]); } else return TCL_ERROR; ARF_Entry[counter_].timer = ARF_TIMEOUT; // Init timer// printf("Node[%d].%d: Setting rate=%f and CPThresh=%f for link %d->%d\n", addr(), counter_, dataRateNhbr_[counter_], CPThreshNhbr_[counter_], IdNhbr_[counter_], addr());// printf("Node[%d].%d: Setting MAC_ID=%d, rate_index=%d and timer=%d for link %d->%d\n", addr(), counter_, ARF_Entry[counter_].MAC_ID, ARF_Entry[counter_].rate_index, ARF_Entry[counter_].timer, IdNhbr_[counter_], addr()); counter_++; return TCL_OK; } if (argc == 3) { if (strcmp(argv[1], "set-noise") == 0) { noise_ = atof(argv[2]); // Set noise power if(noise_ < 0.0)// Entered value in dB noise_ = dBtomW(noise_); return TCL_OK;// VIVEK MULTI-RATE, MULTI-SINR MODULE } else 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 tracingvoid 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 ====================================================================== */voidMac802_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());}voidMac802_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 intMac802_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 intMac802_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;}voidMac802_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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -