linux网络协议栈(四)链路层 (3)邻居子系统ARP

2024-05-09 22:32

本文主要是介绍linux网络协议栈(四)链路层 (3)邻居子系统ARP,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

4.3、邻居子系统+ARP:

4.3.1、什么是邻居:

所谓邻居就是二层直连的两个主机,如A与B直连或者A与B通过二层交换机连接,都是邻居。邻居子系统的作用是就是实现L3地址和L2地址的映射关系。

邻居子系统本身只实现一个通用架构,具体实现按照具体的L3协议和L2协议确定,如对于IPV4/ethernet,ARP协议就是邻居子系统的实现内容,对于IPV6/ethernet则是ND协议,对于其他的L3协议和L2协议还会有其他的协议。事实上理解了邻居子系统,也就理解了ARP或其他L2.5协议。

在详细描述邻居子系统之前,首先仔细感受下它到底的用途是什么,在输入报文需要转发,以及输出报文的处理,在其路由缓存条目的路由结果dst_entry中的output方法都会设置为ip_output函数,output方法是离开L3层的处理方法,也就是说无论输入报文需要转发还是输出报文,都要调用ip_output函数离开L3层进入L2层,该函数逻辑如下图:


注意记录出接口的操作,这是非常重要的一个容易被忽略的地方,接下来是函数ip_finish_output,它的主要任务是处理分帧,关于分帧详见第五章,接下来它会调用函数ip_finish_output2,在这里将根据路由缓存条目绑定的邻居(未绑定邻居无法发送)的情况,选择发送方式,首次发送将选择慢速方式发送,之后则按快速方式发送,如下图:


路由结果dst_entry的hh,回看5.3.2.2节中,在实际把路由缓存条目加入路由缓存表时对调用函数arp_bind_neighbour创建邻居条目,即dst->neighbour,所以第一次发送时调用dst->neighbour->output方法发送,这是慢速发送。

上面的内容重点不在细节,而是感受到邻居系统的作用:由路由缓存条目绑定的邻居条目,确定发送报文的目的MAC,并调用相应的发送方法发送报文。事实上理解了这一点已经差不多够了,邻居子系统的细节是为了更好的理解链路层处理。

由前面已经知道,邻居子系统的作用是绑定L3地址和L2地址的对应关系,最终发送报文必须知道给哪个主机的链路层发送,典型如以太网,在二层是按MAC地址转发,所以必须确定目的地的MAC地址,否则报文无法发到目的地,而所谓邻居,就是那么目的地,作为终端的主机可能没有多少邻居,但可以看下作为路由器网关的设备,如下图是192.168.99.1的一个路由器网关设备的arp缓存情况:


实际条目是上图的10倍以上,可以感受到邻居数目的众多。

那么ARP和邻居是什么关系?不同的链路层协议使用不同的L2.5层协议,而邻居子系统是一个通用的子系统,为所有类似ARP的L2.5层协议封装了一个通用架构。邻居子系统不仅仅提供最基本的二三层地址绑定关系,还实现通用的处理机制,如邻居条目状态机、用户接口、超时机制等,其他L2.5层协议如ARP都是在邻居子系统架构下实现。

4.3.2、邻居子系统详述:

邻居子系统最核心的内容是邻居状态机,在讨论邻居状态机之前首先描述一些必要的内容:

1、邻居表

每个L2.5层协议都会调用函数neigh_table_init在邻居子系统中注册自己的邻居表,以管理自己的邻居条目,对于ARP协议是全局变量arp_tbl;

2、邻居条目:


目前无需理解全部字段的含义,只需知道如下信息:

每个路由缓存条目都会绑定的邻居条目就是这样的一个数据结构,其中的邻居的目的MAC地址是struct hh_cache结构体成员hh,

对应的接口是成员dev,

发送报文的方法还是就是其中的output成员,

每个存在着的邻居条目都会处在邻居子系统状态机的某一个状态,由nud_state指示,

如果发送了请求后,无法正常收到邻居的应答,会触发邻居子系统的重传机制,成员probes记录已重传次数,

若当前无法发送报文则会把报文先缓存在队列arp_queue中,

primary_key存储的是路由缓存条目的IP地址。

4.3.2.1、邻居子系统状态机:
了解上述内容后,下图是邻居子系统状态机:


1、在创建新的邻居条目,这是在创建新的路由缓存条目时调用arp_bind_neighbour函数创建的邻居条目,创建邻居条目最终会调用函数neigh_create,无需过于纠缠其实现细节,重点要知道在此处把路由缓存条目中的下一跳网关成员rt_gateway作为IP地址赋给邻居条目的primary_key成员,把输出接口成员dev赋给邻居条目的dev成员,初始状态为NUD_NONE;

2、收到了ARP请求报文,并且是发给自己的(通过路由信息的路由类型字段),那么状态变为NUD_STALE,解析出对方的IP地址和MAC地址,创建这个发送者的邻居条目;

3、收到了ARP请求报文,但不是发给自己的(通过路由信息的路由类型字段),这就是ARP代理(事实上这是邻居子系统通用功能,所有L2.5层协议都支持L2.5层代理),路由器网关必须行使的功能,状态变为NUD_STALE,它将把报文放入邻居代理队列(proxy_queue),启动代理队列定时器,该定时器处理将给发送者发送回应,即行使ARP代理功能;

4、收到了ARP回复报文,并且是发给自己的(通过报文的类型字段skb->pkt_type),那么状态升为NUD_REACHABLE;

5、在NUD_NONE情况下,发送报文,由于路由结果dst_entry中还没有邻居(ARP)缓存,即hh_cache成员还未赋值,属于第一次发送,由函数neigh_resolve_output处理,将按慢速发送处理,所谓慢速发送就是要首先确保所要发送的邻居条目有效(由函数neigh_event_send确定是否有效)然后才发送,如果有效,那么将在路由缓存条目中缓存二层包头并填充skb的二层包头并发送,从此路由缓存结果dst_entry中就记录了邻居缓存即目的MAC地址,从此以后就可以走快速发送方式,即直接由邻居缓存中记录的目的MAC地址填充报文并立即发送,注意发送函数是dev_queue_xmit,它将走到相应的网卡驱动;状态升为NUD_INCOMPLETE,与此同时,将启动定时器,检查是否收到了回复;

6、在NUD_INCOMPLETE情况下,只有在NUD_NONE状态下发送报文才会进入此状态,并且同时启动了定时器,邻居定时器处理(neigh_timer_handler)将会检查状态依然是NUD_INCOMPLETE (因为收到回复是异步的,比如arp_process收到给本机的回复则走第4步,状态就会升为NUD_REACHABLE)的邻居条目,检查其重传次数是否到限,限制值是由邻居条目创建时的邻居参数决定的(不是重点),若到限则状态降为NUD_FAILED,否则继续重传;

7、在NUD_INCOMPLETE情况下,如果在重传次数到限之前收到了邻居的回复,则状态升为NUD_REACHABLE,并且把MAC地址记录在路由缓存条目的hh_cache中,标记本邻居条目今后可走快速发送路径,则报文发送时直接由路由缓存条目的hh_cache填充包头发送;

8、在第2、3步中由于接受到ARP请求所以创建邻居条目并且状态为NUD_STALE,在定时器处理中,检查其是否超时(闲置时间过长),若超时则状态降为NUD_FAILED;

9、在NUD_STALE下,如果要发送ARP请求,则状态报文NUD_DELAY,如果超时时间内未收到回复则状态报文NUD_PROBE即重传状态,否则状态升为NUD_REACHABLE;

10、在NUD_REACHABLE状态下,如果闲置时间过长(老化),该邻居条目状态降为NUD_STALE;

11、在NUD_REACHABLE状态下,发送ARP请求,状态变为NUD_DELAY,如果超时时间内未收到回复则状态报文NUD_PROBE即重传状态,否则状态依然为NUD_REACHABLE;

12、在重传状态NUD_PROBE下,如果超时并且重传次数到限,则状态降为NUD_FAILED,如果收到了邻居的回复,则状态升为NUD_REACHABLE,如果超时但重传次数还未到限,并且也未收到邻居的回复,则继续重传,状态不变;

13、在NUD_FAILED状态下,这里的邻居条目都将被删除;

4.3.3、ARP:

ARP是用于L3为IPV4和L2为以太网的L2.5层协议,它绑定的是IPV4地址和MAC地址,注意ARP条目不是永远存在,超时会老化掉,否则需要保存的ARP缓存条目太多了。

所有ARP报文按照以太网类型0x0806注册在内核的链路层处理中(proc/net/ptype),其hook处理函数为arp_rcv,该函数在进行ARP处理前netfilter之后调用arp_process,这是ARP报文的实际处理的地方,事实上该函数就是在根据收到的ARP报文的类型调用相关的邻居子系统方法,创建/删除/更新邻居条目及其状态,行使包括ARP代理在内的ARP协议功能;ARP报文发送接口函数为arp_send,在构造arp报文之后调用arp_xmit,它将进行ARP处理后netfilter之后调用dev_queue_xmit实际发送报文。

在proc文件系统中可通过查看proc/net/arp查看本机当前的arp缓存条目,对于IPV4和以太网的设备来说事实上就是邻居条目。

下图是结合ARP的邻居子系统的流程图:


关于ARP子系统的一些细节,后续再补充,个人认为其细节不是重点,对于ARP或者说对于邻居子系统重在理解原理和解决一些可能出现的问题,后续对ARP防控多做总结

这篇关于linux网络协议栈(四)链路层 (3)邻居子系统ARP的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/974683

相关文章

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

Linux samba共享慢的原因及解决方案

《Linuxsamba共享慢的原因及解决方案》:本文主要介绍Linuxsamba共享慢的原因及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux samba共享慢原因及解决问题表现原因解决办法总结Linandroidux samba共享慢原因及解决

新特性抢先看! Ubuntu 25.04 Beta 发布:Linux 6.14 内核

《新特性抢先看!Ubuntu25.04Beta发布:Linux6.14内核》Canonical公司近日发布了Ubuntu25.04Beta版,这一版本被赋予了一个活泼的代号——“Plu... Canonical 昨日(3 月 27 日)放出了 Beta 版 Ubuntu 25.04 系统镜像,代号“Pluc

Linux安装MySQL的教程

《Linux安装MySQL的教程》:本文主要介绍Linux安装MySQL的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux安装mysql1.Mysql官网2.我的存放路径3.解压mysql文件到当前目录4.重命名一下5.创建mysql用户组和用户并修

Linux上设置Ollama服务配置(常用环境变量)

《Linux上设置Ollama服务配置(常用环境变量)》本文主要介绍了Linux上设置Ollama服务配置(常用环境变量),Ollama提供了多种环境变量供配置,如调试模式、模型目录等,下面就来介绍一... 目录在 linux 上设置环境变量配置 OllamPOgxSRJfa手动安装安装特定版本查看日志在

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

Linux系统之dns域名解析全过程

《Linux系统之dns域名解析全过程》:本文主要介绍Linux系统之dns域名解析全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、dns域名解析介绍1、DNS核心概念1.1 区域 zone1.2 记录 record二、DNS服务的配置1、正向解析的配置