wimaxctrlagent.cc
上传用户:hzie11
上传日期:2013-10-07
资源大小:1487k
文件大小:15k
- /* This class contains the control agent located in IEEE 802.16 BS responsible
- * for synchronization between BSs.
- * This software was developed at the National Institute of Standards and
- * Technology by employees of the Federal Government in the course of
- * their official duties. Pursuant to title 17 Section 105 of the United
- * States Code this software is not subject to copyright protection and
- * is in the public domain.
- * NIST assumes no responsibility whatsoever for its use by other parties,
- * and makes no guarantees, expressed or implied, about its quality,
- * reliability, or any other characteristic.
- * <BR>
- * We would appreciate acknowledgement if the software is used.
- * <BR>
- * NIST ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
- * DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
- * FROM THE USE OF THIS SOFTWARE.
- * </PRE></P>
- * @author rouil
- */
- #include "wimaxctrlagent.h"
- #include "mac802_16.h"
- #include "bsscheduler.h"
- #define MYNUM Address::instance().print_nodeaddr(addr())
- int hdr_wimaxbs::offset_;
- /**
- * Tcl hook for Packet definitions
- */
- static class WimaxBSHeaderClass : public PacketHeaderClass {
- public:
- WimaxBSHeaderClass() : PacketHeaderClass("PacketHeader/WIMAXBS",
- sizeof(hdr_wimaxbs)) {
- bind_offset(&hdr_wimaxbs::offset_);
- }
- } class_wimaxbshdr;
- /**
- * Tcl hook for agent
- */
- static class WimaxCtrlAgentClass : public TclClass {
- public:
- WimaxCtrlAgentClass() : TclClass("Agent/WimaxCtrl") {}
- TclObject* create(int, const char*const*) {
- return (new WimaxCtrlAgent());
- }
- } class_wimaxctrlagent;
- /*
- * Handler for timer expiration
- */
- void UpdateTimer::expire (Event*)
- {
- a_->sendUpdate();
- }
- /*
- * Handler for response timer expiration
- */
- void ScanRspTimer::expire (Event*)
- {
- a_->agent()->send_scan_response(a_->cid());
- }
- /*
- * Creates a Wimax controler agent
- * Initializes the agent and bind variable to be accessible in TCL
- */
- WimaxCtrlAgent::WimaxCtrlAgent() : Agent(PT_WIMAXBS), mac_(0), updatetimer_ (this)
- {
- nbmapentry_=0;
- LIST_INIT (&scan_req_head_);
- //bind attributes
- bind ("adv_interval_", &adv_interval_);
- bind ("default_association_level_", &defaultlevel_);
- bind ("synch_frame_delay_", &synch_frame_delay_);
- //schedule first update
- updatetimer_.sched (Random::uniform(0, UPDATE_JITTER));
- }
- /*
- * Interface with TCL interpreter
- * @param argc The number of elements in argv
- * @param argv The list of arguments
- * @return TCL_OK if everything went well else TCL_ERROR
- */
- int WimaxCtrlAgent::command(int argc, const char*const* argv)
- {
- Tcl& tcl= Tcl::instance();
- if (argc == 3) {
- // set the Minimum interval between two RAs
- if (strcmp(argv[1], "set-mac") == 0) {
- mac_ = (Mac802_16*) TclObject::lookup(argv[2]);
- ((BSScheduler*)mac_->getScheduler())->setCtrlAgent (this);
- return TCL_OK;
- }
- else if (strcmp(argv[1], "add-neighbor") == 0) {
- //the parameter is the mac, and we also extract the node
- Mac802_16 *tmp = (Mac802_16 *) TclObject::lookup(argv[2]);
- if (nbmapentry_ == MAX_MAP_ENTRY) {
- fprintf (stderr, "Table size exceeding. Increase MAX_MAP_ENTRYn");
- }
- tcl.evalf ("%s get-node", argv[2]);
- Node *tmpNode = (Node *) TclObject::lookup(tcl.result());
- //add entry
- maptable_[nbmapentry_][0] = tmp->addr();
- maptable_[nbmapentry_][1] = tmpNode->address();
- debug ("Adding neighbor %s (mac %d) in %sn", Address::instance().print_nodeaddr(tmpNode->address()),
- tmp->addr(), MYNUM);
- nbmapentry_++;
- return TCL_OK;
- }
- }
- return (Agent::command(argc, argv));
- }
- /*
- * Send an update (DCD/UCD) to all neighboring BSs
- */
- void WimaxCtrlAgent::sendUpdate ()
- {
- //get the DCD/UCD message to include in the update
- Packet *dcd = mac_->getScheduler()->map_->getDCD();
- Packet *ucd = mac_->getScheduler()->map_->getUCD();
- //allocate data to store information
- mac802_16_dcd_frame *dcdframe = (mac802_16_dcd_frame*) dcd->accessdata();
- mac802_16_ucd_frame *ucdframe = (mac802_16_ucd_frame*) ucd->accessdata();
-
- Packet *p = allocpkt();
- hdr_ip *iph = HDR_IP(p);
- hdr_wimaxbs *rh = HDR_WIMAXBS(p);
- hdr_cmn *hdrc = HDR_CMN(p);
-
- rh->getType() = WIMAX_BS_ADV;
- hdrc->size() = HDR_CMN(dcd)->size()+HDR_CMN(ucd)->size(); //TBD: remove double header
- //set content
- rh->macAddr() = mac_->addr();
- p->allocdata (sizeof (mac802_16_dcd_frame)+sizeof (mac802_16_ucd_frame));
- unsigned char *data = p->accessdata();
- memcpy (data, dcdframe, sizeof (mac802_16_dcd_frame));
- memcpy (data+sizeof (mac802_16_dcd_frame), ucdframe, sizeof (mac802_16_ucd_frame));
-
- Packet *tmpPkt;
- for (int i = 0; i < nbmapentry_ ; i++) {
- tmpPkt = p->copy();
- iph = HDR_IP(tmpPkt);
- //set packet destination
- iph->daddr() = maptable_[i][1];
- iph->dport() = port();
- debug ("At %f in node %s, send update to node %sn", NOW, MYNUM,Address::instance().print_nodeaddr(iph->daddr()));
- debug ("frame number=%dn", dcdframe->frame_number);
- send(tmpPkt, 0);
- }
- //reschedule timer
- updatetimer_.resched (adv_interval_);
- }
- /*
- * Process received packet
- * @param p The packet received
- * @param h The handler that sent the packet
- */
- void WimaxCtrlAgent::recv(Packet* p, Handler *h)
- {
- assert (p);
- hdr_wimaxbs *rh = HDR_WIMAXBS(p);
- switch (rh->getType()) {
- case WIMAX_BS_ADV:
- processUpdate (p);
- break;
- case WIMAX_BS_SYNCH_REQ:
- process_synch_request (p);
- break;
- case WIMAX_BS_SYNCH_RSP:
- process_synch_response (p);
- break;
- default:
- fprintf (stderr, "Unknown message type in WimaxCtrlAgentn");
- }
- Packet::free (p);
- }
- /*
- * Process received packet
- * @param p The update received
- * @param h The handler that sent the packet
- */
- void WimaxCtrlAgent::processUpdate(Packet* p)
- {
- debug ("At %f in node %s, WimaxCtrlAgent received update message from %sn", NOW, MYNUM,
- Address::instance().print_nodeaddr(HDR_IP(p)->saddr()));
- hdr_wimaxbs *rh = HDR_WIMAXBS(p);
- NeighborEntry *entry = mac_->getScheduler()->nbr_db_->getNeighbor(rh->macAddr());
- //check if we know about this neighbor
- bool found = false;
- for (int i = 0; i < nbmapentry_ ; i++) {
- if (maptable_[i][1]==HDR_IP(p)->saddr())
- found = true;
- }
- assert (found);
- if (entry==NULL) {
- debug ("tNew neighbor detected...add entry for mac %dn", rh->macAddr());
- entry = new NeighborEntry (rh->macAddr());
- mac_->getScheduler()->nbr_db_->addNeighbor(entry);
- }
- //update entry
- unsigned char *data = p->accessdata();
- mac802_16_dcd_frame *dcdframe = (mac802_16_dcd_frame *)malloc (sizeof (mac802_16_dcd_frame));
- mac802_16_ucd_frame *ucdframe = (mac802_16_ucd_frame *)malloc (sizeof (mac802_16_ucd_frame));
- memcpy (dcdframe, data, sizeof (mac802_16_dcd_frame));
- memcpy (ucdframe, data+sizeof (mac802_16_dcd_frame), sizeof (mac802_16_ucd_frame));
- debug ("tframe number=%d ccc=%dn", dcdframe->frame_number,ucdframe->config_change_count);
- mac802_16_dcd_frame *dcdtmp = entry->getDCD();
- if (dcdtmp)
- free(dcdtmp);
- mac802_16_ucd_frame *ucdtmp = entry->getUCD();
- if (ucdtmp)
- free(ucdtmp);
- entry->setDCD (dcdframe);
- entry->setUCD (ucdframe);
- //free (p);
- }
- /**
- * Process scanning request
- * @param p The request
- */
- void WimaxCtrlAgent::process_scan_request (Packet *req)
- {
- hdr_mac802_16 *wimaxHdr_req = HDR_MAC802_16(req);
- gen_mac_header_t header_req = wimaxHdr_req->header;
- mac802_16_mob_scn_req_frame *req_frame;
- req_frame = (mac802_16_mob_scn_req_frame*) req->accessdata();
- mac_->debug ("At %f in Mac %d received scanning request from %dn", NOW, mac_->addr(), header_req.cid);
-
- //for first implementation we disregard the information
- //sent by MN. Just use default association mechanisms
- //should check if there is already pending request: TBD
- Scan_req *entry = new Scan_req (this, synch_frame_delay_*mac_->getFrameDuration(), header_req.cid, req_frame);
- entry->insert_entry (&scan_req_head_);
- entry->start_frame()=mac_->getFrameNumber();
- switch (defaultlevel_){
- case 0: //Scan without association
- entry->response()->scan_duration = req_frame->scan_duration;
- entry->response()->start_frame = 2;
- entry->response()->report_mode = 0; //no report for now
- entry->response()->interleaving_interval = req_frame->interleaving_interval;
- entry->response()->scan_iteration = req_frame->scan_iteration;
- entry->response()->n_recommended_bs_index = 0;
- entry->response()->n_recommended_bs_full = nbmapentry_;
- for (int i = 0; i < nbmapentry_ ; i++) {
- entry->response()->rec_bs_full[i].recommended_bs_id = maptable_[i][0];
- entry->response()->rec_bs_full[i].scanning_type = SCAN_WITHOUT_ASSOC;
- }
- //send response
- ((BSScheduler*)mac_->getScheduler())->send_scan_response (entry->response(), header_req.cid);
- //clean data
- entry->remove_entry();
- delete entry;
- break;
- case 1: //Association without coordination
- entry->response()->scan_duration = req_frame->scan_duration;
- entry->response()->start_frame = 2;
- entry->response()->report_mode = 0; //no report for now
- entry->response()->interleaving_interval = req_frame->interleaving_interval;
- entry->response()->scan_iteration = req_frame->scan_iteration;
- entry->response()->n_recommended_bs_index = 0;
- entry->response()->n_recommended_bs_full = nbmapentry_;
- for (int i = 0; i < nbmapentry_ ; i++) {
- entry->response()->rec_bs_full[i].recommended_bs_id = maptable_[i][0];
- entry->response()->rec_bs_full[i].scanning_type = SCAN_ASSOC_LVL0;
- }
- //send response
- ((BSScheduler*)mac_->getScheduler())->send_scan_response (entry->response(), header_req.cid);
- //clean data
- entry->remove_entry();
- delete entry;
- break;
- case 2: //Association with coordination
- //init data
- entry->response()->n_recommended_bs_index = 0;
- entry->response()->n_recommended_bs_full = 0;
- entry->pending_rsp () = 0;
-
- //send request to neighbors
- for (int i = 0; i < nbmapentry_ ; i++) {
- Packet *p = allocpkt();
- hdr_ip *iph = HDR_IP(p);
- hdr_wimaxbs *rh = HDR_WIMAXBS(p);
- hdr_cmn *hdrc = HDR_CMN(p);
-
- rh->getType() = WIMAX_BS_SYNCH_REQ;
- hdrc->size() = 30; //We need to define proper size
- //set content
- iph = HDR_IP(p);
- iph->daddr() = maptable_[i][1];
- iph->dport() = port();
-
- rh->macAddr() = mac_->getCManager()->get_connection(header_req.cid, true)->getPeerNode()->getPeerNode();
- rh->cid = header_req.cid;
- rh->scanning_type = (wimax_scanning_type) defaultlevel_;
- //we suggest a rendez-vous time at the beginning of each
- //scan iteration
- rh->current_frame = mac_->getFrameNumber();
- //if we want to start scanning 2 frames after, then add one (i.e 3) because
- //the message will be sent on the next frame
- printf ("scan_duration=%d, scan_interval=%dn", req_frame->scan_duration,
- req_frame->interleaving_interval);
- rh->rdvt = (i+1)*(req_frame->scan_duration+req_frame->interleaving_interval)+synch_frame_delay_+START_FRAME_OFFSET+1;
- rh->rendezvous_time = NOW+rh->rdvt*mac_->getFrameDuration();
- printf ("Request: current frame=%d, rdv frame=%d, rdv time=%fn",
- rh->current_frame, rh->rdvt, rh->rendezvous_time);
- entry->pending_rsp ()++;
- send (p,0);
-
- entry->response()->n_recommended_bs_full = i + 1;
- entry->response()->rec_bs_full[i].recommended_bs_id = maptable_[i][0];
- entry->response()->rec_bs_full[i].scanning_type = rh->scanning_type;
- entry->response()->rec_bs_full[i].rdv_time = rh->rdvt-synch_frame_delay_;
- }
- //continue initializing response
- entry->response()->scan_duration = req_frame->scan_duration;
- entry->response()->start_frame = START_FRAME_OFFSET;
- entry->response()->report_mode = 0; //no report for now
- entry->response()->interleaving_interval = entry->request()->interleaving_interval;
- entry->response()->scan_iteration = entry->request()->scan_iteration;
- entry->response()->n_recommended_bs_index = 0;
-
- //printf ("Response: current frame=%d (now=%f), start in %d frame (t=%f)n",
- // mac_->getFrameNumber (), NOW, entry->response()->start_frame, NOW+(entry->response()->start_frame*mac_->getFrameDuration()));
- //send response
- //((BSScheduler*)mac_->getScheduler())->send_scan_response (entry->response(), entry->cid());
- break;
- case 3: //Network Assisted Association reporting
- break;
- default:
- break;
- }
- }
- /**
- * Process synchronization request
- * @param req The request
- */
- void WimaxCtrlAgent::process_synch_request (Packet *req)
- {
- debug ("At %f in node %s, WimaxCtrlAgent received synch request from %sn", NOW, MYNUM,
- Address::instance().print_nodeaddr(HDR_IP(req)->saddr()));
- //schedule rendez-vous time
- //schedule sending of Fast-ranging-IE
- ((BSScheduler*)mac_->getScheduler())->addNewFastRanging (HDR_WIMAXBS(req)->rendezvous_time, HDR_WIMAXBS(req)->macAddr());
-
- //send response
- Packet *p = allocpkt();
- hdr_ip *iph = HDR_IP(p);
- hdr_wimaxbs *rh = HDR_WIMAXBS(p);
- hdr_cmn *hdrc = HDR_CMN(p);
-
- rh->getType() = WIMAX_BS_SYNCH_RSP;
- hdrc->size() = 30; //We need to define proper size
- //set content
- iph = HDR_IP(p);
- iph->daddr() = HDR_IP(req)->saddr();
- iph->dport() = port();
-
- //we accept what the serving BS sent
- rh->cid = HDR_WIMAXBS(req)->cid;
- rh->scanning_type = HDR_WIMAXBS(req)->scanning_type;
- rh->current_frame = HDR_WIMAXBS(req)->current_frame;
- rh->rdvt = HDR_WIMAXBS(req)->rdvt;
- rh->rendezvous_time = HDR_WIMAXBS(req)->rendezvous_time;
- //send (p,0);
- }
- /**
- * Process synchronization response
- * @param p The response
- */
- void WimaxCtrlAgent::process_synch_response (Packet *p)
- {
- debug ("At %f in node %s, WimaxCtrlAgent received synch response from %sn", NOW, MYNUM,
- Address::instance().print_nodeaddr(HDR_IP(p)->saddr()));
- hdr_wimaxbs *rh = HDR_WIMAXBS(p);
- int i;
- //update information
- Scan_req *entry;
- for (entry = scan_req_head_.lh_first ; entry && (entry->cid() != rh->cid); entry=entry->next_entry());
- assert (entry);
- i = entry->response()->n_recommended_bs_full;
- entry->response()->n_recommended_bs_full = i + 1;
- entry->response()->rec_bs_full[i].recommended_bs_id = maptable_[i][0];
- entry->response()->rec_bs_full[i].scanning_type = rh->scanning_type;
- entry->response()->rec_bs_full[i].rdv_time = rh->rdvt;
- }
- /**
- * Send a scan response to the MN that has the given CID
- * @param cid The CID of the MN
- */
- void WimaxCtrlAgent::send_scan_response (int cid)
- {
- Scan_req *entry;
- for (entry = scan_req_head_.lh_first ; entry && (entry->cid() != cid); entry=entry->next_entry());
-
- assert (entry);
-
- entry->response()->scan_duration = entry->request()->scan_duration;
- printf ("Response: current frame=%d, start frame=%d diff=%dn",
- mac_->getFrameNumber(), entry->start_frame(), 100-(mac_->getFrameNumber()-entry->start_frame()));
- printf ("Response: current frame=%d (now=%f), start in %d frame (t=%f)n",
- mac_->getFrameNumber (), NOW, entry->response()->start_frame, NOW+(entry->response()->start_frame*mac_->getFrameDuration()));
- //send response
- ((BSScheduler*)mac_->getScheduler())->send_scan_response (entry->response(), entry->cid());
- //clean data
- entry->remove_entry();
- delete entry;
- }