路由协议之:WSN网络的RPL路由协议 for 6LOWPAN

目前专门为LoWPAN设计的路由协议(RPL协议)尚在制定完善中,很有可很成为6LoWPAN中使用的标准路由协议

一  RPL处理数据包:

代码流程:

Ieee802.15.4mac

\/

\/

6lowpan子系统,

\/

\/

Ipv6-->ipv6_rcv():

---->ip6_input()--->ip6_input_finish(){

….

nexthdr = skb_network_header(skb)[nhoff];//取出ipv6包头,判断出要使用那个上层协议(tcp,udp,icmp6)

 

raw= raw6_local_deliver(skb, nexthdr);

if((ipprot = rcu_dereference(inet6_protos[nexthdr])) != NULL) {

 

ret = ipprot->handler(skb);---传递给上一层协议(tcp,udp,icmp6)处理

\/

\/

 2 下面是icmp6模块:

首先注册协议到inet6_protos[]

int __initicmpv6_init(void)

{

interr;

 

err= register_pernet_subsys(&icmpv6_sk_ops);

if(err < 0)

returnerr;

 

err= -EAGAIN;

if(inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6)< 0)

gotofail;

其次,handler定义:

static const structinet6_protocol icmpv6_protocol = {

.handler        =        icmpv6_rcv,

.err_handler        =        icmpv6_err,

.flags                =        INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,

};

补充认识icmp6

功能ICMPv6向源节点报告关于目的地址传输IPv6包的错误和信息,具有差错报告、网络诊断、邻节点发现和多播实现等功能。在IPv6中,ICMPv6实现IPv4ICMPARPIGMP的功能NDNI协议也是基于ICMPv6

ND协议定义了5ICMPV6报文类型,包括RSRANSNARedirect报文:

icmpv6_rcv(){

….

caseNDISC_ROUTER_SOLICITATION://RS

case NDISC_ROUTER_ADVERTISEMENT:

caseNDISC_NEIGHBOUR_SOLICITATION:

caseNDISC_NEIGHBOUR_ADVERTISEMENT:

case NDISC_REDIRECT:

ndisc_rcv(skb);

…..

3  RPL是通过icmpv6来接受数据包:参考RPL协议规范定义,如下图:

路由协议之:WSN网络的RPL路由协议 for 6LOWPAN_第1张图片

下面分析代码

icmpv6_rcv(){

完成icmp的处理之后。

…..

#ifdefCONFIG_IPV6_RPL//linux_rpl

caseICMPV6_RPL:

rpl_rcv(skb);

break;

#endif /*CONFIG_IPV6_RPL */

 

rpl_rcv{}------rpl_rx_worker()----_rpl_rcv(rw->dev,skb){

…..

根据RPL组网过程基本原理,其基本消息处理如下:

//处理如下消息:DISDIODAO

switch(msg->icmp6_code){

caseICMPV6_RPL_DIS:

rpl_recv_dis(dev,skb);

break;

caseICMPV6_RPL_DIO:

rpl_recv_dio(dev,skb);

break;

caseICMPV6_RPL_DAO:

rpl_recv_dao(dev,skb);

break;

caseICMPV6_RPL_DAO_ACK:

//rpl_recv_dao_ack();

break;

caseICMPV6_RPL_CC:

//rpl_recv_cc();

break;

caseICMPV6_RPL_SEC_DIS:

caseICMPV6_RPL_SEC_DIO:

caseICMPV6_RPL_SEC_DAO:

caseICMPV6_RPL_SEC_DAO_ACK:

……

…...

}

逐个函数分析:

1)rpl_recv_dis(dev,skb);

{

//step1.找到节点信息,就是找路由信息。

icmpv6_rpl_find_option()

//step2:新节点,则加入

rpl_dag_inconsistent()---trickle_hear_inconsistent()---_trickle_start()---trickle_threadfn()

  ------trickle->trickle_fn(trickle->trickle_fn_arg);----rpl_dag_dio_timer_handler()

{

发送出DIOrpl_send_dio(dag,NULL,NULL,true,false);----dag处理---icmp处理---dst_output()--

ipV6rt->dst.output  =ip6_output;

---->ip6_finish_output()---->ip6_finish_output2()----->

ND系统---mac---》物理层

}

dio timer什么时候建立?

Dio timer基于The Trickle Algorithm算法的定时器,参考rfc6206.pdf

当检测到netdevnetevent的时候

static structnotifier_block rpl_netdev_notifier = {

.notifier_call= rpl_netdev_event,

};

 

static structnotifier_block rpl_netevent_notifier = {

.notifier_call= rpl_netevent_event,

};

…/…./….--->rpl_dag_start_root()----…/….--->rpl_dag_dio_timer_reset(dag);

 

2rpl_recv_dio(dev,skb);

这里只关注更新节点更新“自身邻居表”,并选择合适的节点发送数据包

rpl_dag_update_upward_routes()---

-1rpl_node_set_default_route()

-2rpl_node_unset_default_route()

   首先调用rt6_get_dflt_router()获取ipv6的路由缓存表信息

   其次dst_neigh_lookup()更新自身的(ipv6)邻居表---->….----->ip6_neigh_lookup();

 

3rpl_recv_dao(dev,skb);

父节点更新了自身的路由表后,再向”父节点的父节点““发DAO”,最后到达sink点后双向链路最终形成。

//for each target intargets

rpl_recv_dao(dev,skb)

{

…..

   rpl_dag_add_target()

{

..

..

rpl_target_check_routes()---->rpl_add_route_nexthop()

{

interr = -EINVAL;

intpref = 0;

structfib6_config cfg;

//FIXMEcheck expires!!

 

memset(&cfg,0, sizeof(cfg));

cfg.fc_table        = RT6_TABLE_DFLT;

cfg.fc_metric        =IP6_RT_PRIO_USER;

cfg.fc_ifindex        =dev->ifindex;

cfg.fc_flags        =RTF_GATEWAY | RTF_PREF(pref);

cfg.fc_nlinfo.portid= 0;

cfg.fc_nlinfo.nlh= NULL;

cfg.fc_nlinfo.nl_net= dev_net(dev);

cfg.fc_dst= *prefix;

cfg.fc_dst_len= prefix_len;

cfg.fc_gateway= *next_hop;

 

err =ip6_route_add(&cfg);//增加路由表项

 

returnerr;

}

你可能感兴趣的:(路由,6lowpan,RPL协议)