aodv之一

<span style="font-size:14px;">kaodv-mod.c,该文件是运行aodv的内核模块,开始的文件,通过从这里入手,了解aodv的整个工作方式和实现机制
kaodv-mod.c文件的两个先头函数就是module_init(kaodv_init)和module_exit(kaodv_exit),这两个函数就是执行insmod kaodv.ko和rmmod kaodv时执行的函数
函数kaodv_init:首先初始化expl(路由条目,用于存储路由),该函数kaodv_expl_init做了这些操作。主要有create_proc_read_entry(),
struct proc_dir_entry *create_proc_read_entry (const char *name, mode_t mode, struct proc_dir_entry *base, read_proc_t *read_proc, void *data);</span>


说明

name : 要创建的文件名;

mode : 文件掩码,为 0 则按照系统默认的掩码创建文件。

base : 指定该文件所在的目录,如果为 NULL,则文件被创建在 /proc 根目录下。

read_proc : 实现该文件的 read_proc 函数。也就是说,当我们读取 "name" 这个文件时(如 cat /proc/myproc_name) ,读取请求会通过这个函数发送到驱动模块,然后在函数里处理的数据会写到 myproc_name 文件中。

data : 内核忽略此参数,但会把它当作参数传递给 read_proc 这个自定义函数。

init_net.proc_net应该是指目录/proc/net/

aodv中利用这个函数在/proc/net/kaodv_expl的创建了路由条目信息,只要使用cat /proc/net/kaodv_expl就是以看到相关的路由信息

expl_len记录了路由条目的数量,一个全局变量

如果路由条目是有期限的,那么这个函数也初始化路由条目定时器,init_timer(&expl_timer)

接着执行kaodv_queue_init()初始化缓存队列:

首先是对缓存队列长度初始化为0,然后在/proc/net/*下创建proc文件kaodv_queue,当我们执行cat /proc/net/kaodv_queue时,会输出队列长度和队列的最大长度信息,以上的信息都没有出错的情况下

进入netlink初始化,实现内核与用户空间通信的关键

kaodv_netlink_init():

netlink_register_notifier(&kaodv_nl_notifier);登记kaodv的netlink套接口的通知

static struct notifier_block kaodv_nl_notifier = {
    .notifier_call = kaodv_netlink_rcv_nl_event,
};
以上是一个事件通知链, 通知链只能用在各个子系统之间,而不能在内核和用户空间进行事件的通知。组成内核的核心系统代码均位于kernel目录下,通知链表位于kernel/notifier.c中,对应的头文件为include/linux/notifier.h。关于事件通知链,可以参考http://www.linuxidc.com/Linux/2013-07/86999.htm

这里是netlink的通知链注册(目前还不懂怎么回事,应该是notifier.c中的事件通知链类似),netlink的通知链貌似是在notifier.c中的事件通知链的基础上进一步封装,构成自己特色的。参考http://blog.chinaunix.net/uid-23069658-id-4360706.html

对于netlink通知链,既可以用于内核与用户空间的通信,还能用于内核不同子系统之间的通信,关于通知链的使用可以仔细阅读http://blog.chinaunix.net/uid-23069658-id-4360706.html这里的一系列文章

kaodv_netlink_rcv_nl_event处理netlink的通知链事件,如果事件是NETLINK_URELEASE,协议是NETLINK_AODV,进程号不是内核的,该函数会把路由表清除掉,缓存队列清除掉.

netlink_kernel_create(&init_net, NETLINK_AODV, AODVGRP_MAX, kaodv_netlink_rcv_skb, NULL, THIS_MODULE);创建与用户空间通信的套接字struct sock

struct sock *netlink_kernel_create(struct net *net,  
  
                  int unit,unsigned int groups,  
  
                  void (*input)(struct sk_buff *skb),  
  
                  struct mutex *cb_mutex,  
  
                  struct module *module);  
其中net参数是网络设备命名空间指针,input函数是netlink socket在接受到消息时调用的回调函数指针,module默认为THIS_MODULE.
在初始化了路由表,缓存队列,同时创建了与用户空间通信的套接字后,接下来就是注册钩子函数,用于路由使用

nf_register_hook(&kaodv_ops[]),struct nf_hook_ops结构主要用于处理NF_INET_PRE_ROUTING,NF_INET_LOCAL_OUT和NF_INET_POST_ROUTING等钩子的地方,具体可参考http://www.cnblogs.com/liushaodong/archive/2013/02/26/2933593.html

5个链:

NF_IP_PRE_ROUTING:数据包进入路由表之前

NF_IP_LOCAL_IN:通过路由表后目的地为本机

NF_IP_FORWARD:通过路由表后,目的地不为本机

NF_IP_LOCAL_OUT:由本机产生,向外转发

NF_IP_POST_ROUTING:发送到网卡接口之前。


4个表:

filter,nat,mangle,raw,默认表是filter(没有指定表的时候就是filter表)。

          filter:一般的过滤功能

          nat: 用于nat功能(端口映射,地址映射等)

          mangle: 用于对特定数据包的修改

          raw:优先级最高,设置raw时一般是为了不再让iptables做数据包的链接跟踪处理,提高性能

无论那个链,都由kaodv_hook函数处理。

kaodv_hook,首先判断ip header是否为空,如果是空的,则直接交给上层处理,否则获取udp header,判断是否为aodv控制信息,如果是的话,还判断信号质量问题,如果质量不好,直接扔弃,否则更新路由表信息,然后上传上层。如果不是aodv控制信息(RREQ,RREP,RERR等),则获取输入设备(输出设备)的接口地址和广播地址信息。如果是广播地址,多播地址,直接上传,return NF_ACCEPT,

接下来处理三个链的数据packet

NF_INET_PRE_ROUTING:如果是网关节点,协议是自定义的IPPROTO_MIPE,目的节点是本节点,则需要解包,如果节点不是网关节点,packet是本地产生的或者是发送给本节点的,则直接上传。如果不是到本节点的packet,则查询路由表,是否有到目的节点的路由,如果没有到目的节点的路由,则向用户空间程序发送kaodv_netlink_send_rerr_msg(PKT_INBOUND, iph->saddr, iph->daddr, in->ifindex);然后扔掉当前这个packet.如果找到了到目的节点的路由条目,首先判断flags,是否需要修复,如果需要的话,则向用户空间发送repair信息,kaodv_netlink_send_rt_msg(KAODVM_REPAIR, iph->saddr, iph->daddr);如果需要修复这个路由条目的话,当前的数据packet先进入数据缓存队列kaodv_queue_enqueue_packet(skb, okfn);(okfn是是个函数指针,当所有的该HOOK点的所有登记函数调用完后,转而走此流程,执行okfn指向的函数).这里其返回NF_STOLEN,其意思就是由这个数据packet已经被钩子函数处理过了,上面不用管,不要继续传送这个packet,意思就是说,这个packet会放在缓存队列中,由往后的一些程序处理,不再上传其他层了。由用户空间发送netlink信息,如果KAODV_QUEUE_SEND发送,通过函数kaodv_queue_set_verdict(KAODV_QUEUE_SEND, m->dst);

(这一部分应该要改,如果我们使用地理信息进行转发,必须要计算下一跳节点,那一个适合转发,所以这里应该要缓存队列)

如果该路由不需要修复,则直接交给上层(可能转发,因为在这里判断了到目的节点的路由是否存在)

NF_INET_LOCAL_OUT:本地报文流出路由前执行,如果不存在到目的节点的路由,或者路由需要修复的情况下,首先判断数据缓存队列中有没有关于该目的节点的数据packet,如果有的话,表示已经发送RREQ进行路由请求了,如果没有,则向用户空间通信,发起RREQ路由请求,同时该缓存数据packet进入缓存队列中。如果路由条目有KAODV_RT_GW_ENCAP,使能网关聚合(分片功能吗?还是说每个输出的数据packet都要修改ip header,加入min_ipedr_enc),然后执行ip_route_me_harder(skb, RTN_LOCAL),重新路由一次。

NF_INET_POST_ROUTING://路由后的报文流出前执行,这里只是更新一下路由条目的信息

三个钩子函数理解完后,如果注册钩子函数失败,进行对应的处理。

剩下的就是处理设备信息,dev_get_by_name(&inti_net, ifname[i])获取设备信息


最后,创建/proc/net/kaodv,用于读取kaodv的相关信息,包括信号质量阈值,pkts dropped ,最近的一次qual值,以及网关模式。

除了module_init(kaodv_init);外,还有module_exit(kaodv_exit);这个函数就是处理模块卸载后的善后操作,包括接口信息清除,注销钩子函数,移除/proc/net/kaodv ,/proc/net/kaodv_expl ,/proc/net/kadov_queue这些文件,同时注销netlink的事件链。

以上还是自己初步理解aodv的内核模块,应该有不少出错的地方,往往再慢慢修正,写这个博文,帮助自己学习记忆奋斗




  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
AODV(Ad hoc On-Demand Distance Vector)是一种用于自组织无线网络中的路由协议,它是一种基于距离向量的协议。AODV协议的主要特点是在需要时才建立路由,而不是提前建立所有可能的路由。这种按需路由的方式可以减少网络中的路由开销,并且适用于动态变化的网络拓扑。 Matlab是一种高级的数值计算和科学编程语言,它提供了丰富的工具箱和函数库,用于数据分析、算法开发、模型建立等。在Matlab中,可以使用Simulink工具箱进行系统建模和仿真。 ZigBee是一种低功耗、短距离无线通信技术,它基于IEEE 802.15.4标准,并且专门设计用于低速率、低功耗的无线传感器网络。ZigBee网络可以支持多种应用场景,如智能家居、工业自动化、物联网等。 关于AODV、Matlab和ZigBee的相关问题: 1. AODV协议的工作原理是什么? 2. 在Matlab中如何使用Simulink进行系统建模和仿真? 3. ZigBee网络有哪些特点和应用场景? 4. AODV协议与其他路由协议相比有什么优势? 5. Matlab中有哪些工具箱和函数库可以用于数据分析和算法开发? 6. ZigBee网络中的节点如何进行通信和协调工作? 7. 如何在Matlab中实现AODV协议或者ZigBee网络的仿真模型? 8. ZigBee网络中的安全性如何保障? 9. AODV协议在无线传感器网络中的应用有哪些? 10. Matlab中有哪些工具可以用于无线通信系统的性能评估和优化?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值