📄 mac-tdma.cc
字号:
void MacTdma::recv(Packet* p, Handler* h) { struct hdr_cmn *ch = HDR_CMN(p); /* Incoming packets from phy layer, send UP to ll layer. Now, it is in receiving mode. */ if (ch->direction() == hdr_cmn::UP) { // Since we can't really turn the radio off at lower level, // we just discard the packet. if (!radio_active_) { free(p); //printf("<%d>, %f, I am sleeping...\n", index_, NOW); return; } sendUp(p); //printf("<%d> packet recved: %d\n", index_, tdma_pr_++); return; } /* Packets coming down from ll layer (from ifq actually), send them to phy layer. Now, it is in transmitting mode. */ callback_ = h; state(MAC_SEND); sendDown(p); //printf("<%d> packet sent down: %d\n", index_, tdma_ps_++);}void MacTdma::sendUp(Packet* p) { struct hdr_cmn *ch = HDR_CMN(p); /* Can't receive while transmitting. Should not happen...?*/ if (tx_state_ && ch->error() == 0) { printf("<%d>, can't receive while transmitting!\n", index_); ch->error() = 1; }; /* Detect if there is any collision happened. should not happen...?*/ if (rx_state_ == MAC_IDLE) { SET_RX_STATE(MAC_RECV); // Change the state to recv. pktRx_ = p; // Save the packet for timer reference. /* Schedule the reception of this packet, since we just see the packet header. */ double rtime = TX_Time(p); assert(rtime >= 0); /* Start the timer for receiving, will end when receiving finishes. */ mhRxPkt_.start(p, rtime); } else { /* Note: we don't take the channel status into account, as collision should not happen... */ printf("<%d>, receiving, but the channel is not idle....???\n", index_); }}/* Actually receive data packet when RxPktTimer times out. */void MacTdma::recvDATA(Packet *p){ /*Adjust the MAC packet size: strip off the mac header.*/ struct hdr_cmn *ch = HDR_CMN(p); ch->size() -= ETHER_HDR_LEN; ch->num_forwards() += 1; /* Pass the packet up to the link-layer.*/ uptarget_->recv(p, (Handler*) 0);}/* Send packet down to the physical layer. Need to calculate a certain time slot for transmission. */void MacTdma::sendDown(Packet* p) { u_int32_t dst, src, size; struct hdr_cmn* ch = HDR_CMN(p); struct hdr_mac_tdma* dh = HDR_MAC_TDMA(p); /* Update the MAC header, same as 802.11 */ 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((u_int32_t)ETHER_ADDR(dh->dh_da) != MAC_BROADCAST) dh->dh_duration = DATA_DURATION; else dh->dh_duration = 0; dst = ETHER_ADDR(dh->dh_da); src = ETHER_ADDR(dh->dh_sa); size = ch->size(); /* buffer the packet to be sent. */ pktTx_ = p;}/* Actually send the packet. */void MacTdma::send() { u_int32_t dst, src, size; struct hdr_cmn* ch; struct hdr_mac_tdma* dh; double stime; /* Check if there is any packet buffered. */ if (!pktTx_) { printf("<%d>, %f, no packet buffered.\n", index_, NOW); return; } /* Perform carrier sence...should not be collision...? */ if(!is_idle()) { /* Note: we don't take the channel status into account, ie. no collision, as collision should not happen... */ printf("<%d>, %f, transmitting, but the channel is not idle...???\n", index_, NOW); return; } ch = HDR_CMN(pktTx_); dh = HDR_MAC_TDMA(pktTx_); dst = ETHER_ADDR(dh->dh_da); src = ETHER_ADDR(dh->dh_sa); size = ch->size(); stime = TX_Time(pktTx_); /* Turn on the radio and transmit! */ SET_TX_STATE(MAC_SEND); radioSwitch(ON); /* Start a timer that expires when the packet transmission is complete. */ mhTxPkt_.start(pktTx_->copy(), stime); downtarget_->recv(pktTx_, this); pktTx_ = 0;}// Turn on / off the radiovoid MacTdma::radioSwitch(int i) { radio_active_ = i; EnergyModel *em = netif_->node()->energy_model(); if (i == ON) { if (em && em->sleep()) em->set_node_sleep(0); // printf("<%d>, %f, turn radio ON\n", index_, NOW); return; } if (i == OFF) { if (em && !em->sleep()) { em->set_node_sleep(1); // netif_->node()->set_node_state(INROUTE); }; // printf("<%d>, %f, turn radio OFF\n", index_, NOW); return; }}// make the new preamble.void MacTdma::makePreamble() { u_int32_t dst; struct hdr_mac_tdma* dh; // If there is a packet buffered, file its destination to preamble. if (pktTx_) { dh = HDR_MAC_TDMA(pktTx_); dst = ETHER_ADDR(dh->dh_da); //printf("<%d>, %f, write %d to slot %d in preamble\n", index_, NOW, dst, slot_num_); tdma_preamble_[slot_num_] = dst; } else { //printf("<%d>, %f, write NO_PKT to slot %d in preamble\n", index_, NOW, slot_num_); tdma_preamble_[slot_num_] = NOTHING_TO_SEND; }}/* Timers' handlers *//* Slot Timer: For the preamble calculation, we should have it: occupy one slot time, radio turned on for the whole slot.*/void MacTdma::slotHandler(Event *e) { // Restart timer for next slot. mhSlot_.start((Packet *)e, slot_time_); // Make a new presamble for next frame. if ((slot_count_ == active_node_) || (slot_count_ == FIRST_ROUND)) { //printf("<%d>, %f, make the new preamble now.\n", index_, NOW); // We should turn the radio on for the whole slot time. radioSwitch(ON); makePreamble(); slot_count_ = 0; return; } // If it is the sending slot for me. if (slot_count_ == slot_num_) { //printf("<%d>, %f, time to send.\n", index_, NOW); // We have to check the preamble first to avoid the packets coming in the middle. if (tdma_preamble_[slot_num_] != NOTHING_TO_SEND) send(); else radioSwitch(OFF); slot_count_++; return; } // If I am supposed to listen in this slot if ((tdma_preamble_[slot_count_] == index_) || ((u_int32_t)tdma_preamble_[slot_count_] == MAC_BROADCAST)) { //printf("<%d>, %f, preamble[%d]=%d, I am supposed to receive now.\n", index_, NOW, slot_count_, tdma_preamble_[slot_count_]); slot_count_++; // Wake up the receive packets. radioSwitch(ON); return; } // If I dont send / recv, do nothing. //printf("<%d>, %f, preamble[%d]=%d, nothing to do now.\n", index_, NOW, slot_count_, tdma_preamble_[slot_count_]); radioSwitch(OFF); slot_count_++; return;}void MacTdma::recvHandler(Event *e) { u_int32_t dst, src; int size; struct hdr_cmn *ch = HDR_CMN(pktRx_); struct hdr_mac_tdma *dh = HDR_MAC_TDMA(pktRx_); /* Check if any collision happened while receiving. */ if (rx_state_ == MAC_COLL) ch->error() = 1; SET_RX_STATE(MAC_IDLE); /* check if this packet was unicast and not intended for me, drop it.*/ dst = ETHER_ADDR(dh->dh_da); src = ETHER_ADDR(dh->dh_sa); size = ch->size(); //printf("<%d>, %f, recv a packet [from %d to %d], size = %d\n", index_, NOW, src, dst, size); // Turn the radio off after receiving the whole packet radioSwitch(OFF); /* Ordinary operations on the incoming packet */ // Not a pcket destinated to me. if ((dst != MAC_BROADCAST) && (dst != (u_int32_t)index_)) { drop(pktRx_); return; } /* Now forward packet upwards. */ recvDATA(pktRx_);}/* After transmission a certain packet. Turn off the radio. */void MacTdma::sendHandler(Event *e) { // printf("<%d>, %f, send a packet finished.\n", index_, NOW); /* Once transmission is complete, drop the packet. p is just for schedule a event. */ SET_TX_STATE(MAC_IDLE); Packet::free((Packet *)e); // Turn off the radio after sending the whole packet radioSwitch(OFF); /* unlock IFQ. */ if(callback_) { Handler *h = callback_; callback_ = 0; h->handle((Event*) 0); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -