📄 mac802_16.cc
字号:
*/void Mac802_16::nextChannel (){ debug ("At %f in Mac %d Going to channel %d\n", NOW, index_, (phymib_.channel+1)%nbFreq); setChannel ((phymib_.channel+1)%nbFreq);}/** * Add a flow * @param qos The QoS required * @param handler The entity that requires to add a flow */void Mac802_16::addFlow (ServiceFlowQoS * qos, void * handler) {}/** * Backup the state of the Mac */state_info* Mac802_16::backup_state (){ state_info *backup_state = (state_info*) malloc (sizeof (state_info)); backup_state->bs_id = bs_id_; backup_state->state = state_; backup_state->frameduration = getFrameDuration(); backup_state->frame_number = frame_number_; backup_state->channel = getChannel(); backup_state->connectionManager = connectionManager_; connectionManager_ = new ConnectionManager (this); init_default_connections (); backup_state->serviceFlowHandler = serviceFlowHandler_; serviceFlowHandler_ = new ServiceFlowHandler(); backup_state->peer_list = peer_list_; peer_list_ = (struct peerNode *) malloc (sizeof(struct peerNode)); LIST_INIT(peer_list_); return backup_state;}/** * Restore the state of the Mac */void Mac802_16::restore_state (state_info *backup_state){ bs_id_ = backup_state->bs_id; state_ = backup_state->state; setFrameDuration(backup_state->frameduration); frame_number_ = backup_state->frame_number; setChannel (backup_state->channel); delete (connectionManager_); connectionManager_ = backup_state->connectionManager; delete (serviceFlowHandler_); serviceFlowHandler_ = backup_state->serviceFlowHandler; while (getPeerNode_head()!=NULL) { removePeerNode (getPeerNode_head()); } peer_list_ = backup_state->peer_list;} /** * Set the variable used to find out if upper layers * must be notified to send packets. During scanning we * do not want upper layers to send packet to the mac. */void Mac802_16::setNotify_upper (bool notify) { notify_upper_ = notify; if (notify_upper_ && pktBuf_) { sendDown (pktBuf_); pktBuf_ = NULL; }}/**** Packet processing methods ****//* * Process packets going out * @param p The packet to send out */void Mac802_16::sendDown(Packet *p){ //We first send it through the CS int cid = -1; if (!notify_upper_) { assert (!pktBuf_); pktBuf_ = p; return; } for (SDUClassifier *n=classifier_list_.lh_first; n && cid==-1; n=n->next_entry()) { cid = n->classify (p); } if (cid == -1) { debug ("At %f in Mac %d drop packet because no classification were found\n", \ NOW, index_); drop(p, "CID"); //Packet::free (p); } else { //enqueue the packet Connection *connection = connectionManager_->get_connection (cid, type_ == STA_MN); if (connection == NULL) { debug ("Warning: At %f in Mac %d connection with cid = %d does not exist. Please check classifiers\n",\ NOW, index_, cid); //Packet::free (p); update_watch (&loss_watch_, 1); drop(p, "CID"); } else { if (connection->queueLength ()==macmib_.queue_length) { //queue full update_watch (&loss_watch_, 1); drop (p, "QWI"); } else { //update mac header information //set header information hdr_mac802_16 *wimaxHdr = HDR_MAC802_16(p); wimaxHdr->header.ht = 0; wimaxHdr->header.ec = 1; wimaxHdr->header.type = 0; //no subheader wimaxHdr->header.ci = 0; wimaxHdr->header.eks = 0; wimaxHdr->header.cid = cid; //default wimaxHdr->header.hcs = 0; HDR_CMN(p)->size() += HDR_MAC802_16_SIZE; HDR_CMN(p)->timestamp() = NOW; //set timestamp for delay connection ->enqueue (p); //printf ("At %f in Mac %d Enqueue packet to cid=%d queue size=%d(max=%d)\n", NOW, index_, cid,connection->queueLength (), macmib_.queue_length); } } } //inform upper layer that it can send another packet //if (notify_upper_) resume (NULL); }/* * Transmit a packet to the physical layer * @param p The packet to send out */void Mac802_16::transmit(Packet *p){ if (NOW < last_tx_time_+last_tx_duration_) { //still sending //printf ("MAC is already transmitting. Drop packet.\n"); Packet::free (p); return; } struct hdr_cmn *ch = HDR_CMN(p); /* debug ("At %f in Mac %d sending packet (type=%s, size=%d) ", NOW, index_, packet_info.name(ch->ptype()), ch->size()); if (ch->ptype()==PT_MAC) { if (HDR_MAC802_16(p)->header.ht == 0) debug ("mngt=%d\n", ((mac802_16_dl_map_frame*) p->accessdata())->type); else debug ("bwreq\n"); } else { debug ("\n"); } */ //update stats for delay and jitter double delay = NOW-ch->timestamp(); update_watch (&delay_watch_, delay); double jitter = fabs (delay - last_tx_delay_); update_watch (&jitter_watch_, jitter); last_tx_delay_ = delay; if (ch->ptype()!=PT_MAC) { update_throughput (&tx_data_watch_, 8*ch->size()); } update_throughput (&tx_traffic_watch_, 8*ch->size()); last_tx_time_ = NOW; last_tx_duration_ = ch->txtime(); downtarget_->recv (p, (Handler*)NULL);}/* * Process incoming packets * @param p The incoming packet */void Mac802_16::sendUp (Packet *p){ struct hdr_cmn *ch = HDR_CMN(p);#ifdef DEBUG_WIMAX debug ("At %f in Mac %d receive first bit..over at %f(txtime=%f) (type=%s) ", NOW, index_, NOW+ch->txtime(),ch->txtime(), packet_info.name(ch->ptype())); if (ch->ptype()==PT_MAC) { if (HDR_MAC802_16(p)->header.ht == 0) debug ("mngt=%d\n", ((mac802_16_dl_map_frame*) p->accessdata())->type); else debug ("bwreq\n"); } else { debug ("\n"); }#endif if (pktRx_ !=NULL) { /* * 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) { Packet::free(p); } else { /* * 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(txtime(p) > rxTimer_.expire()) { rxTimer_.stop(); //printf ("\t drop pktRx..collision\n"); drop(pktRx_, "COL"); update_watch (&loss_watch_, 1); pktRx_ = p; //mark the packet with error ch->error() = 1; collision_ = true; rxTimer_.start(ch->txtime()-0.000000001); } else { //printf ("\t drop new packet..collision\n"); drop(p, "COL"); //mark the packet with error HDR_CMN(pktRx_)->error() = 1; collision_ = true; } } return; } assert (pktRx_==NULL); assert (rxTimer_.busy()==0); pktRx_ = p; //create a timer to wait for the end of reception //since the packets are received by burst, the beginning of the new packet //is the same time as the end of this packet..we process this packet 1ns //earlier to make room for the new packet. rxTimer_.start(ch->txtime()-0.000000001);}/** * Process the fully received packet */void Mac802_16::receive (){ assert (pktRx_); struct hdr_cmn *ch = HDR_CMN(pktRx_);#ifdef DEBUG_WIMAX printf ("At %f in Mac %d packet received (type=%s) ", NOW, index_, packet_info.name(ch->ptype())); if (ch->ptype()==PT_MAC) { if (HDR_MAC802_16(pktRx_)->header.ht == 0) printf ("mngt=%d\n", ((mac802_16_dl_map_frame*) pktRx_->accessdata())->type); else printf ("bwreq\n"); } else { printf ("\n"); }#endif //drop the packet if corrupted if (ch->error()) { if (collision_) { //printf ("\t drop new pktRx..collision\n"); drop (pktRx_, "COL"); collision_ = false; } else { //error in the packet, the Mac does not process Packet::free(pktRx_); } //update drop stat update_watch (&loss_watch_, 1); pktRx_ = NULL; return; } //process packet hdr_mac802_16 *wimaxHdr = HDR_MAC802_16(pktRx_); gen_mac_header_t header = wimaxHdr->header; int cid = header.cid; Connection *con = connectionManager_->get_connection (cid, type_==STA_BS); mac802_16_dl_map_frame *frame; if (con == NULL) { //This packet is not for us //printf ("At %f in Mac %d Connection null\n", NOW, index_); update_watch (&loss_watch_, 1); Packet::free(pktRx_); pktRx_=NULL; return; } //printf ("CID=%d\n", cid); //update rx time of last packet received PeerNode *peer; if (type_ == STA_MN) peer = getPeerNode_head(); //MN only has one peer else peer = con->getPeerNode(); //BS can have multiple peers if (peer) { peer->setRxTime (NOW); //collect receive signal strength stats peer->getStatWatch()->update(10*log10(pktRx_->txinfo_.RxPr*1e3)); //debug ("At %f in Mac %d weighted RXThresh: %e rxp average %e\n", NOW, index_, macmib_.lgd_factor_*macmib_.RXThreshold_, pow(10,peer->getStatWatch()->average()/10)/1e3); double avg_w = pow(10,(peer->getStatWatch()->average()/10))/1e3; if ( avg_w < (macmib_.lgd_factor_*macmib_.RXThreshold_)) { if (!peer->isGoingDown () && type_ == STA_MN && state_==MAC802_16_CONNECTED) { ((SSscheduler*) scheduler_)->send_scan_request (); } peer->setGoingDown (true); debug ("At %f Mac %d link going down trigger\n", NOW, index_);#ifdef USE_802_21 double probability = 1; if(type_ == STA_MN) { Mac::send_link_going_down (addr(), getPeerNode_head()->getPeerNode(), -1, (int)(100*probability), eventId_++); } else { Mac::send_link_going_down (peer->getPeerNode(), addr(), -1, (int)(100*probability), eventId_++); }#endif } else { if (peer->isGoingDown()) {#ifdef USE_802_21 Mac::send_link_rollback (addr(), eventId_-1);#endif peer->setGoingDown (false); } } } //process reassembly if (wimaxHdr->frag_subheader) { bool drop_pkt = true; //printf ("Frag type = %d\n",wimaxHdr->fc & 0x3); switch (wimaxHdr->fc & 0x3) { case FRAG_NOFRAG: if (con->getFragmentationStatus()!=FRAG_NOFRAG) con->updateFragmentation (FRAG_NOFRAG, 0, 0); //reset drop_pkt = false; break; case FRAG_FIRST: //when it is the first fragment, it does not matter if we previously //received other fragments, since we reset the information assert (wimaxHdr->fsn == 0); //printf ("\tReceived first fragment\n"); con->updateFragmentation (FRAG_FIRST, 0, ch->size()-(HDR_MAC802_16_SIZE+HDR_MAC802_16_FRAGSUB_SIZE)); break; case FRAG_CONT: if ( (con->getFragmentationStatus()!=FRAG_FIRST && con->getFragmentationStatus()!=FRAG_CONT) || ((wimaxHdr->fsn&0x7) != (con->getFragmentNumber ()+1)%8) ) { con->updateFragmentation (FRAG_NOFRAG, 0, 0); //reset } else { //printf ("\tReceived cont fragment\n"); con->updateFragmentation (FRAG_CONT, wimaxHdr->fsn&0x7, con->getFragmentBytes()+ch->size()-(HDR_MAC802_16_SIZE+HDR_MAC802_16_FRAGSUB_SIZE)); } break; case FRAG_LAST: if ( (con->getFragmentationStatus()==FRAG_FIRST || con->getFragmentationStatus()==FRAG_CONT) && ((wimaxHdr->fsn&0x7) == (con->getFragmentNumber ()+1)%8) ) { //printf ("\tReceived last fragment\n"); ch->size() += con->getFragmentBytes()-HDR_MAC802_16_FRAGSUB_SIZE; drop_pkt = false; } else { //printf ("Error with last frag seq=%d (expected=%d)\n", wimaxHdr->fsn&0x7, (con->getFragmentNumber ()+1)%8); } con->updateFragmentation (FRAG_NOFRAG, 0, 0); //reset break; default: fprintf (stderr,"Error, unknown fragmentation type\n"); exit (-1); } //if we got an error, or it is a fragment that is not the last, free the packet if (drop_pkt) { //update drop stat update_watch (&loss_watch_, 1); Packet::free(pktRx_); pktRx_=NULL; return; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -