batman-adv路由算法分析

来源:互联网 发布:西部域名怎么解析 编辑:程序博客网 时间:2024/05/01 06:44

五、路由算法分析

通过OGM包更新对应源节点的数据

在bat_iv_ogm.c中line 970,batadv_iv_ogm_orig_update函数执行此工作。

(1)遍历orig_node->neigh_list链表,匹配地址,接收接口。

if (batadv_compare_eth(neigh_addr, ethhdr->h_source) &&        tmp_neigh_node->if_incoming == if_incoming &&        atomic_inc_not_zero(&tmp_neigh_node->refcount)) {            ……}

(2)得到发送接口之后,更新TQ缓冲区,更新TQ平均值。

spin_lock_bh(&tmp_neigh_node->ifinfo_lock);batadv_ring_buffer_set(neigh_ifinfo->bat_iv.tq_recv,               &neigh_ifinfo->bat_iv.tq_index, 0);tq_avg = batadv_ring_buffer_avg(neigh_ifinfo->bat_iv.tq_recv);neigh_ifinfo->bat_iv.tq_avg = tq_avg;spin_unlock_bh(&tmp_neigh_node->ifinfo_lock);

(3)如果计算出的下一跳不是一跳邻居节点,则利用batadv_iv_ogm_neigh_new函数重新获取下一跳;

(4)如果该邻居已经是下一跳,则直接退出;

(5)如果该邻居的TQ值并不比原来好,则直接退出;

(6)如果TQ值相同但是链路对称性不比原来好也不考虑;

TQ值的计算

在bat_iv_ogm.c中line 1131,batadv_iv_ogm_calc_tq函数执行此工作。

(1)首先匹配到相应的邻居节点;

(2)更新其last_seen;

(3)找到对应的数据包计数。

/* find packet count of corresponding one hop neighbor */spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);if_num = if_incoming->if_num;orig_eq_count = orig_neigh_node->bat_iv.bcast_own_sum[if_num];neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing);if (neigh_ifinfo) {    neigh_rq_count = neigh_ifinfo->bat_iv.real_packet_count;    batadv_neigh_ifinfo_free_ref(neigh_ifinfo);} else {    neigh_rq_count = 0;}spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);

其中,bcast_own_sum计算bcast_own的数量,存储在orig_eq_count中,bcast-own为计数的bit集,统计自己广播出去,然后由该邻居节点广播回来的OGM包,统计窗口为64。
将neigh_rq_count赋值统计到的真实OGM数量。

(4)将orig_eq_count和neigh_rq_count其中的较小者赋值给total_count。

/* pay attention to not get a value bigger than 100 % */if (orig_eq_count > neigh_rq_count)    total_count = neigh_rq_count;else    total_count = orig_eq_count;

(5)如果接受OGM包过少(小于1),将tq_own置0;

(6)否则,计算tq_own;

tq_own = (BATADV_TQ_MAX_VALUE * total_count) /  neigh_rq_count;

(7)加入非对称链路惩罚1 - ((1-x) ** 3)和接口惩罚(半双工网卡会受影响,因为不能同时收发);

(8)考虑链路的最低传输质量需求(如果有的话);

透过广播与再广播OGMs的方式交换路由资讯,以传输品质(Transmission Quality,简称TQ)做为路径选择的依据,TQ值的计算必须先取得接收品质(Receive Quality,简称RQ)与回声品质(Echo Quality,简称EQ)这二个参考数值。

  1. 各网路节点以广播的方式定期发送路由讯息封包即OGMs封包,其内容包含发送端位址,转发节点位址,存活时间(Time To Live,简称TTL)值和序列号(Sequence Number),附近的邻近节点计算已收到的OGMs封包数量作为RQ值。

  2. 检查每个路由的资讯,选择最好的单跳节点(Best Hop Neighbor)。

  3. 将最好的单跳节点传送过来的OGMs封包进行再广播,原始的OGMs封包发送节点透过接收到的再广播OGMs数量可以得到EQ。

  4. 如果EQ值大于RQ,则TQ = max(TQ);如果RQ值大于EQ,则TQ = max(TQ)× EQ ÷ RQ。

OGM包处理

在bat_iv_OGM.c/line 1570行,函数batadv_iv_ogm_process负责处理一个接收到的OGM数据包。
邻居节点在接收到包时,首先会解析,然后会做相应处理。这里有四种情况:如果包来自本节点的其他次接口,则丢弃。如果该的发起者是本节点的主接口,则次接口有义务帮其转发。如果包的起始地址是广播地址,则丢掉。如果包经过广播又转发回来,先检查该包是否是发送出去的最新的包,如果是则对—的—和一进行滑动窗口式的更新,之后抛弃。一和成员是计算返回链路通信质量的成员,它们是计算的基础。如果排除以上三种可能则进入常规处理阶段,首先确定该包是否为新包,如果是旧包则抛弃;如果是新包则纳入邻居节点的局部窗口,同时其他的邻居节点也需要对窗口中的数值更新。之后需要确定该链路是否为双向导通,只有双向通信都顺畅的链路才能纳入网络。链路的双向导通检查非常必要,非双向导通的网络链路会影响数据的传输效率。双向导通的标准是通过计算衡量,当大于协议制定的下限值时,则确定该链路是双向导通。

if (is_my_addr) {    batadv_dbg(BATADV_DBG_BATMAN, bat_priv,    "Drop packet: received my own broadcast (sender: %pM)\n",    ethhdr->h_source);    return;}if (is_my_orig) {……}if (is_my_oldorig) {    batadv_dbg(BATADV_DBG_BATMAN, bat_priv,    "Drop packet: ignoring all rebroadcast echos (sender: %pM)\n",    ethhdr->h_source);    return;}

接下来,在每个发送接口(同属一个soft接口)上广播该数据包。

batadv_iv_ogm_process_per_outif(skb, ogm_offset, orig_node,if_incoming, BATADV_IF_DEFAULT);……list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {    if (hard_iface->if_status != BATADV_IF_ACTIVE)        continue;    if (hard_iface->soft_iface != bat_priv->soft_iface)        continue;    batadv_iv_ogm_process_per_outif(skb, ogm_offset, orig_node,                    if_incoming, hard_iface);}

关于BATADV_IF_DEFAULT的解释:

/* default interface for multi interface operation. The default interface is* used for communication which originated locally (i.e. is not forwarded)* or where special forwarding is not desired/necessary.*/#define BATADV_IF_DEFAULT   ((struct batadv_hard_iface *)NULL)

所以,在以下两种情况时会用到缺省接口:
* 本地发起的数据请求;
* 没有指定特殊转发的情况;

/* line 1449 */if (if_outgoing == BATADV_IF_DEFAULT)batadv_tvlv_ogm_receive(bat_priv, ogm_packet, orig_node);

其中的TVLV表示type-version-length-value,详见https://www.open-mesh.org/projects/batman-adv/wiki/TVLV。

接收单播数据包的处理

接收到单播数据包时,由batadv_recv_unicast_packet(routing.c/line 830)处理。
如果接收到的数据包是发送到自己的,则首先检查该数据包的类型,分为以下几种:
* BATADV_P_DATA: user payload
* BATADV_P_DAT_DHT_GET: DHT request message
* BATADV_P_DAT_DHT_PUT: DHT store message
* BATADV_P_DAT_CACHE_REPLY: ARP reply generated by DAT

如果是第一种,则分析它的源节点地址,返回NET_RX_SUCCESS。

如果目的地不是自己,则进行下面的路由与转发。

路由与转发

  • 普通单播数据包

在route.c/line571, batadv_route_unicast_packet负责单播路由。
首先对数据包进行检查(TTL),正常的话,利用batadv_orig_hash_find函数找到源节点,得到路由信息。然后进行后续操作(TTL减一等),然后根据packet_type转发。(详见packet.h/line 38)

  • 对于bonding技术

在route.c/line441 , batadv_find_router函数负责为一个源节点和一个给定的接口,找到合适的路由节点。
* 首先运行batadv_orig_router_get函数找到合适的下一跳节点,然后考虑bonding和alter机制。在mesh接口信息结构体batadv_priv中,包含了bonding, fragmentation, bridge_loop_avoidance, distributed_arp_table, multicast_mode, gw_mode(gateway), network_coding等等标识符。

  • 在bonding模式下,recv_if传入的值为BATADV_IF_DEFAULT。首先,遍历所有可能的转发节点,找到一个不同于上一个bonding接口的candidate (next_candidate)。如果没有找到,则继续使用之前的接口。如果第一个bonding接口都无法找到,则返回之前计算出来的下一跳。

  • 在存储源节点的batadv_orig_node结构体中,有一个成员是last_bonding_candidate( pointer to last ifinfo of last used router)。首先遍历源节点的所有接口,为每个接口获取到达它的下一跳接口,存储在cand_router中。由于默认alternative是开启的,如果cand_router并不比原来的好,则视作无效。否则,如果cand_router与last_bonding_candidate相同,则两次不走同一个接口,也视作无效。满足上述两个条件之后,将算出来的第一个cand_router保存在first_ candidate中。如果遍历指针已经处于last_bonding_candidate之后(已遍历),则直接选用list中位于last_bonding_candidate后一个的接口作为next_candidate,程序退出。否则,返回first_ candidate。(估计链表根据某种指标从坏到好排序)

广播数据包处理

接收到广播数据包时,由batadv_recv_bcast_packet(routing.c/line 1012)处理。

1、对数据包进行检查,大小不合格、携带有源节点地址、自己转发或发送的广播报文、TTL<2、找不到发送源节点的数据包都会不作处理。

2、检查该数据包是否重复、是否是旧的或者发送它的源节点刚刚启动。

3、将其记录下来,必要的话更新滑动窗口位置。

4、检查该数据包是否被其他节点转发过。

5、通过batadv_add_bcast_packet_to_list,在当前所属soft interface广播出去。

6、对广播报文进行处理,例如回复、更新必要信息等。

batadv_add_bcast_packet_to_list函数会将一个广播报文广播几次来提高接收可靠性。

0 0
原创粉丝点击