📄 mac-802_11.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: /u23/ns-user/cvsroot/ns-2/mac-802_11.cc,v 1.1.1.1.6.3 2001/08/20 12:04:14 dugdale Exp $ * * Ported from CMU/Monarch's code, nov'98 -Padma. *//* * Code contained within lines such as the below * // wqos - <date> - dugdale // wqos - changes by dugdale ends * * or * // wqos - <date> - almquist // wqos - changes by almquist ends * * have been changed or added to implement the PCF mode of IEEE 802.11 and is * Copyright (c) 2001 Anders Lindgren and Andreas Almquist. * * 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 above disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the above disclaimer in the * documentation and/or other materials provided with the distribution. * * The disclaimer above apply to the modifications made to the source code * by Anders Lindgren and Andreas Almquist as well as to the rest of the code. */#include "delay.h"#include "connector.h"#include "packet.h"#include "random.h"#include "mobilenode.h"// #define DEBUG#include "arp.h"#include "ll.h"#include "mac.h"#include "mac-timers.h"#include "mac-802_11.h"#include "cmu-trace.h"// XXX Can't we make these macros inline methods? Otherwise why should we have// inline methods at all??#define CHECK_BACKOFF_TIMER() \{ \ if(is_idle() && mhBackoff_.paused()) \ mhBackoff_.resume(difs_); \ if(! is_idle() && mhBackoff_.busy() && ! mhBackoff_.paused()) \ mhBackoff_.pause(); \}#define TRANSMIT(p, t) \{ \ tx_active_ = 1; \ \ /* \ * 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_11 *dh = HDR_MAC802_11(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. \ */ \ downtarget_->recv(p->copy(), this); \ \ mhSend_.start(t); \ \ mhIF_.start(TX_Time(p)); \}#define SET_RX_STATE(x) \{ \ rx_state_ = (x); \ CHECK_BACKOFF_TIMER(); \}#define SET_TX_STATE(x) \{ \ tx_state_ = (x); \ CHECK_BACKOFF_TIMER(); \}/* ====================================================================== Global Variables ====================================================================== */static PHY_MIB PMIB ={ DSSS_CWMin, DSSS_CWMax, DSSS_SlotTime, DSSS_CCATime, DSSS_RxTxTurnaroundTime, DSSS_SIFSTime, DSSS_PreambleLength, DSSS_PLCPHeaderLength}; static MAC_MIB MMIB ={ 0 /* MAC_RTSThreshold */, MAC_ShortRetryLimit, MAC_LongRetryLimit, MAC_FragmentationThreshold, MAC_MaxTransmitMSDULifetime, MAC_MaxReceiveLifetime, // wqos - Wed 04 Oct 00, 11:10 - dugdale 0 /* CF Pollable */, 1 /* CFP Period */, 15 /* CFP Max Duration*/, 20 /* BeaconPeriod */, 0 /* DTIM Period */, // wqos - changes by dugdale ends 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};/* ====================================================================== 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(&PMIB, &MMIB)); }} class_mac802_11;/* ====================================================================== Mac Class Functions ====================================================================== */Mac802_11::Mac802_11(PHY_MIB *p, MAC_MIB *m) : Mac(), mhIF_(this), mhNav_(this), mhRecv_(this), mhSend_(this), mhDefer_(this, p->SlotTime), mhBackoff_(this, p->SlotTime),// wqos - Sat 18 Aug 01, 16:49 - dugdale mhBeacon_(this) // wqos - changes by dugdale ends{ macmib_ = m; phymib_ = p; nav_ = 0.0; tx_state_ = rx_state_ = MAC_IDLE; tx_active_ = 0; pktRTS_ = 0; pktCTRL_ = 0; cw_ = phymib_->CWMin; ssrc_ = slrc_ = 0; sifs_ = phymib_->SIFSTime; pifs_ = sifs_ + phymib_->SlotTime; difs_ = sifs_ + 2*phymib_->SlotTime; eifs_ = sifs_ + difs_ + DATA_Time(ETHER_ACK_LEN + phymib_->PreambleLength/8 + phymib_->PLCPHeaderLength/8); tx_sifs_ = sifs_ - phymib_->RxTxTurnaroundTime; tx_pifs_ = tx_sifs_ + phymib_->SlotTime; tx_difs_ = tx_sifs_ + 2 * phymib_->SlotTime; sta_seqno_ = 1; cache_ = 0; cache_node_count_ = 0; // wqos - Fri 06 Oct 00, 10:29 - dugdale pc_=0; dtimcount_=0; cfp_=0; cfpcount_ = macmib_->dot11CFPPeriod; pktPCF_ = 0; pollList_=0; pollsToSend_=0; btbs_=0; // wqos - changes by dugdale ends} intMac802_11::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; }// wqos - Sat 18 Aug 01, 12:39 - dugdale // If this node is a base station, add a station to its polling list else if(strcmp(argv[1], "addSTA") == 0){ if(pc_) { int macId = atoi(argv[2]); int cfPollable = atoi(argv[3]); int cfPollReq = atoi(argv[4]); pollList_->insertNode(macId, cfPollable, cfPollReq); // TODO: Some debug printouts and errorchecking. // free(tmpstr); return TCL_OK; } else return TCL_ERROR; } // If this node is a base station, remove a station from its polling list else if(strcmp(argv[1], "remSTA") == 0){ if(pc_) { int macId = atoi(argv[2]); if(pollList_->deleteNode(macId)==0) return TCL_OK; else return TCL_ERROR; } else return TCL_ERROR; } // Sets the beacon period else if(strcmp(argv[1], "beaconperiod") == 0){ macmib_->dot11BeaconPeriod = atoi(argv[2]); // Calculate the maximum length of a CFP (the CFP interval - the time // to send a maximum length frame) // (Each beacon starts a CFP) macmib_->dot11CFPMaxDuration = macmib_->dot11CFPPeriod*(macmib_->dot11DTIMPeriod+1)*macmib_->dot11BeaconPeriod - tu(2346/bandwidth_); return TCL_OK; } } else if(argc==2) { // Let this node be the Point Coordinator if(strcmp(argv[1], "make-pc") == 0) { pc_=1; if(!pollList_) pollList_ = new PCFPollList(); mhBeacon_.start(macmib_->dot11BeaconPeriod*0.001024); return TCL_OK; } } // wqos - changes by dugdale ends return Mac::command(argc, argv);}/* ====================================================================== 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_da), ETHER_ADDR(dh->dh_sa), 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_: %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_11::hdr_dst(char* hdr, int dst ){ struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr; //dst = (u_int32_t)(dst); if(dst > -2) STORE4BYTE(&dst, (dh->dh_da)); return ETHER_ADDR(dh->dh_da);}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_sa)); return ETHER_ADDR(dh->dh_sa);}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 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;// wqos - Sat 18 Aug 01, 17:17 - dugdale case MAC_Subtype_CFEnd: case MAC_Subtype_CFEnd_CFACK: break; // wqos - changes by dugdale ends 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;// wqos - Sat 18 Aug 01, 17:17 - dugdale case MAC_Subtype_Data_CFACK: case MAC_Subtype_Data_CFACK_CFPoll: case MAC_Subtype_NullFunction: case MAC_Subtype_CFACK: case MAC_Subtype_CFPoll: case MAC_Subtype_CFACK_CFPoll: break;// wqos - changes by dugdale ends 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_11::capture(Packet *p){ /* * Update the NAV so that this does not screw * up carrier sense. */ set_nav(usec(eifs_ + TX_Time(p))); Packet::free(p);}voidMac802_11::collision(Packet *p){ switch(rx_state_) { case MAC_RECV: SET_RX_STATE(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(TX_Time(p) > mhRecv_.expire()) { mhRecv_.stop(); discard(pktRx_, DROP_MAC_COLLISION); pktRx_ = p; mhRecv_.start(TX_Time(pktRx_)); } else { discard(p, DROP_MAC_COLLISION); } break; default: assert(0); }}voidMac802_11::tx_resume(){ assert(mhSend_.busy() == 0); assert(mhDefer_.busy() == 0); // wqos - Thu 09 Nov 00, 09:55 - dugdale if(btbs_) { // Make sure beacons are sent... btbs_=0; send_beacon(); } // wqos - changes by dugdale ends if(pktCTRL_) { /* * Need to send a CTS or ACK. */ mhDefer_.start(sifs_); } // wqos - Tue 10 Oct 00, 14:17 - dugdale else if(pktPCF_) { // We have been polled, and should send a packet // if(mhBackoff_.busy() && !mhBackoff_.paused()) // Should we really do this?? if(mhBackoff_.busy()) // Should we really do this?? mhBackoff_.stop(); // Pausing // mhBackoff_.pause(); // Pausing mhDefer_.start(sifs_); // We should only wait a SIFS to send this... } // wqos - changes by dugdale ends else if(pktRTS_) { if(mhBackoff_.busy() == 0) mhDefer_.start(difs_); } else if(pktTx_) { if(mhBackoff_.busy() == 0) mhDefer_.start(difs_); } else if(callback_) { Handler *h = callback_; callback_ = 0; h->handle((Event*) 0); } SET_TX_STATE(MAC_IDLE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -