LINUX邻居子系统(一)

邻居子系统是linux网络协议栈中非常庞大的一块,也是比较混乱复杂的一块,不过有一点感觉挺好玩的就是

它不涉及太多具体协议的内容,所以阅读起来还不算太复杂

而且它很多时候自成一个小小的系统运转(所以才叫子系统),不需要外界太多的管理(ARP,ND等协议的管理),这也是它的一个特色。

不过感觉它也承担了一部分第二层的功能(二层协议首部的封装)

它嵌入在网络层和数据链路层之间(但是又不能把它叫做LLC--逻辑链路控制),可以对上和对下提供一个统一的接口,让两层间的通信变的透明。当然这里面有很大一部分原因得归功于地址解析协议(ARP)

注:这个ARP和ARP协议不是一个东西,所有的能够将L3地址(一般都是逻辑地址)到L2地址(一般选物理地址为数据链路层的地址)的转换的都称作地址解析协议。

弄懂它有助于理解协议栈整体过程。


说明:主要的参考资料来源---

(1)《Understand Linux Kernel Internel》

(2)《Linux内核源码剖析-TCP/IP实现》

(3)linux内核源码--我使用的版本是3.2.4

注:还是建议去买个正版书,一个是好做笔记,另外一个感觉别人写书不容易


开篇点题,什么是邻居子系统?------可以略过不看,感觉说的不是太好

答:这个在《Understand Linux Kernel Internel》中花费了许多笔墨介绍,还举了很多例子给与说明(见第26章)。

个人感觉也没那么复杂:大致意思就是L3的是逻辑地址,L2的是物理地址,需要做的就是实现这两个地址的映射。

举个简单的例子:比如我要给寄出一个包裹到国外,对方的地址就是一个逻辑地址,但是我不可能直接就交到对方手上,我需要做的第一件事情就是看以下附近有没有什么邮局,邮局就是我的一个“邻居关系”,而且它是可以帮助我把包裹送到国外的唯一渠道,那我要做的就是查到邮局的地址,然后把这个包裹送到邮局,让它帮忙。做如下等价:

收件人地址=逻辑地址

邮局地址=物理地址

两者同时具备,这个包裹就可以正确送达了。

注:其实这就是ARP协议做的功能

注2:把它做成邻居子系统的原因就是,网络不可能只有IPV4,其他的协议也需要地址解析,如果为每个单独开发,有很多重复劳动,做一个通用结构就可以减少这些劳动了

注3:可能后面东西会比较零散,个人将很多感觉一开始学习不需要的细节(如初始化,删除等)给略过的原因,先掌握全貌,然后再细致的一个个看,这样可能会简单很多


1、纵览:邻居子系统的框架

框架图(见《Understand Linux Kernel Internel》图26-5):


图 1-1 邻居子系统框架图

这个图这么来看:

(1)中间的一块就是邻居子系统

(2)看中间那块最上部,Generic neighbouring interface(VFT),它为上层协议提供了一个统一的输出接口(其实就是neigh->output()),第三层协议在封装好报文后,不需要考虑自身是什么协议类型,直接使用邻居子系统的输出函数,它会自动帮你弄好发送的工作。

(3)看中间那块最下部,Generic neighbouring interface(VFT),它为下层提供的也是一个统一的接口(其实就是dev_queue_xmit()),下层协议只需要处理从dev_queue_xmit()出来的数据就可以了。

(4)看中间那块的中部,可以看到ARP和ND,ARP是为IPV4设计的地址解析协议,而ND(neighbour detect)则是为IPv6设计的。这些地址解析协议可以说是“嵌入”在邻居子系统里面,但是又可以自由灵活的拆卸,非常方便。

还有一点需要注意的,可以看到每个地址解析协议还有各自的缓存(cache),这个是实现的原因,管理方便,搜索迅速。以后会慢慢看到这个缓存的样貌的。

(5)看右方虚线框内,是不是很奇怪?不奇怪就跳过后面内容。这里是这样的,为了加速数据包的发送速度,会将路由表和邻居缓存进行绑定,这个绑定其实就是吧邻居缓存中的每个项的结构体嵌入路由表中的一个路由项中,这样报文在查找到路由以后,其实也相当于已经在邻居子系统中查到了缓存,减少了查找的次数。这样在进入邻居子系统后的处理流程就很短。

注:路由查表工作发生在第四层,TCP协议在建立链接过程中就会把报文需要的路由项保存在套接字结构中了。而udp协议因为不是面向协议,在没有调用connect的情况下会每次都查找路由,这个查找动作发生在udp_sendmsg()尾部



2、先看看数据结构框架(见《Understand Linux Kernel Internel》图27-2):

注:图太大,截图不好弄,结果很模糊,另外如果觉得这个图太复杂可以参考《Linux内核源码剖析-TCP/IP实现》图17-1,那个要清晰很多


图2 -1邻居子系统,数据框架图

最开始看这张图,感觉这么来看要好一些:

(1)邻居子系统中主要用到的数据结构有

  • struct neigh_table
  • struct neigh_statistics
  • struct neighbour
  • struct hhcache
  • struct pneigh_entry
  • struct neigh_parms

注:中间颜色很深的区域的几个结构可以不去关注,他们和邻居子系统的关系不是太大。

(2)struct neigh_table : 邻居表,每个地址解析协议就会创建这样的一个表,如图中画的,这里有一张nd_table和一张arp_table,分别对应ND协议和ARP协议。!!!这个表中就包含了所有所有的数据成员。

注:所有的邻居表组织成链表的形式方便管理,但是两个表中间其实没有什么关系,他们单独维护一个邻居表而已。

(3)struct neighbour : 邻居项,邻居项代表一个邻居。邻居项用哈希表(散列表)+链表链的组织方式(这种方式在内核中随处可见),最后struct neigh_table的hash_bucket成员就指向这个哈希表的表头。

注:可以看到每个邻居项都会有一个hh字段指向一个struct hh_cache(这个是什么后面介绍),这里需要说明的是图中画的也不准确,因为有多个neighbour指向同一个hh_cache的时候。(貌似说错了)

注2:需要关注以下neighbour中的ops字段,这个字段很重要,后面慢慢讲

(4)struct hh_cache : 这个字段存的就是封装好的二层协议头部。如下图(见《Understand Linux Kernel Inter

  • 8
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值