?? mac-tdma.c
字號:
// Record the start time of the new schedule.
start_time_ = NOW;
/* Seperate slot_num_ and the node id:
we may have flexibility as node number changes.
*/
slot_num_ = slot_pointer++;
tdma_schedule_[slot_num_] = (char) index_;
}
/* To handle incoming packet. */
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_);
ch->txtime() = stime;
/* 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 radio
void 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);
Phy *p;
p = netif_;
((WirelessPhy *)p)->node_wakeup();
return;
}
if (i == OFF) {
//if (em && !em->sleep()) {
//em->set_node_sleep(1);
// netif_->node()->set_node_state(INROUTE);
Phy *p;
p = netif_;
((WirelessPhy *)p)->node_sleep();
// 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 + -