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

网络

开发平台:

C/C++

  1. /* This class contains the control agent located in IEEE 802.16 BS responsible
  2.  * for synchronization between BSs.
  3.  * This software was developed at the National Institute of Standards and
  4.  * Technology by employees of the Federal Government in the course of
  5.  * their official duties. Pursuant to title 17 Section 105 of the United
  6.  * States Code this software is not subject to copyright protection and
  7.  * is in the public domain.
  8.  * NIST assumes no responsibility whatsoever for its use by other parties,
  9.  * and makes no guarantees, expressed or implied, about its quality,
  10.  * reliability, or any other characteristic.
  11.  * <BR>
  12.  * We would appreciate acknowledgement if the software is used.
  13.  * <BR>
  14.  * NIST ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
  15.  * DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
  16.  * FROM THE USE OF THIS SOFTWARE.
  17.  * </PRE></P>
  18.  * @author  rouil
  19.  */
  20. #include "wimaxctrlagent.h"
  21. #include "mac802_16.h" 
  22. #include "bsscheduler.h"
  23. #define MYNUM Address::instance().print_nodeaddr(addr())
  24. int hdr_wimaxbs::offset_;
  25. /**
  26.  * Tcl hook for Packet definitions
  27.  */
  28. static class WimaxBSHeaderClass : public PacketHeaderClass {
  29. public:
  30. WimaxBSHeaderClass() : PacketHeaderClass("PacketHeader/WIMAXBS",
  31.      sizeof(hdr_wimaxbs)) {
  32.     bind_offset(&hdr_wimaxbs::offset_);
  33.         }
  34. } class_wimaxbshdr;
  35. /**
  36.  * Tcl hook for agent 
  37.  */
  38. static class WimaxCtrlAgentClass : public TclClass {
  39. public:
  40. WimaxCtrlAgentClass() : TclClass("Agent/WimaxCtrl") {}
  41. TclObject* create(int, const char*const*) {
  42. return (new WimaxCtrlAgent());
  43. }
  44. } class_wimaxctrlagent;
  45. /*
  46.  * Handler for timer expiration
  47.  */
  48. void UpdateTimer::expire (Event*)
  49. {
  50.   a_->sendUpdate();
  51. }
  52. /*
  53.  * Handler for response timer expiration
  54.  */
  55. void ScanRspTimer::expire (Event*)
  56. {
  57.   a_->agent()->send_scan_response(a_->cid());
  58. }
  59. /*
  60.  * Creates a Wimax controler agent
  61.  * Initializes the agent and bind variable to be accessible in TCL
  62.  */
  63. WimaxCtrlAgent::WimaxCtrlAgent() : Agent(PT_WIMAXBS), mac_(0), updatetimer_ (this)
  64. {
  65.   nbmapentry_=0;
  66.   LIST_INIT (&scan_req_head_);
  67.   //bind attributes
  68.   bind ("adv_interval_", &adv_interval_);
  69.   bind ("default_association_level_", &defaultlevel_);
  70.   bind ("synch_frame_delay_", &synch_frame_delay_);
  71.   //schedule first update
  72.   updatetimer_.sched (Random::uniform(0, UPDATE_JITTER));
  73. }
  74. /* 
  75.  * Interface with TCL interpreter
  76.  * @param argc The number of elements in argv
  77.  * @param argv The list of arguments
  78.  * @return TCL_OK if everything went well else TCL_ERROR
  79.  */
  80. int WimaxCtrlAgent::command(int argc, const char*const* argv)
  81. {
  82.   Tcl& tcl= Tcl::instance();
  83.   if (argc == 3) {
  84.     // set the Minimum interval between two RAs
  85.     if (strcmp(argv[1], "set-mac") == 0) {
  86.       mac_ = (Mac802_16*) TclObject::lookup(argv[2]);
  87.       ((BSScheduler*)mac_->getScheduler())->setCtrlAgent (this);
  88.       return TCL_OK;
  89.     }
  90.     else if (strcmp(argv[1], "add-neighbor") == 0) {
  91.       //the parameter is the mac, and we also extract the node
  92.       Mac802_16 *tmp = (Mac802_16 *) TclObject::lookup(argv[2]);
  93.       if (nbmapentry_ == MAX_MAP_ENTRY) {
  94. fprintf (stderr, "Table size exceeding. Increase MAX_MAP_ENTRYn");
  95.       }
  96.       tcl.evalf ("%s get-node", argv[2]);
  97.       Node *tmpNode = (Node *) TclObject::lookup(tcl.result());
  98.       //add entry
  99.       maptable_[nbmapentry_][0] = tmp->addr();
  100.       maptable_[nbmapentry_][1] = tmpNode->address();
  101.       debug ("Adding neighbor %s (mac %d) in %sn", Address::instance().print_nodeaddr(tmpNode->address()),
  102.       tmp->addr(), MYNUM);
  103.       nbmapentry_++;
  104.       return TCL_OK;
  105.     }
  106.   }
  107.   return (Agent::command(argc, argv));
  108. }
  109. /*
  110.  * Send an update (DCD/UCD) to all neighboring BSs
  111.  */
  112. void WimaxCtrlAgent::sendUpdate ()
  113. {
  114.   //get the DCD/UCD message to include in the update
  115.   Packet *dcd = mac_->getScheduler()->map_->getDCD();
  116.   Packet *ucd = mac_->getScheduler()->map_->getUCD();
  117.   //allocate data to store information
  118.   mac802_16_dcd_frame *dcdframe = (mac802_16_dcd_frame*) dcd->accessdata();
  119.   mac802_16_ucd_frame *ucdframe = (mac802_16_ucd_frame*) ucd->accessdata();
  120.   
  121.   Packet *p = allocpkt();
  122.   hdr_ip *iph = HDR_IP(p);
  123.   hdr_wimaxbs *rh = HDR_WIMAXBS(p);
  124.   hdr_cmn *hdrc = HDR_CMN(p);
  125.   
  126.   rh->getType() = WIMAX_BS_ADV; 
  127.   hdrc->size() = HDR_CMN(dcd)->size()+HDR_CMN(ucd)->size(); //TBD: remove double header
  128.   //set content
  129.   rh->macAddr() = mac_->addr();
  130.   p->allocdata (sizeof (mac802_16_dcd_frame)+sizeof (mac802_16_ucd_frame)); 
  131.   unsigned char *data = p->accessdata();
  132.   memcpy (data, dcdframe, sizeof (mac802_16_dcd_frame));
  133.   memcpy (data+sizeof (mac802_16_dcd_frame), ucdframe, sizeof (mac802_16_ucd_frame));
  134.   
  135.   Packet *tmpPkt; 
  136.   for (int i = 0; i < nbmapentry_ ; i++) {
  137.     tmpPkt = p->copy();
  138.     iph = HDR_IP(tmpPkt);
  139.     //set packet destination
  140.     iph->daddr() = maptable_[i][1];
  141.     iph->dport() = port();
  142.     debug ("At %f in node %s, send update to node %sn", NOW, MYNUM,Address::instance().print_nodeaddr(iph->daddr()));
  143.     debug ("frame number=%dn", dcdframe->frame_number);
  144.     send(tmpPkt, 0);
  145.   }
  146.   //reschedule timer
  147.   updatetimer_.resched (adv_interval_);
  148. }
  149. /* 
  150.  * Process received packet
  151.  * @param p The packet received
  152.  * @param h The handler that sent the packet
  153.  */
  154. void WimaxCtrlAgent::recv(Packet* p, Handler *h)
  155. {
  156.   assert (p);
  157.   hdr_wimaxbs *rh = HDR_WIMAXBS(p);
  158.   switch (rh->getType()) {
  159.   case WIMAX_BS_ADV:
  160.     processUpdate (p);
  161.     break;
  162.   case WIMAX_BS_SYNCH_REQ:
  163.     process_synch_request (p);
  164.     break;
  165.   case WIMAX_BS_SYNCH_RSP:
  166.     process_synch_response (p);
  167.     break;
  168.   default:
  169.     fprintf (stderr, "Unknown message type in WimaxCtrlAgentn");
  170.   }
  171.   Packet::free (p);
  172. }
  173. /* 
  174.  * Process received packet
  175.  * @param p The update received
  176.  * @param h The handler that sent the packet
  177.  */
  178. void WimaxCtrlAgent::processUpdate(Packet* p)
  179. {
  180.   debug ("At %f in node %s, WimaxCtrlAgent received update message from %sn", NOW, MYNUM,
  181.  Address::instance().print_nodeaddr(HDR_IP(p)->saddr()));
  182.   hdr_wimaxbs *rh = HDR_WIMAXBS(p);
  183.   NeighborEntry *entry = mac_->getScheduler()->nbr_db_->getNeighbor(rh->macAddr());
  184.   //check if we know about this neighbor
  185.   bool found = false;
  186.   for (int i = 0; i < nbmapentry_ ; i++) {
  187.     if (maptable_[i][1]==HDR_IP(p)->saddr())
  188.       found = true;
  189.   }
  190.   assert (found);
  191.   if (entry==NULL) {
  192.     debug ("tNew neighbor detected...add entry for mac %dn", rh->macAddr());
  193.     entry = new NeighborEntry (rh->macAddr());
  194.     mac_->getScheduler()->nbr_db_->addNeighbor(entry);
  195.   }
  196.   //update entry
  197.   unsigned char *data = p->accessdata();
  198.   mac802_16_dcd_frame *dcdframe = (mac802_16_dcd_frame *)malloc (sizeof (mac802_16_dcd_frame));
  199.   mac802_16_ucd_frame *ucdframe = (mac802_16_ucd_frame *)malloc (sizeof (mac802_16_ucd_frame));
  200.   memcpy (dcdframe, data, sizeof (mac802_16_dcd_frame));
  201.   memcpy (ucdframe, data+sizeof (mac802_16_dcd_frame), sizeof (mac802_16_ucd_frame));
  202.   debug ("tframe number=%d ccc=%dn", dcdframe->frame_number,ucdframe->config_change_count);
  203.   mac802_16_dcd_frame *dcdtmp = entry->getDCD();
  204.   if (dcdtmp)
  205.     free(dcdtmp);
  206.   mac802_16_ucd_frame *ucdtmp = entry->getUCD();
  207.   if (ucdtmp)
  208.     free(ucdtmp);
  209.   entry->setDCD (dcdframe);
  210.   entry->setUCD (ucdframe);
  211.   //free (p);
  212. }
  213. /**
  214.  * Process scanning request
  215.  * @param p The request
  216.  */
  217. void WimaxCtrlAgent::process_scan_request (Packet *req)
  218. {
  219.   hdr_mac802_16 *wimaxHdr_req = HDR_MAC802_16(req);
  220.   gen_mac_header_t header_req = wimaxHdr_req->header;
  221.   mac802_16_mob_scn_req_frame *req_frame;
  222.   req_frame = (mac802_16_mob_scn_req_frame*) req->accessdata();
  223.   mac_->debug ("At %f in Mac %d received scanning request from %dn", NOW, mac_->addr(), header_req.cid);
  224.   
  225.   //for first implementation we disregard the information 
  226.   //sent by MN. Just use default association mechanisms
  227.   //should check if there is already pending request: TBD
  228.   Scan_req *entry = new Scan_req (this, synch_frame_delay_*mac_->getFrameDuration(), header_req.cid, req_frame);
  229.   entry->insert_entry (&scan_req_head_);
  230.   entry->start_frame()=mac_->getFrameNumber();
  231.   switch (defaultlevel_){
  232.   case 0: //Scan without association
  233.     entry->response()->scan_duration = req_frame->scan_duration;
  234.     entry->response()->start_frame = 2;
  235.     entry->response()->report_mode = 0; //no report for now
  236.     entry->response()->interleaving_interval = req_frame->interleaving_interval;
  237.     entry->response()->scan_iteration = req_frame->scan_iteration;
  238.     entry->response()->n_recommended_bs_index = 0;
  239.     entry->response()->n_recommended_bs_full = nbmapentry_;
  240.     for (int i = 0; i < nbmapentry_ ; i++) {
  241.       entry->response()->rec_bs_full[i].recommended_bs_id = maptable_[i][0];
  242.       entry->response()->rec_bs_full[i].scanning_type = SCAN_WITHOUT_ASSOC;
  243.     }
  244.     //send response
  245.     ((BSScheduler*)mac_->getScheduler())->send_scan_response (entry->response(), header_req.cid);
  246.     //clean data
  247.     entry->remove_entry();
  248.     delete entry;
  249.     break;
  250.   case 1: //Association without coordination
  251.     entry->response()->scan_duration = req_frame->scan_duration;
  252.     entry->response()->start_frame = 2;
  253.     entry->response()->report_mode = 0; //no report for now
  254.     entry->response()->interleaving_interval = req_frame->interleaving_interval;
  255.     entry->response()->scan_iteration = req_frame->scan_iteration;
  256.     entry->response()->n_recommended_bs_index = 0;
  257.     entry->response()->n_recommended_bs_full = nbmapentry_;
  258.     for (int i = 0; i < nbmapentry_ ; i++) {
  259.       entry->response()->rec_bs_full[i].recommended_bs_id = maptable_[i][0];
  260.       entry->response()->rec_bs_full[i].scanning_type = SCAN_ASSOC_LVL0;
  261.     }
  262.     //send response
  263.     ((BSScheduler*)mac_->getScheduler())->send_scan_response (entry->response(), header_req.cid);
  264.     //clean data
  265.     entry->remove_entry();
  266.     delete entry;
  267.     break;
  268.   case 2: //Association with coordination
  269.     //init data
  270.     entry->response()->n_recommended_bs_index = 0;
  271.     entry->response()->n_recommended_bs_full = 0;
  272.     entry->pending_rsp () = 0;
  273.  
  274.     //send request to neighbors
  275.     for (int i = 0; i < nbmapentry_ ; i++) {
  276.       Packet *p = allocpkt();
  277.       hdr_ip *iph = HDR_IP(p);
  278.       hdr_wimaxbs *rh = HDR_WIMAXBS(p);
  279.       hdr_cmn *hdrc = HDR_CMN(p);
  280.       
  281.       rh->getType() = WIMAX_BS_SYNCH_REQ; 
  282.       hdrc->size() = 30; //We need to define proper size
  283.       //set content
  284.       iph = HDR_IP(p);
  285.       iph->daddr() = maptable_[i][1];
  286.       iph->dport() = port();
  287.       
  288.       rh->macAddr() = mac_->getCManager()->get_connection(header_req.cid, true)->getPeerNode()->getPeerNode();
  289.       rh->cid = header_req.cid;
  290.       rh->scanning_type = (wimax_scanning_type) defaultlevel_;
  291.       //we suggest a rendez-vous time at the beginning of each 
  292.       //scan iteration
  293.       rh->current_frame = mac_->getFrameNumber();
  294.       //if we want to start scanning 2 frames after, then add one (i.e 3) because 
  295.       //the message will be sent on the next frame
  296.       printf ("scan_duration=%d, scan_interval=%dn", req_frame->scan_duration,
  297.       req_frame->interleaving_interval);
  298.       rh->rdvt = (i+1)*(req_frame->scan_duration+req_frame->interleaving_interval)+synch_frame_delay_+START_FRAME_OFFSET+1;
  299.       rh->rendezvous_time = NOW+rh->rdvt*mac_->getFrameDuration();     
  300.       printf ("Request: current frame=%d, rdv frame=%d, rdv time=%fn",
  301.       rh->current_frame, rh->rdvt, rh->rendezvous_time); 
  302.       entry->pending_rsp ()++;
  303.       send (p,0);
  304.       
  305.       entry->response()->n_recommended_bs_full = i + 1;
  306.       entry->response()->rec_bs_full[i].recommended_bs_id = maptable_[i][0];
  307.       entry->response()->rec_bs_full[i].scanning_type = rh->scanning_type;
  308.       entry->response()->rec_bs_full[i].rdv_time = rh->rdvt-synch_frame_delay_;  
  309.     }
  310.     //continue initializing response
  311.     entry->response()->scan_duration = req_frame->scan_duration;
  312.     entry->response()->start_frame = START_FRAME_OFFSET;
  313.     entry->response()->report_mode = 0; //no report for now
  314.     entry->response()->interleaving_interval = entry->request()->interleaving_interval;
  315.     entry->response()->scan_iteration = entry->request()->scan_iteration;
  316.     entry->response()->n_recommended_bs_index = 0;
  317.     
  318.     //printf ("Response: current frame=%d (now=%f), start in %d frame (t=%f)n",
  319.     //     mac_->getFrameNumber (), NOW, entry->response()->start_frame, NOW+(entry->response()->start_frame*mac_->getFrameDuration()));
  320.     //send response
  321.     //((BSScheduler*)mac_->getScheduler())->send_scan_response (entry->response(), entry->cid());
  322.     break;
  323.   case 3: //Network Assisted Association reporting
  324.     break;
  325.   default:
  326.     break;
  327.   }
  328. }
  329. /**
  330.  * Process synchronization request
  331.  * @param req The request
  332.  */
  333. void WimaxCtrlAgent::process_synch_request (Packet *req)
  334. {
  335.   debug ("At %f in node %s, WimaxCtrlAgent received synch request from %sn", NOW, MYNUM,
  336.  Address::instance().print_nodeaddr(HDR_IP(req)->saddr()));
  337.   //schedule rendez-vous time
  338.   //schedule sending of Fast-ranging-IE
  339.   ((BSScheduler*)mac_->getScheduler())->addNewFastRanging (HDR_WIMAXBS(req)->rendezvous_time, HDR_WIMAXBS(req)->macAddr());
  340.   
  341.   //send response
  342.   Packet *p = allocpkt();
  343.   hdr_ip *iph = HDR_IP(p);
  344.   hdr_wimaxbs *rh = HDR_WIMAXBS(p);
  345.   hdr_cmn *hdrc = HDR_CMN(p);
  346.   
  347.   rh->getType() = WIMAX_BS_SYNCH_RSP; 
  348.   hdrc->size() = 30; //We need to define proper size
  349.   //set content
  350.   iph = HDR_IP(p);
  351.   iph->daddr() = HDR_IP(req)->saddr();
  352.   iph->dport() = port();
  353.   
  354.   //we accept what the serving BS sent
  355.   rh->cid = HDR_WIMAXBS(req)->cid;
  356.   rh->scanning_type = HDR_WIMAXBS(req)->scanning_type;
  357.   rh->current_frame = HDR_WIMAXBS(req)->current_frame;
  358.   rh->rdvt = HDR_WIMAXBS(req)->rdvt;
  359.   rh->rendezvous_time = HDR_WIMAXBS(req)->rendezvous_time; 
  360.   //send (p,0);
  361. }
  362. /**
  363.  * Process synchronization response
  364.  * @param p The response
  365.  */
  366. void WimaxCtrlAgent::process_synch_response (Packet *p)
  367. {
  368.   debug ("At %f in node %s, WimaxCtrlAgent received synch response from %sn", NOW, MYNUM,
  369.  Address::instance().print_nodeaddr(HDR_IP(p)->saddr()));
  370.   hdr_wimaxbs *rh = HDR_WIMAXBS(p);
  371.   int i;
  372.   //update information
  373.   Scan_req *entry;
  374.   for (entry = scan_req_head_.lh_first ; entry && (entry->cid() != rh->cid); entry=entry->next_entry());
  375.   assert (entry);
  376.   i = entry->response()->n_recommended_bs_full;
  377.   entry->response()->n_recommended_bs_full = i + 1;
  378.   entry->response()->rec_bs_full[i].recommended_bs_id = maptable_[i][0];
  379.   entry->response()->rec_bs_full[i].scanning_type = rh->scanning_type;
  380.   entry->response()->rec_bs_full[i].rdv_time = rh->rdvt;
  381. }
  382. /**
  383.  * Send a scan response to the MN that has the given CID
  384.  * @param cid The CID of the MN
  385.  */
  386. void WimaxCtrlAgent::send_scan_response (int cid)
  387. {
  388.   Scan_req *entry;
  389.   for (entry = scan_req_head_.lh_first ; entry && (entry->cid() != cid); entry=entry->next_entry());
  390.   
  391.   assert (entry);
  392.   
  393.   entry->response()->scan_duration = entry->request()->scan_duration;
  394.   printf ("Response: current frame=%d, start frame=%d diff=%dn", 
  395.   mac_->getFrameNumber(), entry->start_frame(), 100-(mac_->getFrameNumber()-entry->start_frame()));
  396.   printf ("Response: current frame=%d (now=%f), start in %d frame (t=%f)n",
  397.   mac_->getFrameNumber (), NOW, entry->response()->start_frame, NOW+(entry->response()->start_frame*mac_->getFrameDuration()));
  398.   //send response
  399.   ((BSScheduler*)mac_->getScheduler())->send_scan_response (entry->response(), entry->cid());
  400.   //clean data
  401.   entry->remove_entry();
  402.   delete entry;
  403. }