第十八章 Radix树路由表

来源:互联网 发布:linux运行c程序 编辑:程序博客网 时间:2024/05/16 01:18

一、 linux的路由表结构:

  • 一共六列,分别是:
    1. 目的IP地址;
    2. 网关;
    3. 标识量:包括U G H S C L R;
    4. 引用量;
    5. 使用量,应该是通过该IP地址发送的数据量;
    6. 发往IP地址的数据包的出口接口名称。

二、 路由表查表方法:

  • 总共五个步骤:
    1. 路由表是一个树形结构,按照比特比较+掩码比较+回溯组成。
    2. 首先,从linux地址结构的包含IP地址的第一位开始,也就是比特32的地方进行比较,按照比特位为1或为0来判断是查找左子树还是右子树
    3. 直至比较到树叶,然后通过和树叶中的掩码进行与运算,如果能和树叶中的键值匹配,那么就查找成功,否则要进行回溯
    4. 回溯过程中按照每次回溯一层来进行,每次回溯到一层,就要和该层的掩码进行与操作,形成新的比较键值(如果该层有掩码的话),然后按照形成的新的键值从该层开始查找
    5. 如果查找的路由表项添加了克隆标识,那么在查找成功后要为该路由表项创建一个新的树叶,添加到路由表中

三、 路由表的数据结构

  • 五个关键的数据结构
    1. 在一个全局结构rt_tables[]数组结构中,它的每一个元素都代表一种网络协议,在Internet协议元素中,会有一个指针指向路由表树的顶点。
    2. 路由表树的顶点是一个radix_node_head结构,该结构最重要的是有三个radix_node结构,这三个结构左右两个是作为特殊节点end存在的,键值为全零和全一,中间的radix_node结构是作为首个测试比特点存在,为bit32,然后该radix_node结构中会有两个左右radix_node结构体指针来指向路由表树中的下面的孩子(下面的radix_node指针在rtentry结构中,该结构作为一个路由表表项存在),当然,孩子们也有指向父辈节点的指针,详见radix_node结构体的具体结构
    3. 在路由表树中,还有一个比较独立的结构树,根路由表树的关系还是很紧密的,就是掩码树,是用来维护路由表树的中的所有掩码的,每一个掩码只有一个备份,相同的掩码会指向同一个备份的(与掩码的对应的键值,即IP地址是不可以这样的,键值是一个键值一个备份,哪怕是相同的键值)。
    4. 在后面章节中的TCP或者UDP协议中,他们的协议控制块中会有一个route结构的东西,该结构里面有两个元素,一个是指向rtentry结构的指针,一个是指向该路由的目的地址的地址结构,该结构会在图8-24中的代码中用到(ip_output函数)
    5. rtentry结构中还有一些指向其他结构的指针,比如指向所用的ifnet结构的指针、指向该ifnet结构中ifaddr结构的指针等

四、 路由表中的各个数据结构

  • 路由表的数据结构:
    1. radix_node_head结构,这个结构没有什么特别重要的结构,主要是有三个radix_node结构作为树的root,同时还有一些函数指针对路由表树进行操作
    2. radix_node结构,这个结构中有一个union结构,因为radix_node结构既要作为树的层间节点,又要作为树叶节点,所以需要有两种不同的结构,union结构为此提供了很好的灵活性,并能节约空间。使用union结构的哪一部分是由rn_b的正负决定的,层间节点都是正的,叶子节点都是负的。(网络掩码的索引是指掩码中出现的第一个零比特的位置,如果是全零则索引值为0),我还没有太明白rn_bmask和rn_off的作用,以及他们是怎么来的。
      radix_node每一个结构都会对应一个radix_mask结构链表,因为这个radix_node结构可能会有多个掩码(因为重复键的原因)
    3. rtentry结构,第466也的图18-28中队rtentry结构有一个综合的展示,在该结构中,可以看到,有两个radix_node结构,分别作为层间比较点和路由条目值存在,还要一些独立的结构,如指向ifnet结构、ifaddr结构的指针以及指向该路由条目的网关等。

五、 路由表初始化过程:

  • 该过程比较复杂,要从内核初始化开始讲起:
    1. 在内核初始化过程中,要对各个协议域进行初始化,调用domaininit函数进行该操作,domaininit函数之前有讲,在图7-15
    2. domaininit函数会对每一个协议域调用域的初始化函数和每一个域的选路协议控制卡的首部(后面章节会进行讲解)
    3. 在选路域进行初始化的过程中,首先调用rn_init函数,该函数被用来初始化radix结构使用的一些全局变量,route_init函数会调用rtable_init函数对需要路由表的协议域的路由表进行初始化(都是用rn_inithead函数进行初始化的)注:只有选路域有域初始化函数,除了选路域和unix域其他的都有路由表初始化函数,且初始化函数均为rn_inithead函数
    4. 在rn_init函数中,也会调用rn_inithead函数,这里调用rn_inithead函数的作用是初始化掩码树

六、 对于各个函数的具体流程没有特别需要关注的,只需要从前面知道每一个函数的作用即可
七、 对于含有重复键的,第一个键中的rn_dupedkey指针会指向重复键的首地址,如果键的掩码不一样,则会有多个radix_mask结构,否则一个就够了
八、 rn_match函数,在internet协议中,是rnh_matchaddr函数,他将被rtalloc1函数调用(而rtalloc1函数将被rtalloc函数调用),函数的执行流程为:1.从树的顶端开始搜索,直到到达与查找键的比特相应的叶子。检测该叶子,看能否得到一个精确的匹配2.检测该叶节点,看是否能得到匹配的网络地址3.如果不行就回溯。
其中,rn_match函数会调用rn_search函数搜索路由表的字数,来返回找到的节点

0 0