FreakZ学习笔记:路由应答机制

FreakZ学习笔记:路由应答机制

路由应答机制是建立在路由发现和路由请求完成之后进行的,换句话说就是在通信链路建立完成之后,帧信息被传输到目的节点时,由目的节点进行的应答机制;路由应答机制在NWK.c下的mac_data_ind函数被调用,该函数的功能在另一篇文章《FreakZ学习笔记:接收过程详解》中有解释,这里不再赘述;相应代码如下:

switch (cmd.cmd_frm_id)

{

case NWK_CMD_RTE_REQ:

if(nib.dev_type != NWK_END_DEVICE)//Added by LiuTianmin

{

nwk_rte_mesh_rreq_handler(&hdr, &cmd);

}

break;

case NWK_CMD_RTE_REP:

if(nib.dev_type != NWK_END_DEVICE)//Added by LiuTianmin

{

nwk_rte_mesh_rrep_handler(&hdr, &cmd);

}

break;

case NWK_CMD_LEAVE:

nwk_leave_handler(&hdr, &cmd);

break;

default:

break;

}

这里的switch语句会分别对路由请求和路由应答的ID进行判断,如果节点类型为终端节点的话,即执行相应的路由请求函数nwk_rte_mesh_rreq_handler或路由应答函数nwk_rte_mesh_rrep_handler。

路由应答函数nwk_rte_mesh_rrep_handler的主要功能是处理传入的路由线路并确定是否需要路由应答;首先,需要确保本次路由应答有一个对应的发现表和路由表,如果没有,那么丢弃回复路线,同样,如果路径的成本比目前发现路由表里保存的链路成本高的话,同样放弃回复路线直到有一个更高效率的链路建立。如果这条路由应答是给当前链路的,那么结束路由发现过程并发送路由应答,否则,在前进的路由回复中更新记录路由请求的发现表。代码原型如下:

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

{

nwk_pcb_t *pcb = nwk_pcb_get();

nwk_nib_t *nib = nwk_nib_get();

mem_ptr_t *disc_mem_ptr;

mem_ptr_t *rte_mem_ptr;

U8 path_cost;

disc_mem_ptr  = nwk_rte_disc_find(cmd_in->rrep.rreq_id, cmd_in->rrep.originator);

rte_mem_ptr   = nwk_rte_tbl_find(cmd_in->rrep.responder);

path_cost   = cmd_in->rrep.path_cost + NWK_STATIC_PATH_COST;

// if the rte entry or discovery entry doesn‘t exist or the path cost is not less than the current resid cost, then drop

// the rrep.

if ((!rte_mem_ptr) || (!disc_mem_ptr) || (path_cost >= DISC_ENTRY(disc_mem_ptr)->resid_cost))

{

if (!rte_mem_ptr || !disc_mem_ptr)

{///????????这里似乎有问题

nwk_rte_tbl_free(rte_mem_ptr);

nwk_rte_disc_free(disc_mem_ptr);

}

pcb->drop_rrep_frm++;

return;

}

// we‘ve met all the criteria to keep the rrep. that means we should update the rrep and disc entry.

// any time we update the next hop in the rte entry, we need to reset the discovery entry‘s expiry

DISC_ENTRY(disc_mem_ptr)->resid_cost  = path_cost;

DISC_ENTRY(disc_mem_ptr)->expiry      = NWK_RTE_DISC_TIME;

RTE_ENTRY(rte_mem_ptr)->next_hop      = hdr_in->mac_hdr->src_addr.short_addr;

// update the entry to validation underway. once we send an actual frame through it, then we can change

// it to NWK_VALIDATION_UNDERWAY.

RTE_ENTRY(rte_mem_ptr)->status = (RTE_ENTRY(rte_mem_ptr)->status == NWK_DISCOVERY_UNDERWAY) ?

NWK_VALIDATION_UNDERWAY :

RTE_ENTRY(rte_mem_ptr)->status;

// check if the rrep is meant for us.

if (cmd_in->rrep.originator == nib->short_addr)

{

/*We should remove the roter request from req_list added by LiuTianmin*/

mem_ptr_t *mem_ptr;

mem_ptr = nwk_rte_mesh_rreq_find(nib->short_addr,cmd_in->rrep.responder);

nwk_rte_mesh_rreq_free(mem_ptr);

/*We should remove the roter request from req_list added by LiuTianmin*/

// send out pending xfers

nwk_pend_send_pending();

DBG_PRINT("\nNWK_RTE_MESH: Route established.\n");

return;

}

// forward the route reply

nwk_rte_mesh_send_rrep(cmd_in->rrep.rreq_id, cmd_in->rrep.originator, cmd_in->rrep.responder,

path_cost, DISC_ENTRY(disc_mem_ptr)->sender_addr);

}

nwk_rte_mesh_send_rrep为发送路由应答函数,原型如下:

static void nwk_rte_mesh_send_rrep(U8 rreq_id, U16 originator, U16 responder, U8 path_cost, U16 sender_addr)

{

nwk_nib_t *nib = nwk_nib_get();

nwk_hdr_t hdr;

nwk_cmd_t cmd;

buffer_t *buf;

cmd.cmd_frm_id              = NWK_CMD_RTE_REP;

cmd.rrep.cmd_opts           = 0x00;

cmd.rrep.rreq_id            = rreq_id;

cmd.rrep.originator         = originator;

cmd.rrep.responder          = responder;

cmd.rrep.path_cost          = path_cost;

hdr.nwk_frm_ctrl.frame_type = NWK_CMD_FRM;

hdr.nwk_frm_ctrl.disc_route = false;

hdr.src_addr                = nib->short_addr;

hdr.dest_addr               = sender_addr;

hdr.radius                  = (U8)(nib->max_depth << 1);

hdr.seq_num                 = nib->seq_num;

BUF_ALLOC(buf, TX);

nwk_gen_cmd(buf, &cmd);

debug_dump_nwk_cmd(&cmd);

//nwk_fwd(buf, &hdr);   //Delete by LiuTianmin

/*I think here should respone direct to the sender*/

mac_hdr_t mac_hdr_out;

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

hdr.mac_hdr         = &mac_hdr_out;

hdr.mac_hdr->src_addr.mode          = SHORT_ADDR;

hdr.mac_hdr->dest_addr.mode         = SHORT_ADDR;

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

hdr.mac_hdr->dest_addr.short_addr   = hdr.dest_addr;

nwk_tx(buf, &hdr, false);

}

当路由应答产生之后,会通过nwk_tx函数将该路由应答由NWK层传递到MAC层,通过MAC层到达Radio层,然后将应答信息发送。

时间: 2024-10-06 21:06:29

FreakZ学习笔记:路由应答机制的相关文章

linux网络编程学习笔记之五 -----并发机制与线程?

进程线程分配方式 简述下常见的进程和线程分配方式:(好吧,我仅仅是举几个样例作为笔记...并发的水太深了,不敢妄谈...) 1.进程线程预分配 简言之,当I/O开销大于计算开销且并发量较大时,为了节省每次都要创建和销毁进程和线程的开销.能够在请求到达前预先进行分配. 2.进程线程延迟分配 预分配节省了处理时的负担,但操作系统管理这些进程线程也会带来一定的开销.由此,有个折中的方法是,当某个处理须要花费较长时间的时候,我们创建一个并发的进程或线程来处理该请求.实现也非常easy,在主线程中定时,定

linux网络编程学习笔记之五 -----并发机制与线程池

进程线程分配方式 简述下常见的进程和线程分配方式:(好吧,我只是举几个例子作为笔记...并发的水太深了,不敢妄谈...) 1.进程线程预分配 简言之,当I/O开销大于计算开销且并发量较大时,为了节省每次都要创建和销毁进程和线程的开销.可以在请求到达前预先进行分配. 2.进程线程延迟分配 预分配节省了处理时的负担,但操作系统管理这些进程线程也会带来一定的开销.由此,有个折中的方法是,当某个处理需要花费较长时间的时候,我们创建一个并发的进程或线程来处理该请求.实现也很简单,在主线程中定时,定时到期,

FreakZ学习笔记:路由发现机制

路由发现机制 路由发现机制只有在发送通信包的过程中会被调用,而接收过程因为发送时候已经进行了通信链路的扫描和连接,所以不会再进行路由发现机制. 路由的所有处理机制都是在NWK层进行的,当然,路由发现机制也一样.当协议栈进行数据发送时,会依次按照APP->APS->NWK->MAC->PHY->Radio的层次关系来进行,APS层执行完成之后,会跳转到NWK层的nwk_data_req函数,该函数为NWK数据请求服务,接收APS层的数据并且加上NWK层的包头,然后将数据打包.n

FreakZ学习笔记:FreakZ通信网络接收过程详解

FreakZ接收过程详解 FreakZ的接收过程与发送过程刚好相反,层次关系依次为Radio->PHY->MAC->NWK->APS,下面就具体流程做阐述说明: 当Radio层接收到广播信号时,首先会触发中断函数cc2538_rf_rx_tx_isr,该中断函数会跳转到cc2538_rf_process这个进程,process_poll是触发该进程函数,优先级高于process_event: void cc2538_rf_rx_tx_isr(void) { ENERGEST_ON(

C++学习笔记27:异常处理机制

一.异常处理机制基础 异常的定义 程序中可以检测的运行不正常的情况 异常处理的基本流程 某段程序代码在执行操作时发生特殊情况,引发一个特定的异常 另一段程序代码捕获该异常并处理它 二.异常的引发 throw 三.异常的捕获 try { ... } catch(...) 四.异常类与异常对象 五.异常处理策略 异常类可以派生和继承,形成类库架构 可捕获的异常对象的型式 普通型式(包括类):异常对象需要拷贝 对某型式对象的引用:没有额外的拷贝动作 指向某型式对象的指针:要求对象动态构造或者在catc

Linux程序设计学习笔记——异步信号处理机制

转载请注明出处: http://blog.csdn.net/suool/article/details/38453333 Linux常见信号与处理 基本概念 Linux的信号是一种进程间异步的通信机制,在实现上一种软中断.信号能够导致一个正在执行的进程被异步打断,转而去处理一个突发事件.异步事件不可预知,仅仅能通过一些特定方式预防.或者说,当该异步事件发生时依据原来的设定完毕对应的操作. 信号本质 信号是在软件层次上对中断机制的一种模拟.在原理上,一个进程收到一个信号与处理器收到一个中断请求能够

深入理解Java虚拟机- 学习笔记 - 虚拟机类加载机制

虚拟机把描述类的数据从Class文件加载道内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制.在Java里,类型的加载.连接和初始化过程都是在程序运行期间完成的,这种策略虽然会令类加载时稍微增加一些性能开销,但是会为Java应用程序提供高度的灵活性. 一.类加载的时机 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading).验证(Verification).准备(Preparation).解析(Re

java学习笔记09--反射机制

什么是反射: 反射是java语言的一个特性,它允许程序在运行时来进行自我检查并且对内部的成员进行操作.例如它允许一个java的类获取他所有的成员变量和方法并且显示出来. java的反射机制的实现要借助4个类:Class,Constructor,Field,Method 其中Class代表的是类对象,Constructor  类的构造器对象,Field  类的属性对象,Method 类的方法对象.通过这四个对象我们可以粗略的看到一个类的各个组成部分. 在正常情况下,必须知道一个类的完整路径之后才可

Android学习笔记之消息机制

Android的消息机制主要是指Handler的运行机制以及Handler所附带的MessageQueue和Looper的工作过程.   1.为什么要使用Handler? Android规定访问UI只能在主线程中进行,如果在子线程中访问UI,则会抛出异常.同时Android建议不能在主线程中进行耗时的操作,不然会导致程序无法响应即ANR.因此耗时的工作只能交给子线程去做,而子线程却不能直接访问UI,为了解决这个矛盾,Android提供了Handler.Handler的主要作用是将某个任务切换到某