mac802_16.cc
上传用户:hzie11
上传日期:2013-10-07
资源大小:1487k
文件大小:33k
源码类别:

网络

开发平台:

C/C++

  1. /* This software was developed at the National Institute of Standards and
  2.  * Technology by employees of the Federal Government in the course of
  3.  * their official duties. Pursuant to title 17 Section 105 of the United
  4.  * States Code this software is not subject to copyright protection and
  5.  * is in the public domain.
  6.  * NIST assumes no responsibility whatsoever for its use by other parties,
  7.  * and makes no guarantees, expressed or implied, about its quality,
  8.  * reliability, or any other characteristic.
  9.  * <BR>
  10.  * We would appreciate acknowledgement if the software is used.
  11.  * <BR>
  12.  * NIST ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
  13.  * DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
  14.  * FROM THE USE OF THIS SOFTWARE.
  15.  * </PRE></P>
  16.  * @author  rouil
  17.  */
  18. #include "mac802_16.h"
  19. #include "scheduling/wimaxscheduler.h"
  20. #include "scheduling/ssscheduler.h" //TBR
  21. //we use mac 802_11 for trace
  22. #include "mac-802_11.h"
  23. /* Defines frequencies for 3.5 GHz band and 7 Mhz freqency bandwidth */
  24. /* Will be removed when a dynamic way is added */
  25. static const int nbFreq = 5;
  26. static const double frequencies[] = { 3.486e+9, 3.493e+9, 3.5e+9, 3.507e+9, 3.514e+9};
  27. int hdr_mac802_16::offset_;
  28. /**
  29.  * TCL Hooks for the simulator for wimax packets
  30.  */
  31. static class Mac802_16HeaderClass : public PacketHeaderClass
  32. {
  33. public:
  34. Mac802_16HeaderClass() : PacketHeaderClass("PacketHeader/802_16",
  35.      sizeof(hdr_mac802_16))
  36. {
  37. bind_offset(&hdr_mac802_16::offset_);
  38. }
  39. } class_hdr_mac802_16;
  40. /**
  41.  * TCL Hooks for the simulator for wimax mac
  42.  */
  43. static class Mac802_16Class : public TclClass {
  44. public:
  45.   Mac802_16Class() : TclClass("Mac/802_16") {}
  46.   TclObject* create(int, const char*const*) {
  47.     return (new Mac802_16());
  48.     
  49.   }
  50. } class_mac802_16;
  51. Phy802_16MIB::Phy802_16MIB(Mac802_16 *parent)
  52. {
  53.   parent->bind ("channel_", &channel );
  54.   parent->bind ("fbandwidth_", &fbandwidth );
  55.   parent->bind ("ttg_", &ttg );
  56.   parent->bind ("rtg_", &rtg );
  57. }
  58. Mac802_16MIB::Mac802_16MIB(Mac802_16 *parent)
  59. {
  60.   parent->bind ("queue_length_", &queue_length );
  61.   parent->bind ("frame_duration_", &frame_duration );
  62.   parent->bind ("dcd_interval_", &dcd_interval );
  63.   parent->bind ("ucd_interval_", &ucd_interval );
  64.   parent->bind ("init_rng_interval_", &init_rng_interval );
  65.   parent->bind ("lost_dlmap_interval_", &lost_dlmap_interval );
  66.   parent->bind ("lost_ulmap_interval_", &lost_ulmap_interval );
  67.   parent->bind ("t1_timeout_", &t1_timeout );
  68.   parent->bind ("t2_timeout_", &t2_timeout );
  69.   parent->bind ("t3_timeout_", &t3_timeout );
  70.   parent->bind ("t6_timeout_", &t6_timeout );
  71.   parent->bind ("t12_timeout_", &t12_timeout );
  72.   parent->bind ("t16_timeout_", &t16_timeout );
  73.   parent->bind ("t17_timeout_", &t17_timeout );
  74.   parent->bind ("t21_timeout_", &t21_timeout );
  75.   parent->bind ("contention_rng_retry_", &contention_rng_retry );
  76.   parent->bind ("invited_rng_retry_", &invited_rng_retry );
  77.   parent->bind ("request_retry_", &request_retry );
  78.   parent->bind ("reg_req_retry_", &reg_req_retry );
  79.   parent->bind ("tproc_", &tproc );
  80.   parent->bind ("dsx_req_retry_", &dsx_req_retry );
  81.   parent->bind ("dsx_rsp_retry_", &dsx_rsp_retry );
  82.   parent->bind ("rng_backoff_start_", &rng_backoff_start);
  83.   parent->bind ("rng_backoff_stop_", &rng_backoff_stop);
  84.   parent->bind ("bw_backoff_start_", &bw_backoff_start);
  85.   parent->bind ("bw_backoff_stop_", &bw_backoff_stop);
  86.  
  87.   //mobility extension
  88.   parent->bind ("scan_duration_", &scan_duration );
  89.   parent->bind ("interleaving_interval_", &interleaving );
  90.   parent->bind ("scan_iteration_", &scan_iteration );
  91.   parent->bind ("t44_timeout_", &t44_timeout );
  92.   parent->bind ("max_dir_scan_time_", &max_dir_scan_time );
  93.   parent->bind ("nbr_adv_interval_", &nbr_adv_interval );
  94.   parent->bind ("scan_req_retry_", &scan_req_retry );
  95.   parent->bind ("client_timeout_", &client_timeout );
  96.   parent->bind ("rxp_avg_alpha_", &rxp_avg_alpha);
  97.   parent->bind ("lgd_factor_", &lgd_factor_);
  98. }
  99. /**
  100.  * Creates a Mac 802.16
  101.  */
  102. Mac802_16::Mac802_16() : Mac (), macmib_(this), phymib_(this), rxTimer_(this)
  103. {
  104.   //init variable
  105.   LIST_INIT(&classifier_list_);
  106.   peer_list_ = (struct peerNode *) malloc (sizeof(struct peerNode));
  107.   LIST_INIT(peer_list_);
  108.   
  109.   collision_ = false;
  110.   pktRx_ = NULL;
  111.   pktBuf_ = NULL;
  112.   connectionManager_ = new ConnectionManager (this);
  113.   scheduler_ = NULL;
  114.   /* the following will be replaced by dynamic adding of service flow */
  115.   serviceFlowHandler_ = new ServiceFlowHandler ();
  116.   serviceFlowHandler_->setMac (this);
  117.   bs_id_ = BS_NOT_CONNECTED;
  118.   type_ = STA_UNKNOWN;
  119.   frame_number_ = 0;
  120.   state_ = MAC802_16_DISCONNECTED;
  121.   notify_upper_ = true;
  122.   last_tx_time_ = 0;
  123.   last_tx_duration_ = 0;
  124.   Tcl& tcl = Tcl::instance();
  125.   tcl.evalf ("Phy/WirelessPhy set RXThresh_");
  126.   macmib_.RXThreshold_ = atof (tcl.result());
  127.   /* Initialize Stats variables */
  128.   bind_bool ("print_stats_", &print_stats_);
  129.   last_tx_delay_ = 0;
  130.   double tmp;
  131.   bind ("delay_avg_alpha_", &tmp);
  132.   delay_watch_.set_alpha(tmp);
  133.   bind ("jitter_avg_alpha_", &tmp);
  134.   jitter_watch_.set_alpha(tmp);
  135.   bind ("loss_avg_alpha_", &tmp);
  136.   loss_watch_.set_alpha(tmp);
  137.   bind ("throughput_avg_alpha_", &tmp);
  138.   rx_data_watch_.set_alpha(tmp);
  139.   rx_data_watch_.set_pos_gradient (false);
  140.   rx_traffic_watch_.set_alpha(tmp);
  141.   rx_traffic_watch_.set_pos_gradient (false);
  142.   tx_data_watch_.set_alpha(tmp);
  143.   tx_data_watch_.set_pos_gradient (false);
  144.   tx_traffic_watch_.set_alpha(tmp);
  145.   tx_traffic_watch_.set_pos_gradient (false);
  146.   bind ("throughput_delay_", &tmp);
  147.   rx_data_watch_.set_delay (tmp);
  148.   rx_traffic_watch_.set_delay (tmp);
  149.   tx_data_watch_.set_delay (tmp);
  150.   tx_traffic_watch_.set_delay (tmp);
  151.   //timers for stats
  152.   rx_data_timer_ = new StatTimer (this, &rx_data_watch_);
  153.   rx_traffic_timer_ = new StatTimer (this, &rx_traffic_watch_);
  154.   tx_data_timer_ = new StatTimer (this, &tx_data_watch_);
  155.   tx_traffic_timer_ = new StatTimer (this, &tx_traffic_watch_);
  156. }
  157. /*
  158.  * Interface with the TCL script
  159.  * @param argc The number of parameter
  160.  * @param argv The list of parameters
  161.  */
  162. int Mac802_16::command(int argc, const char*const* argv)
  163. {
  164.   if (argc == 2) {
  165.     if (strcmp(argv[1], "dump-classifiers") == 0) {
  166.       for (SDUClassifier *n=classifier_list_.lh_first;n;n=n->next_entry()) {
  167. //printf ("Classifier %x priority=%dn", (int)n, n->getPriority());
  168.       }
  169.       return TCL_OK;
  170.     }
  171.   }
  172.   else if (argc == 3) {
  173.     /*
  174.     if (strcmp(argv[1], "set-bs") == 0) {
  175.       bs_id_ = atoi (argv[2]);
  176.     }
  177.     else*/
  178.     if (strcmp(argv[1], "add-classifier") == 0) {
  179.       SDUClassifier *clas = (SDUClassifier*) TclObject::lookup(argv[2]);
  180.       if (clas == 0)
  181. return TCL_ERROR;
  182.       //add classifier to the list
  183.       addClassifier (clas);
  184.       return TCL_OK;
  185.     } else if (strcmp(argv[1], "set-scheduler") == 0) {
  186.       scheduler_ = (WimaxScheduler*) TclObject::lookup(argv[2]);
  187.       if (scheduler_ == 0)
  188. return TCL_ERROR;
  189.       scheduler_->setMac (this); //register the mac
  190.       setStationType (scheduler_->getNodeType()); //get the node type (BS or MN)
  191.       return TCL_OK;
  192.     } else if (strcmp(argv[1], "set-servicehandler") == 0) {
  193.       serviceFlowHandler_ = (ServiceFlowHandler*) TclObject::lookup(argv[2]);
  194.       if (serviceFlowHandler_ == 0)
  195. return TCL_ERROR;
  196.       serviceFlowHandler_->setMac (this);
  197.       return TCL_OK;
  198.     } else if (strcmp(argv[1], "set-channel") == 0) {
  199.       assert (netif_); //to make sure we can update the phy
  200.       phymib_.channel = atoi (argv[2]);
  201.       double tmp = frequencies[phymib_.channel];
  202.       getPhy ()->setFrequency (tmp);
  203.       return TCL_OK;
  204.     }
  205.   }
  206.   return Mac::command(argc, argv);
  207. }
  208. /**
  209.  * Set the type of STA. This will be called when adding the scheduler
  210.  * It is used to create the default connections
  211.  * @param type The station type
  212.  */
  213. void Mac802_16::setStationType (station_type_t type)
  214. {
  215.   assert (type_ == STA_UNKNOWN && type != STA_UNKNOWN);
  216.   type_ = type;
  217.   init_default_connections ();
  218. }
  219. /**
  220.  * Initialize default connections
  221.  */
  222. void Mac802_16::init_default_connections ()
  223. {
  224.   Connection * con;
  225.   //create initial ranging and padding connection
  226.   con = new Connection (CONN_INIT_RANGING);
  227.   connectionManager_->add_connection (con, true); //uplink
  228.   con = new Connection (CONN_INIT_RANGING);
  229.   connectionManager_->add_connection (con, false); //downlink
  230.   con = new Connection (CONN_PADDING);
  231.   connectionManager_->add_connection (con, true);
  232.   con = new Connection (CONN_PADDING);
  233.   connectionManager_->add_connection (con, false);
  234.   if (type_ == STA_BS) {
  235.     //the BS is always connected
  236.     setMacState (MAC802_16_CONNECTED);
  237.     //we need to create a Broadcast connection and AAS init ranging CIDs
  238.     con = new Connection (CONN_BROADCAST);
  239.     connectionManager_->add_connection (con, false);
  240.     con = new Connection (CONN_AAS_INIT_RANGING);
  241.     connectionManager_->add_connection (con, true);
  242.   } else if (type_ == STA_MN) {
  243.     //create connection to receive broadcast packets from BS
  244.     con = new Connection (CONN_BROADCAST);
  245.     connectionManager_->add_connection (con, false);
  246.   }
  247. }
  248. /**
  249.  * Return the peer node that has the given address
  250.  * @param index The address of the peer
  251.  * @return The peer node that has the given address
  252.  */
  253. PeerNode* Mac802_16::getPeerNode (int index)
  254. {
  255.   for (PeerNode *p=peer_list_->lh_first;p;p=p->next_entry()) {
  256.     if (p->getPeerNode ()==index)
  257.       return p;
  258.   }
  259.   return NULL;
  260. }
  261. /**
  262.  * Add the peer node
  263.  * @param The peer node to add
  264.  */
  265. void Mac802_16::addPeerNode (PeerNode *node)
  266. {
  267.   node->insert_entry (peer_list_);
  268.   //update Rx time so for default value
  269.   node->setRxTime(NOW);
  270.   node->getStatWatch()->set_alpha(macmib_.rxp_avg_alpha);
  271. }
  272. /**
  273.  * Remove the peer node
  274.  * @param The peer node to remove
  275.  */
  276. void Mac802_16::removePeerNode (PeerNode *peer)
  277. {
  278.   if (peer->getBasic()) {
  279.     getCManager()->remove_connection (peer->getBasic()->get_cid());
  280.     delete (peer->getBasic());
  281.   }
  282.   if (peer->getPrimary()) {
  283.     getCManager()->remove_connection (peer->getPrimary()->get_cid());
  284.     delete (peer->getPrimary());
  285.   }
  286.   if (peer->getSecondary()) {
  287.     getCManager()->remove_connection (peer->getSecondary()->get_cid());
  288.     delete (peer->getSecondary());
  289.   }
  290.   if (peer->getInData()) {
  291.     getCManager()->remove_connection (peer->getInData()->get_cid());
  292.     delete (peer->getInData());
  293.   }
  294.   if (peer->getOutData()) {
  295.     getCManager()->remove_connection (peer->getOutData()->get_cid());
  296.     delete (peer->getOutData());
  297.   }
  298.   peer->remove_entry ();
  299.   delete (peer);
  300. }
  301. /**
  302.  * Set the mac state
  303.  * @param state The new mac state
  304.  */  
  305. void Mac802_16::setMacState (Mac802_16State state)
  306. {
  307.   state_ = state;
  308. }
  309. /**
  310.  * Return the mac state
  311.  * @return The new mac state
  312.  */  
  313. Mac802_16State Mac802_16::getMacState ()
  314. {
  315.   return state_;
  316. }
  317. /**
  318.  * Return the PHY layer
  319.  * @return The PHY layer
  320.  */
  321. OFDMPhy* Mac802_16::getPhy () { 
  322.   return (OFDMPhy*) netif_;
  323. }
  324. /**
  325.  * Change the channel
  326.  * @param channel The new channel
  327.  */
  328. void Mac802_16::setChannel (int channel)
  329. {
  330.   assert (channel < nbFreq);
  331.   phymib_.channel = channel;
  332.   double tmp = frequencies[phymib_.channel];
  333.   getPhy ()->setFrequency (tmp);
  334. }
  335. /**
  336.  * Return the channel number for the given frequency
  337.  * @param freq The frequency
  338.  * @return The channel number of -1 if the frequency does not match
  339.  */
  340. int Mac802_16::getChannel (double freq)
  341. {
  342.   for (int i = 0 ; i < nbFreq ; i++) {
  343.     if (frequencies[i]==freq)
  344.       return i;
  345.   }
  346.   return -1;
  347. }
  348. /**
  349.  * Return the channel index
  350.  * @return The channel
  351.  */
  352. int Mac802_16::getChannel ()
  353. {
  354.   return phymib_.channel;
  355. }
  356. /**
  357.  * Set the channel to the next from the list
  358.  * Used at initialisation and when loosing signal
  359.  */
  360. void Mac802_16::nextChannel ()
  361. {
  362.   debug ("At %f in Mac %d Going to channel %dn", NOW, index_, (phymib_.channel+1)%nbFreq);
  363.   setChannel ((phymib_.channel+1)%nbFreq);
  364. }
  365. /**
  366.  * Add a flow
  367.  * @param qos The QoS required
  368.  * @param handler The entity that requires to add a flow
  369.  */
  370. void Mac802_16::addFlow (ServiceFlowQoS * qos, void * handler) 
  371. {
  372. }
  373. /**
  374.  * Backup the state of the Mac
  375.  */
  376. state_info* Mac802_16::backup_state ()
  377. {
  378.   state_info *backup_state = (state_info*) malloc (sizeof (state_info));
  379.   backup_state->bs_id = bs_id_;
  380.   backup_state->state = state_;
  381.   backup_state->frameduration = getFrameDuration();
  382.   backup_state->frame_number = frame_number_;
  383.   backup_state->channel = getChannel();
  384.   backup_state->connectionManager = connectionManager_;
  385.   connectionManager_ = new ConnectionManager (this);
  386.   init_default_connections ();
  387.   backup_state->serviceFlowHandler = serviceFlowHandler_;
  388.   serviceFlowHandler_ = new ServiceFlowHandler();
  389.   backup_state->peer_list = peer_list_;
  390.   peer_list_ = (struct peerNode *) malloc (sizeof(struct peerNode));
  391.   LIST_INIT(peer_list_);
  392.   return backup_state;
  393. }
  394. /**
  395.  * Restore the state of the Mac
  396.  */
  397. void Mac802_16::restore_state (state_info *backup_state)
  398. {
  399.   bs_id_ = backup_state->bs_id;
  400.   state_ = backup_state->state;
  401.   setFrameDuration(backup_state->frameduration);
  402.   frame_number_ = backup_state->frame_number;
  403.   setChannel (backup_state->channel);
  404.   delete (connectionManager_);
  405.   connectionManager_ = backup_state->connectionManager;
  406.   delete (serviceFlowHandler_);
  407.   serviceFlowHandler_ = backup_state->serviceFlowHandler;
  408.   while (getPeerNode_head()!=NULL) {
  409.     removePeerNode (getPeerNode_head());
  410.   }
  411.   peer_list_ = backup_state->peer_list;
  412. }
  413.   
  414. /**
  415.  * Set the variable used to find out if upper layers
  416.  * must be notified to send packets. During scanning we
  417.  * do not want upper layers to send packet to the mac.
  418.  */
  419. void Mac802_16::setNotify_upper (bool notify) { 
  420.   notify_upper_ = notify; 
  421.   if (notify_upper_ && pktBuf_) {
  422.     sendDown (pktBuf_);
  423.     pktBuf_ = NULL;
  424.   }
  425. }
  426. /**** Packet processing methods ****/
  427. /*
  428.  * Process packets going out
  429.  * @param p The packet to send out
  430.  */
  431. void Mac802_16::sendDown(Packet *p)
  432. {
  433.   //We first send it through the CS
  434.   int cid = -1;
  435.   if (!notify_upper_) {
  436.     assert (!pktBuf_);
  437.     pktBuf_ = p;
  438.     return;
  439.   } 
  440.   for (SDUClassifier *n=classifier_list_.lh_first; n && cid==-1; n=n->next_entry()) {
  441.     cid = n->classify (p);
  442.   }
  443.   if (cid == -1) {
  444.     debug ("At %f in Mac %d drop packet because no classification were foundn", 
  445.     NOW, index_);
  446.     drop(p, "CID");
  447.     //Packet::free (p);
  448.   } else {
  449.     //enqueue the packet 
  450.     Connection *connection = connectionManager_->get_connection (cid, type_ == STA_MN);
  451.     if (connection == NULL) {
  452.       debug ("Warning: At %f in Mac %d connection with cid = %d does not exist. Please check classifiersn",
  453.       NOW, index_, cid);
  454.       //Packet::free (p);
  455.       update_watch (&loss_watch_, 1);
  456.       drop(p, "CID");
  457.     }
  458.     else {
  459.       if (connection->queueLength ()==macmib_.queue_length) {
  460. //queue full 
  461. update_watch (&loss_watch_, 1);
  462. drop (p, "QWI");
  463.       } else {
  464. //update mac header information
  465. //set header information
  466. hdr_mac802_16 *wimaxHdr = HDR_MAC802_16(p);
  467. wimaxHdr->header.ht = 0;
  468. wimaxHdr->header.ec = 1;
  469. wimaxHdr->header.type = 0; //no subheader
  470. wimaxHdr->header.ci = 0;
  471. wimaxHdr->header.eks = 0;
  472. wimaxHdr->header.cid = cid; //default
  473. wimaxHdr->header.hcs = 0;
  474. HDR_CMN(p)->size() += HDR_MAC802_16_SIZE;
  475. HDR_CMN(p)->timestamp() = NOW; //set timestamp for delay
  476. connection ->enqueue (p);
  477. //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);
  478.       }
  479.     }
  480.   }
  481.   //inform upper layer that it can send another packet
  482.   //if (notify_upper_) 
  483.   resume (NULL);  
  484. }
  485. /*
  486.  * Transmit a packet to the physical layer
  487.  * @param p The packet to send out
  488.  */
  489. void Mac802_16::transmit(Packet *p)
  490. {
  491.   if (NOW < last_tx_time_+last_tx_duration_) {
  492.     //still sending
  493.     //printf ("MAC is already transmitting. Drop packet.n");
  494.     Packet::free (p);
  495.     return;
  496.   }
  497.   struct hdr_cmn *ch = HDR_CMN(p);
  498.   /*
  499.   debug ("At %f in Mac %d sending packet (type=%s, size=%d) ", NOW, index_, packet_info.name(ch->ptype()), ch->size());
  500.   if (ch->ptype()==PT_MAC) {
  501.     if (HDR_MAC802_16(p)->header.ht == 0)
  502.       debug ("mngt=%dn", ((mac802_16_dl_map_frame*) p->accessdata())->type);
  503.     else
  504.       debug ("bwreqn");
  505.   } else {
  506.     debug ("n");
  507.   }
  508.   */
  509.   //update stats for delay and jitter
  510.   double delay = NOW-ch->timestamp();
  511.   update_watch (&delay_watch_, delay);
  512.   double jitter = fabs (delay - last_tx_delay_);
  513.   update_watch (&jitter_watch_, jitter);
  514.   last_tx_delay_ = delay;
  515.   if (ch->ptype()!=PT_MAC) {
  516.     update_throughput (&tx_data_watch_, 8*ch->size());
  517.   } 
  518.   update_throughput (&tx_traffic_watch_, 8*ch->size());
  519.   
  520.   last_tx_time_ = NOW;
  521.   last_tx_duration_ = ch->txtime();
  522.   downtarget_->recv (p, (Handler*)NULL);
  523. }
  524. /*
  525.  * Process incoming packets
  526.  * @param p The incoming packet
  527.  */
  528. void Mac802_16::sendUp (Packet *p)
  529. {
  530.   struct hdr_cmn *ch = HDR_CMN(p);
  531. #ifdef DEBUG_WIMAX
  532.   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()));
  533.   if (ch->ptype()==PT_MAC) {
  534.     if (HDR_MAC802_16(p)->header.ht == 0)
  535.       debug ("mngt=%dn", ((mac802_16_dl_map_frame*) p->accessdata())->type);
  536.     else
  537.       debug ("bwreqn");
  538.   } else {
  539.     debug ("n");
  540.   }
  541. #endif
  542.   if (pktRx_ !=NULL) {
  543.     /*
  544.      *  If the power of the incoming packet is smaller than the
  545.      *  power of the packet currently being received by at least
  546.      *  the capture threshold, then we ignore the new packet.
  547.      */
  548.     if(pktRx_->txinfo_.RxPr / p->txinfo_.RxPr >= p->txinfo_.CPThresh) {
  549.       Packet::free(p);
  550.     } else {
  551.       /*
  552.        *  Since a collision has occurred, figure out
  553.        *  which packet that caused the collision will
  554.        *  "last" the longest.  Make this packet,
  555.        *  pktRx_ and reset the Recv Timer if necessary.
  556.        */
  557.       if(txtime(p) > rxTimer_.expire()) {
  558. rxTimer_.stop();
  559. //printf ("t drop pktRx..collisionn");
  560. drop(pktRx_, "COL");
  561. update_watch (&loss_watch_, 1);
  562. pktRx_ = p;
  563. //mark the packet with error
  564. ch->error() = 1;
  565. collision_ = true;
  566. rxTimer_.start(ch->txtime()-0.000000001);
  567.       }
  568.       else {
  569. //printf ("t drop new packet..collisionn");
  570. drop(p, "COL");
  571. //mark the packet with error
  572. HDR_CMN(pktRx_)->error() = 1;
  573. collision_ = true;
  574.       }
  575.     }
  576.     return;
  577.   }
  578.   assert (pktRx_==NULL);
  579.   assert (rxTimer_.busy()==0);
  580.   pktRx_ = p;
  581.   //create a timer to wait for the end of reception
  582.   //since the packets are received by burst, the beginning of the new packet 
  583.   //is the same time as the end of this packet..we process this packet 1ns 
  584.   //earlier to make room for the new packet.
  585.   rxTimer_.start(ch->txtime()-0.000000001);
  586. }
  587. /**
  588.  * Process the fully received packet
  589.  */
  590. void Mac802_16::receive ()
  591. {
  592.   assert (pktRx_);
  593.   struct hdr_cmn *ch = HDR_CMN(pktRx_);
  594. #ifdef DEBUG_WIMAX
  595.   printf ("At %f in Mac %d packet received (type=%s) ", NOW, index_, packet_info.name(ch->ptype()));
  596.   if (ch->ptype()==PT_MAC) {
  597.     if (HDR_MAC802_16(pktRx_)->header.ht == 0)
  598.       printf ("mngt=%dn", ((mac802_16_dl_map_frame*) pktRx_->accessdata())->type);
  599.     else
  600.       printf ("bwreqn");
  601.   } else {
  602.     printf ("n");
  603.   }
  604. #endif
  605.     
  606.   //drop the packet if corrupted
  607.   if (ch->error()) {
  608.     if (collision_) {
  609.       //printf ("t drop new pktRx..collisionn");
  610.       drop (pktRx_, "COL");
  611.       collision_ = false;
  612.     } else {
  613.       //error in the packet, the Mac does not process
  614.       Packet::free(pktRx_);
  615.     }
  616.     //update drop stat
  617.     update_watch (&loss_watch_, 1);
  618.     pktRx_ = NULL;
  619.     return;
  620.   }
  621.   //process packet
  622.   hdr_mac802_16 *wimaxHdr = HDR_MAC802_16(pktRx_);
  623.   gen_mac_header_t header = wimaxHdr->header;
  624.   int cid = header.cid;
  625.   Connection *con = connectionManager_->get_connection (cid, type_==STA_BS);
  626.   mac802_16_dl_map_frame *frame;
  627.   if (con == NULL) {
  628.     //This packet is not for us
  629.     //printf ("At %f in Mac %d Connection nulln", NOW, index_);
  630.     update_watch (&loss_watch_, 1);
  631.     Packet::free(pktRx_);
  632.     pktRx_=NULL;
  633.     return;
  634.   }
  635.   //printf ("CID=%dn", cid);
  636.   //update rx time of last packet received
  637.   PeerNode *peer;
  638.   if (type_ == STA_MN)
  639.     peer = getPeerNode_head(); //MN only has one peer
  640.   else
  641.     peer = con->getPeerNode(); //BS can have multiple peers
  642.   if (peer) {
  643.     peer->setRxTime (NOW);
  644.     
  645.     //collect receive signal strength stats
  646.     peer->getStatWatch()->update(10*log10(pktRx_->txinfo_.RxPr*1e3));
  647.     //debug ("At %f in Mac %d weighted RXThresh: %e rxp average %en", NOW, index_, macmib_.lgd_factor_*macmib_.RXThreshold_, pow(10,peer->getStatWatch()->average()/10)/1e3);
  648.     double avg_w = pow(10,(peer->getStatWatch()->average()/10))/1e3;
  649.     
  650.     if ( avg_w < (macmib_.lgd_factor_*macmib_.RXThreshold_)) {
  651.       if (!peer->isGoingDown () && type_ == STA_MN && state_==MAC802_16_CONNECTED) {
  652. ((SSscheduler*) scheduler_)->send_scan_request ();
  653.       }
  654.       peer->setGoingDown (true);
  655.       debug ("At %f Mac %d link going down triggern", NOW, index_);
  656. #ifdef USE_802_21
  657.       double probability = 1;
  658.       if(type_ == STA_MN) {
  659. Mac::send_link_going_down (addr(), getPeerNode_head()->getPeerNode(), -1, (int)(100*probability), eventId_++);
  660.       } else {
  661. Mac::send_link_going_down (peer->getPeerNode(), addr(), -1, (int)(100*probability), eventId_++);
  662.       }
  663. #endif
  664.     }
  665.     else {
  666.       if (peer->isGoingDown()) {
  667. #ifdef USE_802_21
  668. Mac::send_link_rollback (addr(), eventId_-1);
  669. #endif
  670. peer->setGoingDown (false);
  671.       }
  672.     }
  673.   }
  674.   
  675.   //process reassembly
  676.   if (wimaxHdr->frag_subheader) {
  677.     bool drop_pkt = true;
  678.     //printf ("Frag type = %dn",wimaxHdr->fc & 0x3);
  679.     switch (wimaxHdr->fc & 0x3) {
  680.     case FRAG_NOFRAG: 
  681.       if (con->getFragmentationStatus()!=FRAG_NOFRAG)
  682. con->updateFragmentation (FRAG_NOFRAG, 0, 0); //reset
  683.       drop_pkt = false;
  684.       break; 
  685.     case FRAG_FIRST: 
  686.       //when it is the first fragment, it does not matter if we previously
  687.       //received other fragments, since we reset the information
  688.       assert (wimaxHdr->fsn == 0);
  689.       //printf ("tReceived first fragmentn");
  690.       con->updateFragmentation (FRAG_FIRST, 0, ch->size()-(HDR_MAC802_16_SIZE+HDR_MAC802_16_FRAGSUB_SIZE));
  691.       break; 
  692.     case FRAG_CONT: 
  693.       if ( (con->getFragmentationStatus()!=FRAG_FIRST
  694.     && con->getFragmentationStatus()!=FRAG_CONT)
  695.    || ((wimaxHdr->fsn&0x7) != (con->getFragmentNumber ()+1)%8) ) {
  696. con->updateFragmentation (FRAG_NOFRAG, 0, 0); //reset
  697.       } else {
  698. //printf ("tReceived cont fragmentn");
  699. con->updateFragmentation (FRAG_CONT, wimaxHdr->fsn&0x7, con->getFragmentBytes()+ch->size()-(HDR_MAC802_16_SIZE+HDR_MAC802_16_FRAGSUB_SIZE));
  700.       }
  701.       break; 
  702.     case FRAG_LAST: 
  703.       if ( (con->getFragmentationStatus()==FRAG_FIRST
  704.     || con->getFragmentationStatus()==FRAG_CONT)
  705.    && ((wimaxHdr->fsn&0x7) == (con->getFragmentNumber ()+1)%8) ) {
  706. //printf ("tReceived last fragmentn");
  707. ch->size() += con->getFragmentBytes()-HDR_MAC802_16_FRAGSUB_SIZE;
  708. drop_pkt = false;
  709.       } else {
  710. //printf ("Error with last frag seq=%d (expected=%d)n", wimaxHdr->fsn&0x7, (con->getFragmentNumber ()+1)%8);
  711.       }     
  712.       con->updateFragmentation (FRAG_NOFRAG, 0, 0); //reset
  713.       break; 
  714.     default:
  715.       fprintf (stderr,"Error, unknown fragmentation typen");
  716.       exit (-1);
  717.     }
  718.     //if we got an error, or it is a fragment that is not the last, free the packet
  719.     if (drop_pkt) {
  720.       //update drop stat
  721.       update_watch (&loss_watch_, 1);
  722.       Packet::free(pktRx_);
  723.       pktRx_=NULL;
  724.       return;
  725.     } 
  726.   }
  727.   switch (con->getType()) {
  728.   case CONN_INIT_RANGING:
  729.     scheduler_->process (pktRx_);
  730.     break;
  731.   case CONN_AAS_INIT_RANGING:
  732.     break;
  733.   case CONN_MULTICAST_POLLING: 
  734.     break;
  735.   case CONN_PADDING:
  736.     //padding is sent by a SS that does not have data
  737.     //to send is required to send a signal.
  738.     //TBD: Find the SS that sent the padding
  739.     scheduler_->process (pktRx_);
  740.     break; 
  741.   case CONN_BROADCAST:
  742.     if (HDR_CMN(pktRx_)->ptype()==PT_MAC)
  743.       scheduler_->process (pktRx_);
  744.     else {
  745.       //Richard: only send to upper layer if connected
  746.       if (state_ == MAC802_16_CONNECTED)
  747. goto send_upper;
  748.       else {
  749. //update drop stat, could be used to detect deconnection
  750. update_watch (&loss_watch_, 1);
  751. Packet::free(pktRx_);
  752. pktRx_=NULL;
  753. return;
  754.       }
  755.     }
  756.     break; 
  757.   case CONN_BASIC:
  758.     scheduler_->process (pktRx_);
  759.     break; 
  760.   case CONN_PRIMARY:
  761.     assert (HDR_CMN(pktRx_)->ptype()==PT_MAC);
  762.     //we cast to this frame because all management frame start with a type
  763.     if (wimaxHdr->header.ht==1) {
  764.       //bw request
  765.       scheduler_->process (pktRx_);
  766.     } else {
  767.       frame = (mac802_16_dl_map_frame*) pktRx_->accessdata();
  768.       switch (frame->type) {
  769.       case MAC_DSA_REQ: 
  770.       case MAC_DSA_RSP: 
  771.       case MAC_DSA_ACK: 
  772. serviceFlowHandler_->process (pktRx_);
  773. break;
  774.       default:
  775. scheduler_->process (pktRx_);
  776.       }
  777.     }
  778.     break;   
  779.   case CONN_SECONDARY:
  780.     //fall through
  781.   case CONN_DATA:
  782.     //send to upper layer
  783.     goto send_upper;
  784.     break; 
  785.   default:
  786.     fprintf (stderr,"Error: unknown connection typen");
  787.     exit (0);
  788.   }
  789.   goto sent_mac; //default jump
  790.  send_upper:
  791.   update_throughput (&rx_data_watch_, 8*ch->size());    
  792.   update_throughput (&rx_traffic_watch_, 8*ch->size());
  793.   ch->size() -= HDR_MAC802_16_SIZE;
  794.   uptarget_->recv(pktRx_, (Handler*) 0);
  795.   goto done;
  796.  sent_mac:
  797.   update_throughput (&rx_traffic_watch_, 8*ch->size());
  798.   //fall through
  799.   //should not free it here because we don't know if other modules
  800.   //kept a copy of it.
  801.   //Packet::free(pktRx_);
  802.   //update Rx stat
  803.  done:
  804.   update_watch (&loss_watch_, 0);
  805.   pktRx_=NULL;
  806. }
  807. /**** Helper methods ****/
  808. /**
  809.  * Return the frame number
  810.  * @return the frame number
  811.  */
  812. int Mac802_16::getFrameNumber () {
  813.   return frame_number_;
  814. }
  815. /*
  816.  * Return the code for the frame duration
  817.  * @return the code for the frame duration
  818.  */
  819. int Mac802_16::getFrameDurationCode () {
  820.   if (macmib_.frame_duration == 0.0025)
  821.     return 0;
  822.   else if (macmib_.frame_duration == 0.004)
  823.     return 1;
  824.   else if (macmib_.frame_duration == 0.005)
  825.     return 2;
  826.   else if (macmib_.frame_duration == 0.008)
  827.     return 3;
  828.   else if (macmib_.frame_duration == 0.01)
  829.     return 4;
  830.   else if (macmib_.frame_duration == 0.0125)
  831.     return 5;
  832.   else if (macmib_.frame_duration == 0.02)
  833.     return 6;
  834.   else {
  835.     fprintf (stderr, "Invalid frame duration %fn", macmib_.frame_duration);
  836.     exit (1);
  837.   }
  838. }
  839. /*
  840.  * Set the frame duration using code
  841.  * @param code The frame duration code
  842.  */
  843. void Mac802_16::setFrameDurationCode (int code) 
  844. {
  845.   switch (code) {
  846.   case 0:
  847.     macmib_.frame_duration = 0.0025;
  848.     break;
  849.   case 1:
  850.     macmib_.frame_duration = 0.004;
  851.     break;
  852.   case 2:
  853.     macmib_.frame_duration = 0.005;
  854.     break;
  855.   case 3:
  856.     macmib_.frame_duration = 0.008;
  857.     break;
  858.   case 4:
  859.     macmib_.frame_duration = 0.01;
  860.     break;
  861.   case 5:
  862.     macmib_.frame_duration = 0.0125;
  863.     break;
  864.   case 6:
  865.     macmib_.frame_duration = 0.02;
  866.     break;
  867.   default:
  868.   fprintf (stderr, "Invalid frame duration code %dn", code);
  869.     exit (1);
  870.   }
  871. }
  872. /**
  873.  * Return a packet 
  874.  * @return a new packet
  875.  */
  876. Packet *Mac802_16::getPacket ()
  877. {
  878.   Packet *p = Packet::alloc ();
  879.   
  880.   hdr_mac802_16 *wimaxHdr= HDR_MAC802_16(p);
  881.   //set header information
  882.   wimaxHdr->header.ht = 0;
  883.   wimaxHdr->header.ec = 1;
  884.   wimaxHdr->header.type = 0; //no subheader
  885.   wimaxHdr->header.ci = 0;
  886.   wimaxHdr->header.eks = 0;
  887.   wimaxHdr->header.cid = BROADCAST_CID; //default
  888.   wimaxHdr->header.hcs = 0;
  889.   HDR_CMN(p)->ptype() = PT_MAC;
  890.   HDR_CMN(p)->size() = HDR_MAC802_16_SIZE;
  891.   return p;
  892. }
  893. /**** Internal methods ****/
  894. /*
  895.  * Add a classifier
  896.  * @param clas The classifier to add
  897.  */
  898. void Mac802_16::addClassifier (SDUClassifier *clas) 
  899. {
  900.   SDUClassifier *n=classifier_list_.lh_first;
  901.   SDUClassifier *prev=NULL;
  902.   int i = 0;
  903.   if (!n || (n->getPriority () >= clas->getPriority ())) {
  904.     //the first element
  905.     //debug ("Add first classifiern");
  906.     clas->insert_entry_head (&classifier_list_);
  907.   } else {
  908.     while ( n && (n->getPriority () < clas->getPriority ()) ) {
  909.       prev=n;
  910.       n=n->next_entry();
  911.       i++;
  912.     }
  913.     //debug ("insert entry at position %dn", i);
  914.     clas->insert_entry (prev);
  915.   }
  916.   //Register this mac with the classifier
  917.   clas->setMac (this);
  918. }
  919. #ifdef USE_802_21
  920. /* 
  921.  * Configure/Request configuration
  922.  * The upper layer sends a config object with the required 
  923.  * new values for the parameters (or PARAMETER_UNKNOWN_VALUE).
  924.  * The MAC tries to set the values and return the new setting.
  925.  * For examples if a MAC does not support a parameter it will
  926.  * return  PARAMETER_UNKNOWN_VALUE
  927.  * @param config The configuration object
  928.  */ 
  929. void Mac802_16::link_configure (link_parameter_config_t* config)
  930. {
  931. assert (config);
  932. config->bandwidth = 15000000; //TBD use phy (but depend on modulation)
  933. config->type = LINK_802_16;
  934. //we set the rest to PARAMETER_UNKNOWN_VALUE
  935. config->ber = PARAMETER_UNKNOWN_VALUE;
  936. config->delay = PARAMETER_UNKNOWN_VALUE;
  937. config->macPoA = PARAMETER_UNKNOWN_VALUE;
  938. }
  939. /*
  940.  * Disconnect from the PoA
  941.  */
  942. void Mac802_16::link_disconnect ()
  943. {
  944.   if (type_ == STA_MN) {
  945.     //force losing synchronization
  946.     ((SSscheduler*) scheduler_)->lost_synch ();
  947.     getPhy()->node_off();
  948.   }
  949. }
  950. /*
  951.  * Connect to the PoA
  952.  */
  953. void Mac802_16::link_connect (int poa)
  954. {
  955.   if (type_ == STA_MN) {
  956.     getPhy()->node_on();
  957.   }
  958. }
  959. /* 
  960.  * Configure the threshold values for the given parameters
  961.  * @param numLinkParameter number of parameter configured
  962.  * @param linkThresholds list of parameters and thresholds
  963.  */
  964. struct link_param_th_status * Mac802_16::link_configure_thresholds (int numLinkParameter, struct link_param_th *linkThresholds)
  965. {
  966.   struct link_param_th_status *result = (struct link_param_th_status *) malloc(numLinkParameter * sizeof (struct link_param_th_status));
  967.   StatWatch *watch=NULL;
  968.   for (int i=0 ; i < numLinkParameter ; i++) {
  969.     result[i].parameter = linkThresholds[i].parameter;
  970.     result[i].status = 1; //accepted..default
  971.     switch (linkThresholds[i].parameter){
  972.     case LINK_PACKET_LOSS: 
  973.       watch = &loss_watch_;
  974.       break;
  975.     case LINK_PACKET_DELAY:
  976.       watch = &delay_watch_;
  977.       break;
  978.     case LINK_PACKET_JITTER:
  979.       watch = &jitter_watch_;
  980.       break;
  981.     case LINK_RX_DATA_THROUGHPUT:
  982.       watch = &rx_data_watch_;
  983.       break;
  984.     case LINK_RX_TRAFFIC_THROUGHPUT:
  985.       watch = &rx_traffic_watch_;
  986.       break;
  987.     case LINK_TX_DATA_THROUGHPUT:
  988.       watch = &tx_data_watch_;
  989.       break;
  990.     case LINK_TX_TRAFFIC_THROUGHPUT:
  991.       watch = &tx_traffic_watch_;
  992.       break;
  993.     default:
  994.       fprintf (stderr, "Parameter type not supported %dn", linkThresholds[i].parameter);
  995.       result[i].status = 0; //rejected
  996.     }
  997.     watch->set_thresholds (linkThresholds[i].initActionTh.data_d, 
  998.    linkThresholds[i].rollbackActionTh.data_d ,
  999.    linkThresholds[i].exectActionTh.data_d);
  1000.   }
  1001.   return result;
  1002. }
  1003.  
  1004. #endif
  1005. /**
  1006.  * Update the given timer and check if thresholds are crossed
  1007.  * @param watch the stat watch to update
  1008.  * @param value the stat value
  1009.  */
  1010. void Mac802_16::update_watch (StatWatch *watch, double value)
  1011. {
  1012.   char *name;
  1013. #ifdef USE_802_21 //Switch to activate when using 802.21 modules (external package)
  1014.   threshold_action_t action = watch->update (value);
  1015.   if (action != NO_ACTION_TH) {
  1016.     link_parameter_t param;
  1017.     union param_value old_value, new_value;
  1018.     if (watch == &loss_watch_) {
  1019.       param = LINK_PACKET_LOSS;
  1020.     } else if (watch == &delay_watch_) {
  1021.       param = LINK_PACKET_DELAY;
  1022.     } else if (watch == &jitter_watch_) {
  1023.       param = LINK_PACKET_JITTER;
  1024.     }
  1025.     old_value.data_d = watch->old_average();
  1026.     new_value.data_d = watch->average();
  1027.     send_link_parameter_change (addr(), param, old_value, new_value);      
  1028.   }
  1029. #endif
  1030.   if (watch == &loss_watch_) {
  1031.     name = "loss";
  1032.   } else if (watch == &delay_watch_) {
  1033.     name = "delay";
  1034.   } else if (watch == &jitter_watch_) {
  1035.     name = "jitter";
  1036.   } else {
  1037.     name = "other";
  1038.   }
  1039.   if (print_stats_)
  1040.     printf ("At %f in Mac %d, updating stats %s: %fn", NOW, addr(), name, watch->average());
  1041. }
  1042. /**
  1043.  * Update the given timer and check if thresholds are crossed
  1044.  * @param watch the stat watch to update
  1045.  * @param value the stat value
  1046.  */
  1047. void Mac802_16::update_throughput (ThroughputWatch *watch, double size)
  1048. {
  1049.   char *name;
  1050. #ifdef USE_802_21 //Switch to activate when using 802.21 modules (external package)
  1051.   threshold_action_t action = watch->update (size, NOW);
  1052.   if (action != NO_ACTION_TH) {
  1053.     link_parameter_t param;
  1054.     union param_value old_value, new_value;
  1055.     if (watch == &rx_data_watch_) {
  1056.       param = LINK_RX_DATA_THROUGHPUT;
  1057.     } else if (watch == &rx_traffic_watch_) {
  1058.       param = LINK_RX_TRAFFIC_THROUGHPUT;
  1059.     } else if (watch == &tx_data_watch_) {
  1060.       param = LINK_TX_DATA_THROUGHPUT;
  1061.     } else if (watch == &tx_traffic_watch_) {
  1062.       param = LINK_TX_TRAFFIC_THROUGHPUT;
  1063.     }
  1064.     old_value.data_d = watch->old_average();
  1065.     new_value.data_d = watch->average();
  1066.     send_link_parameter_change (addr(), param, old_value, new_value);      
  1067.   }
  1068. #endif 
  1069.   if (watch == &rx_data_watch_) {
  1070.     name = "rx_data";
  1071.     rx_data_timer_->resched (watch->get_timer_interval());
  1072.   } else if (watch == &rx_traffic_watch_) {
  1073.     rx_traffic_timer_->resched (watch->get_timer_interval());
  1074.     name = "rx_traffic";
  1075.   } else if (watch == &tx_data_watch_) {
  1076.     tx_data_timer_->resched (watch->get_timer_interval());
  1077.     name = "tx_data";
  1078.   } else if (watch == &tx_traffic_watch_) {
  1079.     tx_traffic_timer_->resched (watch->get_timer_interval());
  1080.     name = "tx_traffic";
  1081.   }
  1082.   if (print_stats_)
  1083.     printf ("At %f in Mac %d, updating stats %s: %fn", NOW, addr(), name, watch->average());
  1084. }