FreakZ 路由发现机制

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函数,此时又回到了该文档的开头,形成一个循环体,意思是在路由发现的过程中,如果没有找到目的地址,那么就会不断查找,并且不断更新维护路由链表,直到找到为止。

 

 

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • FreakZ路由应答机制 路由应答机制是建立在路由发现和路由请求完成之后进行的,换句话说就是在通信链路建立完成之后...
    zplodge阅读 299评论 0 0
  • ping error: Destination off-link but no route作者 codercjg ...
    codercjg阅读 1,030评论 0 1
  • 今天轮到我们班值日了,早上竟然忘了,好在有看班级群消息的习惯。赶紧把熟睡中的儿子叫起来,儿子一听今天是...
    恺恺悦悦阅读 161评论 0 0
  • 查理芒格是我最佩服的人之一,他是个诚实的人,他是个践行者。巴菲特是这么评价他的:查理是我的启蒙老师。 这个人给了我...
    Classmate阅读 279评论 1 3
  • 有一种等待叫晚点未定 有一种约定叫下次有空 有一种熟悉叫近似陌生 有一种相聚叫草草收场 有一种怀念叫儿时懵懂 有一...
    月圆天心阅读 292评论 0 1