📄 mac-802_11.cc
字号:
TRANSMIT(pktTx, timeout); return 0;}/* * Low-level transmit functions that actually place the packet onto * the channel. */voidMac802_11::sendRTS(int dst){ Packet *p = Packet::alloc(); hdr_cmn* ch = HDR_CMN(p); struct rts_frame *rf = (struct rts_frame*)p->access(off_mac_); assert(pktTx); assert(pktRTS == 0); /* * If the size of the packet is larger than the * RTSThreshold, then perform the RTS/CTS exchange. * * XXX: also skip if destination is a broadcast */ if( (u_int32_t) HDR_CMN(pktTx)->size() < macmib->RTSThreshold || (u_int32_t) dst == MAC_BROADCAST) { Packet::free(p); return; } ch->uid() = 0; ch->ptype() = PT_MAC; ch->size() = ETHER_RTS_LEN; 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); ETHER_ADDR(rf->rf_ra) = dst; ETHER_ADDR(rf->rf_ta) = index; // rf->rf_fcs; pktRTS = p;}voidMac802_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(off_mac_); assert(pktCTRL == 0); ch->uid() = 0; ch->ptype() = PT_MAC; ch->size() = ETHER_CTS_LEN; ch->iface() = -2; ch->error() = 0; 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); ETHER_ADDR(cf->cf_ra) = dst; // cf->cf_fcs; pktCTRL = p;}voidMac802_11::sendACK(int dst){ Packet *p = Packet::alloc(); hdr_cmn* ch = HDR_CMN(p); struct ack_frame *af = (struct ack_frame*)p->access(off_mac_); assert(pktCTRL == 0); ch->uid() = 0; ch->ptype() = PT_MAC; ch->size() = ETHER_ACK_LEN; 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(); ETHER_ADDR(af->af_ra) = dst; // af->af_fcs; pktCTRL = p;}voidMac802_11::sendDATA(Packet *p){ hdr_cmn* ch = HDR_CMN(p); struct hdr_mac802_11* dh = HDR_MAC(p); assert(pktTx == 0); /* * Update the MAC header */ ch->size() += ETHER_HDR_LEN; 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; if(ETHER_ADDR(dh->dh_da) != MAC_BROADCAST) dh->dh_duration = DATA_DURATION(); else dh->dh_duration = 0; pktTx = p;}/* ====================================================================== Retransmission Routines ====================================================================== */voidMac802_11::RetransmitRTS(){ assert(pktTx); assert(pktRTS); assert(mhBackoff.busy() == 0); macmib->RTSFailureCount++; ssrc += 1; // STA Short Retry Count if(ssrc >= macmib->ShortRetryLimit) { 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() -= ETHER_HDR_LEN; 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(off_mac_); rf->rf_fc.fc_retry = 1; inc_cw(); mhBackoff.start(cw, is_idle()); }}voidMac802_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_MAC(pktTx); /* * Broadcast packets don't get ACKed and therefore * are never retransmitted. */ if(ETHER_ADDR(mh->dh_da) == 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->RTSThreshold) { rcount = &ssrc; thresh = &macmib->ShortRetryLimit; } else { rcount = &slrc; thresh = &macmib->LongRetryLimit; } (*rcount)++; if(*rcount > *thresh) { 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() -= ETHER_HDR_LEN; 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_MAC(pktTx); dh->dh_fc.fc_retry = 1; sendRTS(ETHER_ADDR(mh->dh_da)); inc_cw(); mhBackoff.start(cw, is_idle()); }}/* ====================================================================== Incoming Packet Routines ====================================================================== */voidMac802_11::send(Packet *p, Handler *h){ struct hdr_mac802_11* dh = HDR_MAC(p); upcall_ = h; sendDATA(p); sendRTS(ETHER_ADDR(dh->dh_da)); /* * 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 we are already deferring, there is no * need to reset the Defer timer. */ if(mhDefer.busy() == 0) mhDefer.start(difs); } /* * If the medium is NOT IDLE, then we start * the backoff timer. */ else { mhBackoff.start(cw, is_idle()); } }}voidMac802_11::recv(Packet *p, Handler *h){ struct hdr_cmn *hdr = HDR_CMN(p); /* * Sanity Check */ assert(initialized()); /* * Handle outgoing packets. */ if(h) { 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) { SET_RX_STATE(MAC_RECV); pktRx = p; /* * Schedule the reception of this packet, in * txtime seconds. */ mhRecv.start(TX_Time(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); } }}voidMac802_11::recv_timer(){ hdr_cmn *ch = HDR_CMN(pktRx); hdr_mac802_11 *mh = HDR_MAC(pktRx); u_int32_t dst = ETHER_ADDR(mh->dh_da); 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(eifs)); 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(eifs)); goto done; } /* * IEEE 802.11 specs, section 9.2.5.6 * - update the NAV (Network Allocation Vector) */ if(dst != index) { set_nav(mh->dh_duration); } /* tap out */ if (tap && type == MAC_Type_Data && MAC_Subtype_Data == subtype) tap->tap(pktRx); /* * Address Filtering */ if(dst != 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; 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, "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, "Invalid MAC Data Subtype %x\n", subtype); exit(1); } break; default: fprintf(stderr, "Invalid MAC Type %x\n", subtype); exit(1); } done: pktRx = 0; rx_resume();}voidMac802_11::recvRTS(Packet *p){ struct rts_frame *rf = (struct rts_frame*)p->access(off_mac_); 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);}voidMac802_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. Hence, we can reset * the Short Retry Count and the CW. */ ssrc = 0; rst_cw(); tx_resume(); mac_log(p);}voidMac802_11::recvDATA(Packet *p){ struct hdr_mac802_11 *dh = HDR_MAC(p); u_int32_t dst, src, size; { struct hdr_cmn *ch = HDR_CMN(p); dst = ETHER_ADDR(dh->dh_da); src = ETHER_ADDR(dh->dh_sa); size = ch->size(); /* * Adjust the MAC packet size - ie; strip * off the mac header */ ch->size() -= ETHER_HDR_LEN; ch->num_forwards() += 1; } /* * If we sent a CTS, clean up... */ if(dst != MAC_BROADCAST) { if(size >= macmib->RTSThreshold) { if (tx_state == MAC_CTS) { assert(pktCTRL); Packet::free(pktCTRL); pktCTRL = 0; mhSend.stop(); /* * Our CTS got through. */ ssrc = 0; rst_cw(); } else { discard(p, DROP_MAC_BUSY); return; } sendACK(src); tx_resume(); } /* * We did not send a CTS and there's no * room to buffer an ACK. */ else { 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. ============================================================ */ if(dst != MAC_BROADCAST) { Host *h = &cache[src]; if(h->seqno && h->seqno == dh->dh_scontrol) { discard(p, DROP_MAC_DUPLICATE); return; } h->seqno = dh->dh_scontrol; } /* * Pass the packet up to the link-layer. * XXX - we could schedule an event to account * for this processing delay. */ p->incoming = 1; recvtarget_->recv(p, (Handler*) 0);}voidMac802_11::recvACK(Packet *p){ struct hdr_cmn *ch = HDR_CMN(p); if(tx_state != MAC_SEND) { discard(p, DROP_MAC_INVALID_STATE); return; } assert(pktTx); Packet::free(pktTx); pktTx = 0; 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. */ if((u_int32_t) ch->size() <= macmib->RTSThreshold) ssrc = 0; else slrc = 0; /* * Backoff before sending again. */ rst_cw(); assert(mhBackoff.busy() == 0); mhBackoff.start(cw, is_idle()); tx_resume(); mac_log(p);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -