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-基础知识3

打包和压缩 zip 安装zip软件包 yum -y install zip unzip 压缩打包命令: zip -q -r -d -u 压缩包文件名 目录和文件名列表 -q:不显示命令执行过程-r:递归处理,打包各级子目录和文件-u:把文件增加/替换到压缩包中-d:从压缩包中删除指定的文件 解压:unzip 压缩包名 打包文件 把压缩包从服务器下载到本地 把压缩包上传到服务器(zip

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

Linux服务器Java启动脚本

Linux服务器Java启动脚本 1、初版2、优化版本3、常用脚本仓库 本文章介绍了如何在Linux服务器上执行Java并启动jar包, 通常我们会使用nohup直接启动,但是还是需要手动停止然后再次启动, 那如何更优雅的在服务器上启动jar包呢,让我们一起探讨一下吧。 1、初版 第一个版本是常用的做法,直接使用nohup后台启动jar包, 并将日志输出到当前文件夹n

[Linux]:进程(下)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:Linux学习 贝蒂的主页:Betty’s blog 1. 进程终止 1.1 进程退出的场景 进程退出只有以下三种情况: 代码运行完毕,结果正确。代码运行完毕,结果不正确。代码异常终止(进程崩溃)。 1.2 进程退出码 在编程中,我们通常认为main函数是代码的入口,但实际上它只是用户级

VC网络协议

// PCControlDlg.cpp : 实现文件//#include "stdafx.h"#include "PCControl.h"#include "PCControlDlg.h"#include "afxdialogex.h"#ifdef _DEBUG#define new DEBUG_NEW#endif// 用于应用程序“关于”菜单项的 CAboutDlg 对话框#ifde

【Linux】应用层http协议

一、HTTP协议 1.1 简要介绍一下HTTP        我们在网络的应用层中可以自己定义协议,但是,已经有大佬定义了一些现成的,非常好用的应用层协议,供我们直接使用,HTTP(超文本传输协议)就是其中之一。        在互联网世界中,HTTP(超文本传输协议)是一个至关重要的协议,他定义了客户端(如浏览器)与服务器之间如何进行通信,以交换或者传输超文本(比如HTML文档)。