初始化部分的流程
nexthop_list_init(); 初始化下一跳列表,主要用来保存下一跳的信息,确定ack的请求机会
gw_list_init(); 初始化网关列表
routecache_init(); 初始化路由缓存
reqtable_init(); 初始化路由请求表,记录收到的路由请求的信息
rtsmbuffer_init(); 初始化重发缓冲区,保存发出数据中,需要ack回复的数据报的信息
sendbuffer_init(); 初始化发送缓冲区 ,临时存储 发送路由请求之后,受到路由应答请求之前,发送的数据报
dsr_stat_init(); 初始化统计信息
init_packet_queue(); 初始化用户空间队列
对全局变量 ipq_queue_t q 进行初始化,
注册一个处理netfilter队列的函数 netfilter_receive,一旦有数据进入队列就调用,做两件事情:
1.调用ipq_enqueue函数(收到的包和发出的包都由他加入到q队列中,进入的包有dsr头,而发出的包没有dsr头,所以在程序中使用了两次switch 来吧接受的发送的udp包添加的q中)
发出的hello包,info设置为空,根据不同的协议头,把元素加入到不同的list中
接受到的数据包,info字段是由netfileter自己填写的
2.唤醒dsr进程。
startup_dsr(); 创建DSR进程,负责处理用户空间队列的数据报
注册pre_route local_out gw_post_route3个钩子 ,gw_post_route为最后一个被调用的钩子
pre_route 钩子
1如果发现数据包中dsrhdr的头部需要ack标志为1,则直接发送一个ack回复,不进入用户空间排队。
2如果是ack数据包,也就是下游节点返回的ack应答,然后进入dsr_in_ack_op_handler中进行处理,之前的判断已经没有必要了,不过还是按照从前的习惯保留了。其中在dsr_in_ack_op_handler中调用rtsmbuffer_ack_del函数,这个函数用来根据ack回复时间动态调整ack超时,这是和从前dsr最大的区别:
1 如果是数据包,则直接去掉dsr头,返回netfilter
2 其他类型的数据包,则加入用户队列 (返回NF_QUEUE)
加入队列的数据包,有netfitlerreceive调用packet_enqueue来完成,并触发dsr进程,然后再由packet_in和packet_out进行处理
dsr_local_out流程
如果是自己给自己的,则直接返回
如果是发往外网段的直接返回
其他的数据报全部返回到用户空间队列排队。加入队列的数据包,有netfitlerreceive调用packet_enqueue来完成,并触发dsr进程,然后再由packet_in和packet_out进行处理
dsr进程流程
循环从用户空间队列中取出元素 (iqp_dequeue)
{
进入的数据报 ,调用packet_in
发出的数据报,调用packet_out
}
packet_in 的流程
循环处理dsr头部字段
如果是DSR_SRC_OPT :调用dsr_src_opt_handler ,
如果DSR_IN_OPT,调用dsr_in_src_opt_handler处理:
如果dsrhdr标志位中需要ack为1,则发送一个ack
如果DSR_FORWARD_OPT,调用dsr_forward_src_opt_handler
1重新设置接受地址为下一跳地址,源地质为本节点地址;
2重新设置nexthop_info_entry中下一跳的ack请求时间,即:
if_in_nexthop_list判断转发的包的目的地址是否在下一跳得列表中。
Get_nexthop_natime来获得请求下一个跳节点ack的时间。从nexthop_info_entry 中得到最近一次从下一收到的ack时间。改变Nexthop_info_entry中的标志位,需要ack ,计算下一次需要ack的时间;
3 修改ip头目的地址为本节点地址,源地址为本节点地址
如果是DSR_REQ_OPT ,调用dsr_req_opt_handler
如果是DSR_IN_OPT ,则调用dsr_in_req_opt_handler,
1首先处理路由信息,添加从本节点到路由请求发起源的路由信息。
2再次判断是否为网关请求,然后make_and_send_dsr_reply 回复一个网关应答,否则回复一般的请求 同样是使用make_and_send_dsr_reply
3 修改ip头目的地址为本节点地址
如果是DSR_FORWARD_OPT dsr_forward_req_opt_handler
1判断是否收到过这个请求,如果收到过,则返回,否则继续
2处理路由信息,添加从本节点到路由请求发起源的路由信息
3然后针对网关修改,首先查找本的路由网关列表,没有则转发网关请求:iph->daddr = BCAST;
4如果本节点网关列表不为空,则还是make_and_send_dsr_reply来发送回复,将本地有的网关路由发送给请求节。
如果是DSR_REP_OPT ,调用dsr_rep_opt_handler
如果是DSR_IN_OPT, 则dsr_in_rep_opt_handler
首先先把添加本地路由信息,然后添加网关列表,然后处理发送缓冲区的数据,这个缓冲区的数据,是在make_dsr_source_route_option中调用sendbuffer_insert添加的。
如果是DSR_FORWARD_OPT, 则调用dsr_forward_rep_opt_handler ,
首先将reply信息中自己需要的路由信息提取,添加本地路由信息,如果是网关发现应答,然后则提取网关路由,并添加网关列表
如果是DSR_ERR_OPT ,则dsr_err_opt_handler
如果DSR_IN_OPT dsr_in_err_opt_handler
如果是网关错误,则删除网关列表,
删除路由列表
如果DSR_FORWARD_OPT dsr_forward_err_opt_handler
如果是网关错误,则删除网关列表,
删除路由列表
循环结束
如果数据包是给自己的,则从dsr头部恢复真正的源地址和目的地址(针对网关设计的),而后去掉dsr头部,然后返回nf_accept
否则,则直接由自己转发,返回nf_stolen
重新注入netfilter架构:nf_reinject()
paket_out 流程:
调用了make_and_send_dsr_data_packet进行处理 具体过程:
1如果hoplist是空 则调用make_dsr_source_route_option ,在这个函数中,首先比较目的地址是否为本网段,如果不是本网段则需要查找本地网关列表
如果没有网关信息,则发起网关发现:gateway_discovery()
否则 检查到网关/内网地址由,如果没有路由,则发起路由请求,将发送的数据暂时保存在发送缓冲区中,【在收到路由请求应答之后来发送】
总结一下make_dsr_sour_route_option 的功能,就是检查网关信息和路由信息,没有相关信息则发起路由请求,把要发送的数据存到发送缓冲区中
2如果hoplist不为空 则 调用make_dsr_source_route_opt 直接将hoplist复制给scropt的hoplist.
3 ,填写dsrhdr的头部信息
4.获取下一跳的地址 填写ip头的目的地址
5.对nexthop_info_entry中的ack请求时间进行修改,并根据条件修改dsr 需要dsr头部的需要ack标志位。
6.dsr_merge_opt_two合并dsr头和源路由选项,并发送insert_dsr_stuff_and_send
在insert_dsr_stuff_and_send中 又调用dsr_send_packet,而后在dsr_send_packet中
调用了rtsmbuffer_insert来插入发送缓冲区一个记录
回到packet_out,然后返回一个NF_STOLEN
网关节点的钩子调用处理过程
说明几个钩子
dsr的 nat
dsr_pre_route 优先级最高 pre_route 优先级低于dsr_pre_route
pre_route ,本在发出之前的 localout 优先级高于gw_local_out
gw_local_out 上线之前
第一部分 ,从网关受到发往外网段的数据报:
首先调用dsr_pre_route ,进行各种头部处理,然后恢复ip头,交付给netfilter.
这时候nat的pre_route 被调用,nat负责转换原地质为网关地址,记录内外对应的ip信息和段口号,返回netfilter,然后在发出是掉用localout 转换目标地址,返回给netfilter,
此时gw_local_out 由于也是挂在local_out处,优先级低,所以在nat的localout结束后会被调用,察看是不是由内网发给内网的,不是则直接返回nf_accept,由此一个外发的数据报处理完毕。
第二部分 ,从外网发给内网的
首先由dsr_pre_route处里,由于外网进入的是原始的数据报,所以直接返回 ,再次有nat的preroute捕获,进行原地址的变换,转为网关地质,经过内外对应的iptable,再local-out出 转换目标地址为内网结点地址,然后gw_local_out 再次截获,发现是由外网发到内网段的,则进行处理调用make_and_send_dsr_data_packet,转为dsr协议可以识别的包,发送出去
本文详细介绍了DSR路由协议的初始化流程,包括网关和下一跳列表的初始化、路由缓存和请求表的建立、数据包处理机制等。在数据包处理中,重点讨论了DSR头部字段的处理,如DSR_SRC_OPT、DSR_IN_OPT、DSR_FORWARD_OPT等,并涉及到网关发现、路由请求和应答的交互。此外,还阐述了数据包在pre_route、local_out和gw_post_route钩子函数中的处理逻辑,以及在DSR进程中的操作。
8494

被折叠的 条评论
为什么被折叠?



