📄 mac-802_11e.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. */#undef NDEBUG#include <assert.h>#include "delay.h"#include "connector.h"#include "packet.h"#include "random.h"#include "mobilenode.h"#include "stream.h"#include "arp.h"//#include "ll.h"//#include "mac.h"#include "mac-timers_802_11e.h"#include "mac-802_11e.h"#include "cmu-trace.h"#include "priq.h"//include the following line when using Akaroa//#include "akaroa.H"#define AKAROA 0 #define AK_INTERVAL 0.01 inline voidMac802_11e::set_rx_state(MacState x){ rx_state_ = x; check_backoff_timer();}inline voidMac802_11e::set_tx_state(int pri, MacState x){ tx_state_[pri] = x;}inline voidMac802_11e::transmit(Packet *p, double t){ /* * 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) { struct hdr_mac802_11e *dh = HDR_MAC802_11E(p); 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. */ struct hdr_cmn *sd = HDR_CMN(p); int prio = LEVEL(p); tx_active_ = 1; sending = 1; check_backoff_timer(); downtarget_->recv(p->copy(), this); if(sd->ptype() == PT_CBR || sd->ptype() == PT_EXP) { if(!rtx_[prio]){ numbytes_[prio] += sd->size() - phymib_.getHdrLen11(); } } mhIF_.start(txtime(p)); mhSend_.start(t); } void Mac802_11e::check_backoff_timer(){ if(is_idle() && mhBackoff_.paused()) { mhBackoff_.resume(); } if(! is_idle() && mhBackoff_.busy() && ! mhBackoff_.paused()){ mhBackoff_.pause(); } if(!is_idle() && mhDefer_.busy()) mhDefer_.stop();}/* ====================================================================== Global Variables ====================================================================== */EDCA_PHY_MIB::EDCA_PHY_MIB(Mac802_11e *parent){ /* * Bind the phy mib objects. Note that these will be bound * to Mac/802_11e variables */ parent->bind("SlotTime_", &SlotTime); parent->bind("SIFS_", &SIFSTime); parent->bind("PreambleLength_", &PreambleLength); parent->bind("PLCPHeaderLength_", &PLCPHeaderLength); parent->bind_bw("PLCPDataRate_", &PLCPDataRate);}EDCA_MAC_MIB::EDCA_MAC_MIB(Mac802_11e *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);}/* ====================================================================== TCL Hooks for the simulator ====================================================================== */static class Mac802_11eClass : public TclClass {public: Mac802_11eClass() : TclClass("Mac/802_11e") {} TclObject* create(int, const char*const*) { return (new Mac802_11e()); }} class_mac802_11e;/* ====================================================================== Mac Class Functions ====================================================================== */Mac802_11e::Mac802_11e() : Mac(), phymib_(this), macmib_(this), mhIF_(this), mhNav_(this), mhRecv_(this), mhSend_(this), mhDefer_(this, phymib_.getSlotTime()), mhSifs_(this, phymib_.getSlotTime()), mhBackoff_(this, phymib_.getSlotTime()), AK(this){ // Pointer to PriQ, Cast in priq.cc queue_ = 0; //flags to control if PriQ Parameters have already been adopted AIFSset = 0; CWset = 0; for(int i=0; i < MAX_PRI; i++){ packets_[i] = 0; pktRTS_[i] = 0; pktCTRL_[i] = 0; pktTx_[i] = 0; tx_state_[i] = MAC_IDLE; ssrc_[i] = slrc_[i] = 0; callback_[i] = 0; numbytes_[i] = 0; rtx_[i] = 0; cw_[i] = 0; cwmin_[i] = 0; cwmax_[i] = 0; aifs_[i] = 0; txop_limit_[i] = 0; start_handle_[i] = 0; } jitter = 1000; //jitter = 0; throughput = 0; interval_ = AK_INTERVAL; if(AKAROA) AK.start(); nav_ = 0.0; rx_state_ = MAC_IDLE; tx_active_ = 0; idle_time = 0; sending = 0; cfb_dur = 0; cfb_active = 0; cfb_broadcast = 0; levels = 0; slotnum = 0; pf = 0; cw_old = 0; sifs_ = phymib_.getSIFS(); pifs_ = phymib_.getPIFS(); difs_ = phymib_.getDIFS(); // see (802.11-1999, 9.2.10) eifs_ = phymib_.getDIFS(); eifs_nav_ = 0; 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_11e set basicRate_"); if (strcmp(tcl.result(), "0") != 0) bind_bw("basicRate_", &basicRate_); else basicRate_ = bandwidth_; tcl.evalf("Mac/802_11e set dataRate_"); if (strcmp(tcl.result(), "0") != 0) bind_bw("dataRate_", &dataRate_); else dataRate_ = bandwidth_; bind("cfb_", &cfb_);}intMac802_11e::command(int argc, const char*const* argv){ if (argc == 3) { 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; } } return Mac::command(argc, argv);}/* ====================================================================== Debugging Routines ====================================================================== *//* * dump and packet trace are not adopted to 802.11e yet! */voidMac802_11e::trace_pkt(Packet *p) { struct hdr_cmn *ch = HDR_CMN(p); struct hdr_mac802_11e* dh = HDR_MAC802_11E(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_da), ETHER_ADDR(dh->dh_sa), index_, packet_info.name(ch->ptype()), ch->size());}voidMac802_11e::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_: %x, pktRx_: %x, pktRTS_: %x, pktCTRL_: %x, callback: %x\n", (int) pktTx_, (int) pktRx_, (int) pktRTS_, (int) pktCTRL_, (int) 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_11e::hdr_dst(char* hdr, int dst ){ struct hdr_mac802_11e *dh = (struct hdr_mac802_11e*) hdr; //dst = (u_int32_t)(dst); if(dst > -2) STORE4BYTE(&dst, (dh->dh_da)); return ETHER_ADDR(dh->dh_da);}inline int Mac802_11e::hdr_src(char* hdr, int src ){ struct hdr_mac802_11e *dh = (struct hdr_mac802_11e*) hdr; if(src > -2) STORE4BYTE(&src, (dh->dh_sa)); return ETHER_ADDR(dh->dh_sa);}inline int Mac802_11e::hdr_type(char* hdr, u_int16_t type){ struct hdr_mac802_11e *dh = (struct hdr_mac802_11e*) hdr; if(type) STORE2BYTE(&type,(dh->dh_body)); return GET2BYTE(dh->dh_body);}/* ====================================================================== Misc Routines ====================================================================== */inline intMac802_11e::is_idle(){ if(rx_state_ != MAC_IDLE){ idle_time = 0; return 0; } if(sending) { idle_time = 0; return 0; } if(nav_ > Scheduler::instance().clock()){ idle_time = 0; return 0; } idle_time = Scheduler::instance().clock(); return 1;}voidMac802_11e::discard(Packet *p, const char* why){ hdr_mac802_11e* mh = HDR_MAC802_11E(p); hdr_cmn *ch = HDR_CMN(p);#if 0 /* old logic 8/8/98 -dam */ /* * If received below the RXThreshold, then just free. */ if(p->txinfo_.Pr < p->txinfo_.ant.RXThresh) { Packet::free(p); //p = 0; return; }#endif // 0 /* 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); //p = 0; 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_sa) == \ (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_da) == \ (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_da) == \ (u_int32_t)index_ || (u_int32_t)ETHER_ADDR(mh->dh_sa) == \ (u_int32_t)index_ || (u_int32_t)ETHER_ADDR(mh->dh_da) == MAC_BROADCAST) { drop(p); 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);}voidMac802_11e::capture(Packet *p){ /* * Update the NAV so that this does not screw * up carrier sense. */ set_nav(usec(eifs_ + txtime(p))); Packet::free(p);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -