📄 mac-802_11.cc
字号:
/* mac-802_11.cc $Id: mac-802_11.cc,v 1.19 1998/11/19 06:22:10 dmaltz Exp $ */#include <delay.h>#include <connector.h>#include <packet.h>#include <random.h>// #define DEBUG#include <cmu/debug.h>#include <cmu/arp.h>#include <cmu/ll.h> #include <cmu/mac.h>#include <cmu/mac-timers.h>#include <cmu/mac-802_11.h>#include <cmu/cmu-trace.h>/* ====================================================================== Macros ====================================================================== */#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_MAC(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. \ */ \ sendtarget_->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 ====================================================================== */extern char* pt_names[];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, 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){ 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;} 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; } 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 ====================================================================== */voidMac802_11::trace_pkt(Packet *p) { struct hdr_cmn *ch = HDR_CMN(p); struct hdr_mac802_11* dh = HDR_MAC(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, pt_names[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, upcall: %x\n", (int) pktTx, (int) pktRx, (int) pktRTS, (int) pktCTRL, (int) upcall_); 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, u_int32_t dst){ struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr; if(dst) ETHER_ADDR(dh->dh_da) = dst; return ETHER_ADDR(dh->dh_da);}inline int Mac802_11::hdr_src(char* hdr, u_int32_t src){ struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr; if(src) ETHER_ADDR(dh->dh_sa) = src; 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) SET_ETHER_TYPE(dh->dh_body, type); return GET_ETHER_TYPE(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_MAC(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); 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); 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(ETHER_ADDR(mh->dh_sa) == index) { drop(p, why); return; } /* fall through - if necessary */ case MAC_Subtype_CTS: case MAC_Subtype_ACK: if(ETHER_ADDR(mh->dh_da) == 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(ETHER_ADDR(mh->dh_da) == index || ETHER_ADDR(mh->dh_sa) == index || ETHER_ADDR(mh->dh_da) == 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);}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); if(pktCTRL) { /* * Need to send a CTS or ACK. */ mhDefer.start(sifs); } else if(pktRTS) { if(mhBackoff.busy() == 0) mhDefer.start(difs); } else if(pktTx) { if(mhBackoff.busy() == 0) mhDefer.start(difs); } else if(upcall_) { Handler *h = upcall_; upcall_ = 0; h->handle((Event*) 0); } SET_TX_STATE(MAC_IDLE);}voidMac802_11::rx_resume(){ assert(pktRx == 0); assert(mhRecv.busy() == 0); SET_RX_STATE(MAC_IDLE);}/* ====================================================================== Timer Handler Routines ====================================================================== */voidMac802_11::backoffHandler(){ if(pktCTRL) { assert(mhSend.busy() || mhDefer.busy()); return; } if(check_pktRTS() == 0) return; if(check_pktTx() == 0) return;}voidMac802_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;}voidMac802_11::navHandler(){ if(is_idle() && mhBackoff.paused()) mhBackoff.resume(difs);}voidMac802_11::recvHandler(){ recv_timer();}voidMac802_11::sendHandler(){ send_timer();}voidMac802_11::txHandler(){ tx_active = 0;}/* ====================================================================== The "real" Timer Handler Routines ====================================================================== */voidMac802_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 ====================================================================== */intMac802_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_MAC(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; } SET_TX_STATE(MAC_CTS); timeout = (mh->dh_duration * 1e-6) + CTS_Time; // XXX 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: SET_TX_STATE(MAC_ACK); timeout = ACK_Time; break; default: fprintf(stderr, "Invalid MAC Control subtype\n"); exit(1); } TRANSMIT(pktCTRL, timeout); return 0;}intMac802_11::check_pktRTS(){ struct hdr_mac802_11 *mh; double timeout; assert(mhBackoff.busy() == 0); if(pktRTS == 0) return -1; mh = HDR_MAC(pktRTS); switch(mh->dh_fc.fc_subtype) { case MAC_Subtype_RTS: if(! is_idle()) { inc_cw(); mhBackoff.start(cw, is_idle()); return 0; } SET_TX_STATE(MAC_RTS); timeout = CTSTimeout; break; default: fprintf(stderr, "Invalid MAC Control subtype\n"); exit(1); } TRANSMIT(pktRTS, timeout); return 0;}intMac802_11::check_pktTx(){ struct hdr_mac802_11 *mh; double timeout; assert(mhBackoff.busy() == 0); if(pktTx == 0) return -1; mh = HDR_MAC(pktTx); int len = HDR_CMN(pktTx)->size(); switch(mh->dh_fc.fc_subtype) { case MAC_Subtype_Data: if(! is_idle()) { sendRTS(ETHER_ADDR(mh->dh_da)); inc_cw(); mhBackoff.start(cw, is_idle()); return 0; } SET_TX_STATE(MAC_SEND); if(ETHER_ADDR(mh->dh_da) != MAC_BROADCAST) timeout = ACKTimeout(len); else timeout = TX_Time(pktTx); break; default: fprintf(stderr, "Invalid MAC Control subtype\n"); exit(1); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -