FreakZ學習筆記:路由發現機制

路由發現機制

路由發現機制只有在發送通信包的過程中會被調用,而接收過程因爲發送時候已經進行了通信鏈路的掃描和連接,所以不會再進行路由發現機制。

         路由的所有處理機制都是在NWK層進行的,當然,路由發現機制也一樣。當協議棧進行數據發送時,會依次按照APP->APS->NWK->MAC->PHY->Radio的層次關係來進行,APS層執行完成之後,會跳轉到NWK層的nwk_data_req函數,該函數爲NWK數據請求服務,接收APS層的數據並且加上NWK層的包頭,然後將數據打包。nwk_data_req函數執行完成自後會跳轉到void nwk_fwd(buffer_t *buf, nwk_hdr_t *hdr_in)函數,該函數描述如下:

/**************************************************************************/

/*!

    This function is the work horse of the NWK layer. It takes a frame from

    either the data request or the data indication functions (if the dest address

    is not for this node). It will look at the dest address and determine

    how this frame should be transmitted. The forwarding choices are:

    1) broadcast

    2) neighbor table   (the dest is a neighbor of ours)

    3) routing table    (the route path exists)

    4) route discovery  (the route path does not exist but mesh routing is okay)

    5) tree             (none of the above and the route discovery flag is disabled)

*/

/**************************************************************************/

void nwk_fwd(buffer_t *buf, nwk_hdr_t *hdr_in)函數是NWK傳輸層的一個主要函數,它構成了一個數據請求或者數據指示功能的幀(如果該幀數據的目的地址不是當前節點的地址),它將會查找地址並且確定這個幀數據應該怎麼樣被傳輸,主要的傳輸方法有(1)通過廣播傳輸;(2)通過鄰接點傳輸,前提是目的地址在我們的鄰接點裏;(3)通過路由表傳輸,前提是存在合適的路由表;(4)路由發現,如果當前保存的路由機制無法傳輸該幀信息到目的地址,但是mesh路由是可以的,這個時候就需要運行該機制;(5)通過樹形結構傳輸,如果以上的四種機制都不符合並且不允許路由發現機制的時候,使用該機制;其函數原型如下:

void nwk_fwd(buffer_t *buf, nwk_hdr_t *hdr_in)

{

    U16 next_hop;

    nwk_hdr_t hdr_out;

    mac_hdr_t mac_hdr_out;

    bool indirect = false;

    address_t dest_addr;

    mem_ptr_t *nbor_mem_ptr;

 

    hdr_out.mac_hdr         = &mac_hdr_out;

    dest_addr.mode          = SHORT_ADDR;

    dest_addr.short_addr    = hdr_in->dest_addr;

 

    // is it a broadcast?

   if ((hdr_in->dest_addr & NWK_BROADCAST_MASK) == 0xFFF0)

    {

        // the buffer data ptr (dptr) is pointing to the nwk payload now. calc the length of the nwk

        // payload. then we can re-use the buffer, slap on the nwk hdr, and send it back down

        // the stack.

        //

        //lint -e{734} Info 734: Loss of precision (assignment) (31 bits to 8 bits)

        // its okay since we're subtracting a value from a constant

        buf->len = aMaxPHYPacketSize - (buf->dptr - buf->buf);

 

        // need to change the mac dest address to broadcast in case it isn't. Also change the src

        // addr to the address of this device.

        hdr_out.mac_hdr->dest_addr.short_addr       = MAC_BROADCAST_ADDR;

        hdr_out.src_addr                            = hdr_in->src_addr;

    }

    // is the dest in our neighbor table?

    else if ((nbor_mem_ptr = nwk_neighbor_tbl_get_entry(&dest_addr)) != NULL)

    {

 

        // check to see if the dest address is in our neighbor table

        if (hdr_in->src_addr != nib.short_addr)

        {

            //lint -e{734} Info 734: Loss of precision (assignment) (31 bits to 8 bits)

            // its okay since we're subtracting a value from a constant

            buf->len = aMaxPHYPacketSize - (buf->dptr - buf->buf);

        }

 

        // if the neighbor does not keep its rx on when idle (ie: sleeping), then we need to send

        // the frame indirectly.

        if (!NBOR_ENTRY(nbor_mem_ptr)->rx_on_when_idle)

        {

            indirect = true;

        }

 

        // set the mac dest addr to the neighbor address

        hdr_out.mac_hdr->dest_addr.short_addr       = hdr_in->dest_addr;

        hdr_out.src_addr                            = hdr_in->src_addr;

    }

    // is the dest in our routing table?

    else if ((next_hop = nwk_rte_tbl_get_next_hop(hdr_in->dest_addr)) != INVALID_NWK_ADDR)

    {

        // it's in the routing table. forward it.

        // the buffer dptr is pointing to the nwk payload now. calc the length of the nwk

        // payload. then we can re-use the buffer, slap on the nwk hdr, and send it back down

        // the stack.

        //

        //lint -e{734} Info 734: Loss of precision (assignment) (31 bits to 8 bits)

        // its okay since we're subtracting a value from a constant

        buf->len = aMaxPHYPacketSize - (buf->dptr - buf->buf);

 

        // set the mac dest addr to the next hop and the nwk src addr to the originator

        hdr_out.mac_hdr->dest_addr.short_addr       = next_hop;

        hdr_out.src_addr                            = hdr_in->src_addr;

    }

    // are we allowed to discover the route?

   else if (hdr_in->nwk_frm_ctrl.disc_route)   //路由發現

    {

        // the destination isn't in our routing tables. discover route is enabled for the

        // frame so we can buffer it and initiate route discovery.

        nwk_pend_add_new(buf, hdr_in);

        nwk_rte_mesh_disc_start(hdr_in->dest_addr);

        return;

    }

    // if all else fails, route it along the tree

    else

    {

        // tree routing is the default routing if everything else fails or we don't allow mesh routing.

        // we'll just recycle the frame buffer and send it on its way out.

        if ((next_hop = nwk_rte_tree_calc_next_hop(hdr_in->dest_addr)) == INVALID_NWK_ADDR)

        {

            // tree routing failed for some reason. collect the stat and go on with life.

            pcb.failed_tree_rte++;

            buf_free(buf);

            DBG_PRINT("NWK: No such neighbor exists.\n\r");

            return;

        }

        // the buffer dptr is pointing to the nwk payload now. calc the length of the nwk

        // payload. then we can re-use the buffer, slap on the nwk hdr, and send it back down

        // the stack.

        //

        //lint -e{734} Info 734: Loss of precision (assignment) (31 bits to 8 bits)

        // its okay since we're subtracting a value from a constant

        buf->len = aMaxPHYPacketSize - (buf->dptr - buf->buf);

 

        // set the mac dest addr to the spec'd neighbor addr and the nwk src addr to the originator

        hdr_out.mac_hdr->dest_addr.short_addr   = next_hop;

        hdr_out.src_addr                        = hdr_in->src_addr;

    }

 

    // fill out the rest of the fields that will be needed to forward this frame

    hdr_out.nwk_frm_ctrl.frame_type             = hdr_in->nwk_frm_ctrl.frame_type;

    hdr_out.seq_num                             = hdr_in->seq_num;

    hdr_out.nwk_frm_ctrl.disc_route             = hdr_in->nwk_frm_ctrl.disc_route;

    hdr_out.radius                              = hdr_in->radius;

    hdr_out.dest_addr                           = hdr_in->dest_addr;

    hdr_out.handle                              = hdr_in->handle;

    hdr_out.mac_hdr->src_addr.mode              = SHORT_ADDR;

    hdr_out.mac_hdr->dest_addr.mode             = SHORT_ADDR;

    hdr_out.mac_hdr->src_addr.short_addr        = nib.short_addr;

nwk_tx(buf, &hdr_out, indirect);

}

else if (hdr_in->nwk_frm_ctrl.disc_route)這個分支即爲路由發現部分;函數nwk_pend_add_new(buf, hdr_in)的作用是分配一個buf將當前幀數據保存,函數nwk_rte_mesh_disc_start(hdr_in->dest_addr)爲開始路由查找;該函數描述如下:

/**************************************************************************/

/*!

    This function sets up a route discovery operation by initializing the discovery

    info. Once the data is initialized, we will call the rreq handler which is

    where the real route discovery starts.

*/

/**************************************************************************/

該函數的功能爲建立一個路由發現操作並且初始化發現信息;初始化完成之後,我們會調用路由請求(rreq)處理,此時,標誌着路由發現開始了,void nwk_rte_mesh_disc_start(U16 dest_addr)函數原型如下:

void nwk_rte_mesh_disc_start(U16 dest_addr)

{

    nwk_nib_t *nib = nwk_nib_get();

    nwk_hdr_t nwk_hdr;

    mac_hdr_t mac_hdr;

    nwk_cmd_t cmd;

 

    nwk_hdr.mac_hdr     = &mac_hdr;

 

    cmd.rreq.rreq_id    = nib->rreq_id++;

    cmd.rreq.dest_addr  = dest_addr;

    cmd.rreq.cmd_opts   = 0;

    cmd.rreq.path_cost  = 0;

 

    nwk_hdr.radius      = (U8)(nib->max_depth << 1);   // default radius = 2 * max depth

    nwk_hdr.src_addr    = mac_hdr.src_addr.short_addr = nib->short_addr;

 

    nwk_rte_mesh_rreq_handler(&nwk_hdr, &cmd);

}

nwk_rte_mesh_disc_start函數運行最後,會調用路由請求處理句柄nwk_rte_mesh_rreq_handler,該函數主要功能爲處理傳入的路由請求,確定該請求是否需要繼續向前傳輸或者是需要生成路由應答;同時函數會檢測路由表去尋找之前是否接收到過同樣的路由請求,如果接收過,將會對兩個路徑成本進行對比,確定是否當前的路徑更具有高效性,如果是,它將會更新發現鏈路入口。

         如果該路由請求是一個新的路由請求,那麼將會創建一個路由發現鏈表入口和一個路由表入口,然後會檢測當前節點是否爲目的節點,如果是,將會發送一個路由應答,否則,它將會通過廣播來轉播這個路由請求,該函數原型如下:

void nwk_rte_mesh_rreq_handler(const nwk_hdr_t *hdr_in, nwk_cmd_t *cmd_in)

{

    nwk_pcb_t *pcb = nwk_pcb_get();

    nwk_nib_t *nib = nwk_nib_get();

    mac_pib_t *pib = mac_pib_get();

    mem_ptr_t *disc_mem_ptr;

    mem_ptr_t *rte_mem_ptr;

    U8 path_cost;

    address_t dest_addr;

   

    dest_addr.mode          = SHORT_ADDR;

    dest_addr.short_addr    = cmd_in->rreq.dest_addr;

 

    // if we are originating the rreq, then set the path cost to zero. otherwise add the static path cost.

    // later on, we need to figure out a better way to generate path costs.

    path_cost = (hdr_in->src_addr != nib->short_addr) ? cmd_in->rreq.path_cost + NWK_STATIC_PATH_COST: cmd_in->rreq.path_cost;

 

    // check if route discovery table entry exists.

    if ((disc_mem_ptr = nwk_rte_disc_find(cmd_in->rreq.rreq_id, hdr_in->src_addr)) != NULL)

    {

        // if the path cost is less than the fwd cost, then update the entry

        if (path_cost < DISC_ENTRY(disc_mem_ptr)->fwd_cost)

        {

            // If the path cost is less than the fwd cost, then replace the disc table disc_entry path

            // with this path.

            DISC_ENTRY(disc_mem_ptr)->sender_addr  = hdr_in->mac_hdr->src_addr.short_addr;

            DISC_ENTRY(disc_mem_ptr)->fwd_cost     = path_cost;

        }

        else

        {

            // since we already have a discovery entry for this rreq and there's no benefit in cost, drop the rreq

            pcb->drop_rreq_frm++;

            return;

        }

    }

    else

    {

        // add the new discovery entry to the discovery table

        //nwk_rte_disc_add_new(cmd_in->rreq.rreq_id, hdr_in->src_addr, hdr_in->mac_hdr->src_addr.short_addr, hdr_in->dest_addr, path_cost);

        //Changed by LiuTianmin

        nwk_rte_disc_add_new(cmd_in->rreq.rreq_id, hdr_in->src_addr, hdr_in->mac_hdr->src_addr.short_addr, cmd_in->rreq.dest_addr, path_cost);

    }

 

    // get the route entry for this rreq if it exists. otherwise, create a new entry.

    if ((rte_mem_ptr = nwk_rte_tbl_find(cmd_in->rreq.dest_addr)) != NULL)

    {

        // if the route entry isn't active or active but requires validation, then change it to discovery underway.

        if ((RTE_ENTRY(rte_mem_ptr)->status != NWK_ACTIVE) && (RTE_ENTRY(rte_mem_ptr)->status != NWK_VALIDATION_UNDERWAY))

        {

            RTE_ENTRY(rte_mem_ptr)->status = NWK_DISCOVERY_UNDERWAY;

        }

    }

    else

    {

        nwk_rte_tbl_add_new(cmd_in->rreq.dest_addr, NWK_DISCOVERY_UNDERWAY);

    }

 

    // now check to see if the route request destination was meant for us. If so, then prepare a route reply.

    if ((cmd_in->rreq.dest_addr == nib->short_addr) || (nwk_neighbor_tbl_get_child(&dest_addr) != NULL))

    {   /*Here should select a best route to reply LiuTianmin*/

       

        /*Here should select a best route to reply LiuTianmin*/

        // send out the route reply  Delete by LiuTianmin

        //nwk_rte_mesh_send_rrep(cmd_in->rreq.rreq_id, hdr_in->src_addr, cmd_in->rreq.dest_addr,

        //                       path_cost, hdr_in->mac_hdr->src_addr.short_addr);

       

        nwk_rte_mesh_req_wait_start();

    }

    else

   {

       // fwd the rreq

       nwk_rte_mesh_send_rreq(cmd_in, hdr_in->src_addr, path_cost, hdr_in->radius);

   }

}

 

最後一個else分支即爲該路由請求是一個新的路由請求,並且不在當前節點不是路由請求的目的地址,此時會調用nwk_rte_mesh_send_rreq函數,該函數的功能爲生成併發送一個路由請求的控制幀,該控制信息由規定的指令數據結構體生成,頭部將會由剩餘的參數生成,同時會寫入一個路由請求加入路由請求鏈路裏以方便跟蹤請求信息,該函數原型如下:

static void nwk_rte_mesh_send_rreq(nwk_cmd_t *cmd, U16 src_addr, U8 path_cost, U8 radius)

{

    nwk_nib_t *nib = nwk_nib_get();

    nwk_hdr_t hdr;

    buffer_t *buf;

    mem_ptr_t *mem_ptr;

 

    // prepare route request

    cmd->cmd_frm_id     = NWK_CMD_RTE_REQ;

    cmd->rreq.cmd_opts  = 0;

    cmd->rreq.path_cost = path_cost;

 

    // prepare route request nwk frame header

    hdr.nwk_frm_ctrl.frame_type = NWK_CMD_FRM;

    hdr.nwk_frm_ctrl.disc_route = false;

    hdr.src_addr                = src_addr;

    hdr.dest_addr               = NWK_BROADCAST_ROUTERS_COORD;

    hdr.radius                  = radius;

    hdr.seq_num                 = nib->seq_num;

 

    // copy the hdr and cmd structs. we'll use them later for retransmission.

    /*Added by LiuTianmin*/

    //I think the router request retransmission should do only by the originator sender

    if(src_addr == nib->short_addr)

    {

    /*Added by LiuTianmin*/

        if ((mem_ptr = nwk_rte_mesh_rreq_alloc()) != NULL)

        {

            RREQ_ENTRY(mem_ptr)->originator    = src_addr;

            RREQ_ENTRY(mem_ptr)->radius        = radius;

            RREQ_ENTRY(mem_ptr)->retries       = 0;

            RREQ_ENTRY(mem_ptr)->expiry        = ROUTER_REQ_TIME_OUT;  //400ms

            memcpy(&RREQ_ENTRY(mem_ptr)->cmd, cmd, sizeof(nwk_cmd_t));

        }

    /*Added by LiuTianmin*/

    }

    /*Added by LiuTianmin*/

 

    // gen the nwk frame and send it out

    BUF_ALLOC(buf, TX);

    nwk_gen_cmd(buf, cmd);

    debug_dump_nwk_cmd(cmd);

    nwk_fwd(buf, &hdr);

}

nwk_rte_mesh_send_rreq函數執行最後又會跳轉到nwk_fwd函數,此時又回到了該文檔的開頭,形成一個循環體,意思是在路由發現的過程中,如果沒有找到目的地址,那麼就會不斷查找,並且不斷更新維護路由鏈表,直到找到爲止。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章