路由協議之: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協議規範定義,如下圖:


下面分析代碼

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;

}

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